Spring Data YsqlRepository: Data ist not written to DB

I am using YugabyteDB via Spring Data according to the tutorial Spring Data YugabyteDB - Getting Started! | Yugabyte

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’

Many thanks in advance for any pointers!

Hi @ulim

Maybe you aren’t committing the data?

Can you show your source code for inserting and selecting the data?

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.

Hi @ulim,

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.

Here’s the example app:

@ulim I’ll go over the app and see if I can get it to run. I’ll let you know by tomorrow, if I have any progress. Thanks

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.

Just a reminder that this issue still exists. I’d like to provide a bug report, but for some reason cannot get the sample app to run.

@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

I had to update the artifactory to maven central for the build to work -

repositories {
    // maven { url "https://nexus.isys.de/repository/jstage-maven-group/" }
    mavenCentral()
}

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)

Super, many thanks. Now we can reproduce the bug.

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.

I ran the app as you explained above,

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)

That is weird. I have now added a log statement to make sure you have the right TransactionManager enabled, it looks like this:

INFORMATION: Using TransactionManager: com.yugabyte.data.jdbc.datasource.YugabyteTransactionManager

Can you confirm you’re getting that log output?