When I write data the to the database via a simple call to save then the call returns without error, but nothing is saved to the database.
If I simply switch out the Yugabyte driver for the vanilla PostgreSQL driver, then everything works as expected. So I suppose there is some error in my configuration or setup code, although it is copied verbatim from the tutorial code.
Perhaps there is some Commit or Flush mechanism in the Yugabyte code, which needs to be activated somehow? I am purely relying on Spring’s built-in mechanisms in that regards.
My dependencies:
implementation ‘com.yugabyte:spring-data-yugabytedb-ysql:2.3.0’
runtimeOnly ‘org.postgresql:postgresql’
runtimeOnly ‘com.yugabyte:jdbc-yugabytedb:42.3.4’
Hi @dorian_yugabyte ,
as I said, the exact same code works with the PostgreSQL driver, so it cannot be that I’m not committing, unless there is a special “commit behavior” implemented in the YugabyteDB driver.
But what I found in the meantime is that if I comment out this code (which comes from the example application in the tutorial), then everything works as expected:
@Bean
public TransactionManager transactionManager(DataSource dataSource) {
return new YugabyteTransactionManager(dataSource);
}
So apparently the YugabyteTransactionManager has a special behavior and if I just leave in the default one from Spring, then everything works fine, even with the YSQL driver.
There are a couple of things we wanted to investigate, and Recently we made changes to jdbc-yugabytedb driver to shade all the Postgres related JDBC classes which is causing the ClassNotFoundException for PSQLException in YugabyteDialectResolver hence we will need to add Postgres driver as well on the class. Looks like You’ve already added the Postgresql driver dependency in your spring app.
After making the above, App could insert the record into the employee table using employeeRepository, which is of type com.yugabyte.data.jdbc.repository.YsqlRepository. Just wanted to confirm whether you’re using the code snippet in the step 3 of the docs.
is it possible if you can send us the code snippet or the spring app for troubleshooting? Thanks
I have a larger application and tried to extraxt the essential bits into a small example app, but must have done something wrong. Now the application does not start due to a java.lang.NoClassDefFoundError: org/springframework/data/util/TypeScanner. I cannot find the difference to my larger application, which does start without any problems.
That would be super, thanks. My larger app is still running fine and for the life of me I can’t find the difference to this example app. But once we get it running, we might be able to reproduce the actual problem I was experiencing with my larger app.
@ulim Getting some build errors with the sample app, and I’m not familiar with how to resolve them. can you please let me know how I can resolve this Lombok error in Gradle. See the error trace below -
Nikhils-MacBook-Pro:yugabytedb-example nikhil$ ./gradlew bootRun
> Task :generateEffectiveLombokConfig FAILED
Execution optimizations have been disabled for task ':generateEffectiveLombokConfig' to ensure correctness due to the following reasons:
- In plugin 'io.freefair.gradle.plugins.lombok.LombokBasePlugin' type 'io.freefair.gradle.plugins.lombok.tasks.LombokConfig' property 'lombokClasspath' cannot be resolved: Failed to resolve imported Maven boms: nexus.isys.de: nodename nor servname provided, or not known. Reason: An input file collection couldn't be resolved, making it impossible to determine task inputs. Please refer to https://docs.gradle.org/7.5.1/userguide/validation_problems.html#unresolvable_input for more details about this problem.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':generateEffectiveLombokConfig'.
> Could not resolve all files for configuration ':lombok'.
> Could not resolve org.projectlombok:lombok:1.18.22.
Required by:
project :
> Could not resolve org.projectlombok:lombok:1.18.22.
> Could not get resource 'https://nexus.isys.de/repository/jstage-maven-group/org/projectlombok/lombok/1.18.22/lombok-1.18.22.pom'.
> Could not GET 'https://nexus.isys.de/repository/jstage-maven-group/org/projectlombok/lombok/1.18.22/lombok-1.18.22.pom'.
> nexus.isys.de
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings
Execution optimizations have been disabled for 1 invalid unit(s) of work during this build to ensure correctness.
Please consult deprecation warnings for more details.
BUILD FAILED in 1s
1 actionable task: 1 executed
Ok, I’ve removed Lombok, it wasn’t strictly necessary, please pull and try again.
FWIW, here’s how I built it with Java 17:
./gradlew build
./gradlew composeBuild (this build the YugabyteDB Image)
docker-compose up (wait for DB to come up)
./gradlew bootRun (to start the application)
In my case it fails with java.lang.ClassNotFoundException: org.springframework.data.util.TypeScanner
After this, I was able to build the app successfully.
I hit the same issue java.lang.ClassNotFoundException: org.springframework.data.util.TypeScanner. Looks like there is a version mismatch between the different spring data projects.
I believe org.springframework.data:spring-data-cassandra:4.0.0 is the culprit. SDC-4.0.0 is looking for TypeScaner which is only available in spring-data-commons:3.0.0 version. However, the spring boot version is at spring-boot:2.6.14 which doesn’t have TypeScanner API
You will need to update your code from org.springframework.data:spring-data-cassandra:4.0.0 to org.springframework.data:spring-data-cassandra so that spring boot will bring in the compatible SD-cassandra version.
After making this change, I was able to get the app running -
2023-01-13 17:31:09.022 INFO 44877 --- [ s0-admin-0] c.d.o.d.i.c.t.Clock : Using native clock for microsecond precision
2023-01-13 17:31:09.247 INFO 44877 --- [ s0-io-0] c.d.o.d.i.c.c.ChannelFactory : [s0] Failed to connect with protocol DSE_V2, retrying with DSE_V1
2023-01-13 17:31:09.252 INFO 44877 --- [ s0-io-1] c.d.o.d.i.c.c.ChannelFactory : [s0] Failed to connect with protocol DSE_V1, retrying with V4
2023-01-13 17:31:09.327 INFO 44877 --- [ s0-io-2] c.d.o.d.a.c.u.Uuids : PID obtained through native call to getpid(): 44877
2023-01-13 17:31:09.435 WARN 44877 --- [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-01-13 17:31:09.665 INFO 44877 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2023-01-13 17:31:09.681 INFO 44877 --- [ restartedMain] o.s.b.w.e.t.TomcatWebServer : Tomcat started on port(s): 8300 (http) with context path ''
2023-01-13 17:31:09.688 INFO 44877 --- [ restartedMain] e.YugabyteApplication : Started YugabyteApplication in 3.579 seconds (JVM running for 9.016)
If you pull my newest changes and start the app, you will see a log output like this:
INFORMATION: Created ApiKey: ApiKey{id=84be3081-d3c0-4053-a4c7-3e44f89ea53c, keyHash=CZOtlCTTpgjZ}
INFORMATION: ApiKey found in DB: true
This means that an ApiKey (our example object) was created and afterwards it was read successfully from the database.
Now, if you go to the class YugabyteConfiguration you will find a commented out section at the end. Comment that section in, so you have this:
@Bean
public TransactionManager transactionManager(DataSource dataSource) {
return new YugabyteTransactionManager(dataSource);
}
Now restart the application. The log output will now show that the ApiKey was created, but could not be read out again. Thus, it was not actually saved. You can verify this by checking the database with some SQL tool that the ApiKey was indeed not created.
Jan 20, 2023 2:19:12 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Jan 20, 2023 2:19:13 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Jan 20, 2023 2:19:15 PM example.DataPreloader createKeyspace
INFO: Created Keyspace: example
Jan 20, 2023 2:19:15 PM example.DataPreloader createStandardApiKey
INFO: Created ApiKey: ApiKey{id=2487ad40-e026-4e1c-a22e-3c817da50310, keyHash=cWTzfHszMLYv}
Jan 20, 2023 2:19:15 PM example.DataPreloader createStandardApiKey
INFO: ApiKey found in DB: true
and I see the records in the DB as well -
nikhil$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44a20027d0c4 yugabytedb-example:latest "/sbin/tini -- /usr/…" 24 seconds ago Up 19 seconds 0.0.0.0:5433->5433/tcp, 6379/tcp, 7100/tcp, 0.0.0.0:7000->7000/tcp, 0.0.0.0:9000->9000/tcp, 7200/tcp, 9100/tcp, 10100/tcp, 11000/tcp, 0.0.0.0:9042->9042/tcp, 12000/tcp yugabytedb-example
Nikhils-MacBook-Pro:yugabyte-2.17.0.0 nikhil$ ./bin/ysqlsh -d example -U joe -h 192.168.86.116
Password for user joe:
ysqlsh (11.2-YB-2.17.0.0-b0)
Type "help" for help.
example=> \dt
Did not find any relations.
example=> \dt
List of relations
Schema | Name | Type | Owner
--------+--------+-------+-------
public | apikey | table | joe
(1 row)
example=> select * from apikey;
id | key_hash
--------------------------------------+--------------
2487ad40-e026-4e1c-a22e-3c817da50310 | cWTzfHszMLYv
(1 row)