Hibernate + Jetty + Narayana: okay with a ConnectionProvider, but not with a jta-data-source

34 views
Skip to first unread message

Olivier Cailloux

unread,
Apr 24, 2021, 4:50:48 PM4/24/21
to narayana-users
Dear forum,

Following an insightful conversation here some time ago (for which I warmly thank Ondra again), I could configure Narayana to work together with Hibernate, Jetty, JPA, JTA, and the like. The working project involves implementing Hibernate’s ConnectionProvider to provide it with connections supplied by Narayana’s TransactionalDriver.

Now I would like to get rid of this implementation of ConnectionProvider and rather use the standard JTA properties in persistence.xml, if possible.

But replacing, in persistence.xml, the hibernate.connection.provider_class by the standard jta-data-source where I indicate the data source that Narayana connects to (an H2 provided DB) makes the project fail (says that no table is found).

I believe Hibernate actually does not use Narayana’s TransactionalDriver when configured in that way. But, according to the log, Hibernate correctly uses the JBossStandAloneJtaPlatform implementation as Jta support, so I thought Hibernate would realize that it needs to tell Narayana to connect to H2 and not try to connect directly to H2.

Should I indicate in jta-data-source a JNDI name of a Narayana DataSource, instead of H2? But how to do that? It seems that Narayana provides only an implementation of Driver and not of DataSource. I suppose there is a reason for this choice, and thus, that I am doing something wrong.

A sample project where the problem can be reproduced is here: https://github.com/oliviercailloux/sample-jetty. The master branch fails whereas the TCP branch works. The only difference is in the persistence.xml file, as can be seen here: https://github.com/oliviercailloux/sample-jetty/compare/TCP..master/.

Here is a relevant part of the log produced when running the master branch (which fails), thus using a jta-data-source.
22:06:46.308 [qtp1948863195-17] DEBUG o.h.e.t.j.p.i.JtaPlatformInitiator - No JtaPlatform was specified, checking resolver
22:06:46.309 [qtp1948863195-17] DEBUG o.h.e.t.j.p.i.JtaPlatformResolverInitiator - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
22:06:46.345 [qtp1948863195-17] INFO  o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform]
22:06:46.358 [qtp1948863195-17] DEBUG org.hibernate.SQL - drop table if exists Item CASCADE
22:06:46.371 [qtp1948863195-17] DEBUG org.hibernate.SQL - create table Item (id integer generated by default as identity, name varchar(255), primary key (id))
22:06:46.386 [qtp1948863195-17] DEBUG o.h.query.spi.NamedQueryRepository - Checking 0 named HQL queries
22:06:46.386 [qtp1948863195-17] DEBUG o.h.query.spi.NamedQueryRepository - Checking 0 named SQL queries
22:06:46.396 [qtp1948863195-17] DEBUG o.h.internal.SessionFactoryRegistry - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@5dde1572
22:06:46.396 [qtp1948863195-17] DEBUG o.h.internal.SessionFactoryRegistry - Registering SessionFactory: 4c2b62a7-202b-40c7-99ef-3ff69e322f5c (<unnamed>)
22:06:46.396 [qtp1948863195-17] DEBUG o.h.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
22:06:46.449 [qtp1948863195-17] DEBUG o.h.r.t.b.j.i.JtaTransactionCoordinatorImpl - Hibernate RegisteredSynchronization successfully registered with JTA platform
22:06:46.468 [qtp1948863195-17] DEBUG o.h.s.internal.StatisticsInitiator - Statistics initialized [enabled=false]
22:06:46.484 [qtp1948863195-17] DEBUG org.hibernate.engine.spi.ActionQueue - Executing identity-insert immediately
22:06:46.487 [qtp1948863195-17] DEBUG org.hibernate.SQL - insert into Item (id, name) values (null, ?)
22:06:46.493 [qtp1948863195-17] DEBUG o.h.e.jdbc.spi.SqlExceptionHelper - could not prepare statement [insert into Item (id, name) values (null, ?)]
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" non trouvée
Table "ITEM" not found; SQL statement:
insert into Item (id, name) values (null, ?) [42102-200]

And here is a relevant part of the log produced when running the TCP branch (which succeeds), thus configuring the persistence.xml file with a ConnectionProvider implementation and no jta-data-source.
22:25:53.859 [qtp1948863195-18] DEBUG o.h.e.t.j.p.i.JtaPlatformInitiator - No JtaPlatform was specified, checking resolver
22:25:53.860 [qtp1948863195-18] DEBUG o.h.e.t.j.p.i.JtaPlatformResolverInitiator - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
22:25:53.865 [qtp1948863195-18] INFO  o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform]
22:25:53.870 [qtp1948863195-18] DEBUG org.hibernate.SQL - drop table if exists Item CASCADE
22:25:53.877 [qtp1948863195-18] DEBUG org.hibernate.SQL - create table Item (id integer generated by default as identity, name varchar(255), primary key (id))
22:25:53.896 [qtp1948863195-18] DEBUG o.h.query.spi.NamedQueryRepository - Checking 0 named HQL queries
22:25:53.896 [qtp1948863195-18] DEBUG o.h.query.spi.NamedQueryRepository - Checking 0 named SQL queries
22:25:53.905 [qtp1948863195-18] DEBUG o.h.internal.SessionFactoryRegistry - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@701a90e6
22:25:53.908 [qtp1948863195-18] DEBUG o.h.internal.SessionFactoryRegistry - Registering SessionFactory: 390b5545-32be-4526-8912-7bdfa02a3818 (<unnamed>)
22:25:53.909 [qtp1948863195-18] DEBUG o.h.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
22:25:53.973 [qtp1948863195-18] DEBUG o.h.r.t.b.j.i.JtaTransactionCoordinatorImpl - Hibernate RegisteredSynchronization successfully registered with JTA platform
22:25:53.997 [qtp1948863195-18] DEBUG o.h.s.internal.StatisticsInitiator - Statistics initialized [enabled=false]
22:25:54.018 [qtp1948863195-18] DEBUG org.hibernate.engine.spi.ActionQueue - Executing identity-insert immediately
22:25:54.022 [qtp1948863195-18] DEBUG org.hibernate.SQL - insert into Item (id, name) values (null, ?)
22:25:54.029 [qtp1948863195-18] DEBUG com.arjuna.ats.jdbc - ARJUNA017007: Connection will be closed now. Indications are that this db does not allow multiple connections in the same transaction conn1: url=jdbc:h2:mem: user=SA
22:25:54.036 [qtp1948863195-18] DEBUG o.h.id.IdentifierGeneratorHelper - Natively generated identity: 1
22:25:54.036 [qtp1948863195-18] DEBUG o.h.r.j.i.ResourceRegistryStandardImpl - HHH000387: ResultSet's statement was not registered
22:25:54.046 [qtp1948863195-18] DEBUG o.h.r.j.i.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterStatement
22:25:54.055 [qtp1948863195-18] DEBUG c.a.a.j.c.a.ContextPropagationAsyncHandler - Class io.smallrye.reactive.converters.ReactiveTypeConverter is not available on classpath. Handling of asynchronous types in @Transactional methods could not work properly. Consider to add java artifacts 'org.eclipse.microprofile.reactive-streams-operators.microprofile-reactive-streams-operators-api', 'org.reactivestreams:reactive-streams' and  'io.smallrye.reactive:smallrye-reactive-converter-api' to your classpath
22:25:54.058 [qtp1948863195-18] DEBUG o.h.e.i.AbstractFlushingEventListener - Processing flush-time cascades
22:25:54.059 [qtp1948863195-18] DEBUG o.h.e.i.AbstractFlushingEventListener - Dirty checking collections
22:25:54.064 [qtp1948863195-18] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
22:25:54.064 [qtp1948863195-18] DEBUG o.h.e.i.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
22:25:54.065 [qtp1948863195-18] DEBUG o.h.internal.util.EntityPrinter - Listing entities:
22:25:54.068 [qtp1948863195-18] DEBUG o.h.internal.util.EntityPrinter - io.github.oliviercailloux.jetty.Item{name=MyItem dated 2021-04-24T22:25:51.321367+02:00[Europe/Paris], id=1}
22:25:54.068 [qtp1948863195-18] DEBUG o.h.r.j.i.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterStatement
22:25:54.071 [qtp1948863195-18] DEBUG o.h.e.t.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
22:25:54.077 [qtp1948863195-18] DEBUG o.h.r.j.i.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
22:25:54.157 [qtp1948863195-17] DEBUG o.h.r.t.b.j.i.JtaTransactionCoordinatorImpl - Hibernate RegisteredSynchronization successfully registered with JTA platform
22:25:54.162 [qtp1948863195-17] DEBUG o.h.q.c.internal.CriteriaQueryImpl - Rendered criteria query -> select generatedAlias0 from Item as generatedAlias0
22:25:54.180 [qtp1948863195-17] DEBUG o.h.h.i.QueryTranslatorFactoryInitiator - QueryTranslatorFactory: org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory@2614ba15
22:25:54.214 [qtp1948863195-17] DEBUG o.h.h.i.ast.QueryTranslatorImpl - parse() - HQL: select generatedAlias0 from io.github.oliviercailloux.jetty.Item as generatedAlias0

Notice the line “ARJUNA017007: Connection will be closed now. Indications are that this db does not allow multiple connections”. It does not appear in the previous case, which lets me believe that Hibernate tries to bypass Narayana in the previous case.

Thanks a lot for any help in understanding how to obtain a configuration as clean and standard-compliant as possible!

Ondra Chaloupka

unread,
Apr 30, 2021, 11:59:29 AM4/30/21
to narayana-users
Hi Oliver,

thanks for reaching us. Sorry for a delayed response. I don't have a direct experience with Jetty but we worked with Tomcat. The integration code (if I haven't shared it with you yet) is at https://github.com/web-servers/narayana-tomcat

You are right I assume you'll be needed to provide the Transaction Driver connection somehow. Otherwise the connection is not enlisted to transaction. The information that Hibernate is capable to work with JTA means that there are linked the Synchronization calls and that it can find the transaction manager. It's not (unfortunately) the Hibernate that manages the lifecycle of the XA processing. That's the application server. When there is a standalone application then there is needed some code processing the XA enlistment - usually some pooling library, I think IronJacamar or Agroal or the Transaction Driver.

With the Transaction Driver there could be a help to check the Narayana quickstarts where is shown some guts of the transaction processing. I think it could be helpful to check the standalone and hibernate https://github.com/jbosstm/quickstart/tree/master/jta-and-hibernate-standalone

I'm can't run your code currently so I'm not able to share any more insight.

Ondra
Reply all
Reply to author
Forward
0 new messages