question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Failed to retrieve a working connection from transactional data source

See original GitHub issue

Hello,

I have an application with two transactional data sources configured.

Only the first (default) is configured to support JPA as shown below.

datasources:
  default:
    url: jdbc:postgresql://localhost:5432/demo
    username: demo
    password: demo
    driver-class-name: org.postgresql.xa.PGXADataSource
    min-pool-size: 1
    max-pool-size: 5
  db1:
    url: jdbc:postgresql://localhost:5432/db1
    username: db1
    password: db1
    driver-class-name: org.postgresql.xa.PGXADataSource
    min-pool-size: 1
    max-pool-size: 5

jpa:
  default:
    compile-time-hibernate-proxies: true
    properties:
      hibernate:
        hbm2ddl:
          auto: none
        show_sql: true
        transaction:
          coordinator_class: jta
          jta:
            platform: JBossTS

I am encountering an issue when injecting the second data source (db1) and attempting to retrieve a connection from the data source for a standard JDBC call as shown below.

  @Inject
  @Named("db1")
  private DataSource db1DataSource;

  @Test
  void simpleJdbcTest() throws Exception {
    try (Connection connection = db1DataSource.getConnection()) {
      try (PreparedStatement statement = connection.prepareStatement("INSERT INTO demo.data (id, integer_value, string_value, date_value, timestamp_value) VALUES (?, ?, ?, ?, ?)")) {
        int value = random.nextInt();

        statement.setLong(1, System.currentTimeMillis());
        statement.setInt(2,  value);
        statement.setString(3,"New Test Data " + value);
        statement.setObject(4, LocalDate.now());
        statement.setObject(5, LocalDateTime.now());

        statement.executeUpdate();
      }
    }
  }

What is injected is a TransactionAwareDataSource.DataSourceProxy instance.

I have traced the db1DataSource.getConnection() call and the bean lookup in the TransactionAwareDataSource.DataSourceProxy.getTransactionAwareConnection method returns a TransactionalConnection$Intercepted instance.

From what I can see, the transactional database connection is not initialised and registered with the TransactionSynchronizationManager.

This causes the prepareStatement call to fail.

I traced the prepareStatement call and observed that the DataSourceUtils.doGetConnection method is invoked with allowCreate = false.

This is a problem since no existing ConnectionHolder instance exists for the data source that can be retrieved from the TransactionSynchronizationManager, and no new ConnectionHolder instance can be created and registered with the TransactionSynchronizationManager.

I tested with other calls, e.g. connection.getMetaData, and encountered the same problem.

When I use the default data source that is configured for JPA it works correctly. After Tracing, it appears that the reason it is working is that the connection is initialized and registered with the TransactionSynchronizationManager by the HibernateTransactionManager.doBegin method.

I am unfortunately not familiar enough with Micronaut to suggest the best place to initialise the connection and register it with the TransactionSynchronizationManager.

Is there some way to resolve this issue?

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
marcusportmanncommented, Aug 2, 2021

For context, I am attempting to get Micronaut to support both multiple data sources and JTA transactions. The intention is to have support for XA two-phase commit across multiple data sources and other XA resources.

I have successfully integrated Agroal, an XA compliant connection pool, and Narayana, the JTA transaction manager from JBoss. I based my implementation on the Spring JtaTransactionManager implementation. My implementation supports multiple data sources, mixing XA and non-XA data sources, and configures Narayana to support the recovery of XA transactions in the case of an application failure.

I have a sample application that demonstrates how this works and a library that provides the same capability. The library is part of an effort to migrate my Inception framework to Micronaut, which is currently based on Spring and Angular.

Sample Application: https://github.com/marcusportmann/appnaut-poc

Library: https://github.com/marcusportmann/appnaut/tree/main/src/appnaut-jta

So far, I am making good progress in porting my framework. The next challenge is enabling support for multiple JPA persistence units to allow the correct scoping of entity beans and prevent issues with application entity beans conflicting with framework entity beans with the same name.

1reaction
marcusportmanncommented, Jul 20, 2021

Unfortunately, the proposed solution did not work.

No SynchronousTransactionManager<?> instance can be injected for the non-JPA data sources.

I believe this is because of the following.

When the io.micronaut.data:micronaut-data-hibernate-jpa dependency is added it pulls in the io.micronaut.data:micronaut-data-tx-hibernate dependency.

This introduces the io.micronaut.transaction.hibernate5.HibernateTransactionManager bean, which replaces the io.micronaut.transaction.jdbc.DataSourceTransactionManager bean.

While a DataSourceTransactionManager instance is created for each DataSource instance, a HibernateTransactionManager instance is only created for each SessionFactory.

This means that if multiple data sources are configured in the application.yaml configuration file, but they are not all configured for JPA, then those data sources without JPA configuration do not have a matching SynchronousTransactionManager (HibernateTransactionManager) instance.

So, it seems that micronaut does not support using multiple JPA and non-JPA transactional datasources in a single application.

I am investigating whether I can create my own TransactionManagerFactory similar to the io.micronaut.configuration.hibernate.jpa.spring.HibernateTransactionManagerFactory in the micronaut-hibernate-jpa-spring library.

The plan is to create io.micronaut.transaction.jdbc.DataSourceTransactionManager instances for the non-JPA data sources. The only challenge I forsee is the JPA-enabled data source which I would need to skip somehow since a HibernateTransactionManager instance will already be created for this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Resolving Failed to Configure a DataSource Error - Baeldung
In this short tutorial, we'll discuss what causes and what resolves the “Failed to configure a DataSource” error on a Spring Boot project....
Read more >
How do you recover from the XA Connection errors after ... - IBM
All the in-debt transaction recovered and will shut down again. You can start the JVMs in normal mode and see if you no...
Read more >
Database Troubleshooting (Magic xpa 2.x) - Reference
Known possible causes: The number of connections allowed from Magic xpa is too low. Updates outside a transaction - updates within a transaction...
Read more >
java - Could not get JDBC Connection / Transaction is not active
The error is telling you exactly what is wrong. there is no active transaction. The fact that you define a transactionmanager doesn't mean...
Read more >
Unable to Get a Connection From a Data Source
The other option to fix the problem is to manually modify the values within <max-connections> and/or <max-time-to-wait-connection> tags in the data-sources.xml ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found