karaf-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Timothy Ward <tim.w...@paremus.com>
Subject Re: Antw: Re: OSGi Transaction control fails with hibernate
Date Thu, 14 Sep 2017 10:29:40 GMT

> On 14 Sep 2017, at 10:46, Guillaume Nodet <gnodet@apache.org> wrote:
> 
> 
> 
> 2017-09-14 11:40 GMT+02:00 Timothy Ward <tim.ward@paremus.com <mailto:tim.ward@paremus.com>>:
> Hi Alexander,
> 
> As has been discussed on the Aries lists before, I have no problem with someone creating
a separate implementation of the Transaction Control service which leverages the OSGi JTA
Service Specification. The reason that the current implementation doesn’t do this is twofold:
> 
> By embedding a transaction manager the current Tx Control implementation can avoid the
javax.transaction split package from the JVM. This makes the implementation easier to use
and deploy because the user doesn’t need to mess around with the boot class path, or worry
about what JTA version is available
> By embedding a transaction manager the current Tx control implementation can rely on
specific behaviours of the transaction manager that it uses. This means that the Tx control
implementation can support the last resource gambit and XA recovery.
> Fwiw, as I already indicated, the pax-transx project provides a layer solving those problems,
in addition of providing additional features and pluggability.
> 
> Would you be interested to incorporate it in Tx Control ?

This is not something that I have the time to do, but another implementation of a transaction
control service with a pluggable transaction manager would be a great addition.

> 
> Guillaume
>  
> 
> If this is a proof of concept project then are you able to share it somewhere (e.g. GitHub)?
I’d like to help you get to the bottom of the NPE that you’re seeing as I don’t think
it should be possible for that to be happening!
> 
> Finally - yes the Aries user list is the best place to talk about this, but I don’t
want to move the conversation myself as I don’t know whether you’re registered for that
list, and don’t want you to miss my replies.
> 
> Regards,
> 
> Tim
> 
> 
>> On 14 Sep 2017, at 07:53, <alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>>
<alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>> wrote:
>> 
>> Hi Tim.
>> 
>> I'm using the 2.6.1 version of aries jpa support already. Normal transaction control
with blueprint and @Transactional annotation was working fine.
>> 
>> To have better control over startup dependencies and cope with disappearing and appearing
services during runtime we invest some time in a Proof-Of-Concept for switching over to declarative
services (DS). Everything works fine so far - even restful services for DS with cxf-dosgi
works fine. Last bit to get it working is transaction management. With DS, the @Transactional
annotation is not working anymore due to the lack of interceptors with DS.
>> 
>> What do you think of the idea that tx-control should pick up a JTS Transaction manager
from the service registry instead of creating an own one with new operator which is in fact
tightly coupled. To implement loose coupling here we should add a factory that may be configurable
in the factory config file.
>> 
>> BTW, should we switch the discussion to aries group still?
>> 
>> Best, Alexander.
>> 
>> 
>> 
>> Hi Alexander,
>> 
>> That looks like it should be fine - what version of Aries JPA are you using? There
were some fixes made to Aries JPA in 2.4.0 to add support for JPA 2.1 configuration properties
which are needed by the transaction control implementation, and I think that there were then
more fixes in 2.5.0 which are needed to get XA working with Hibernate. 2.6.1 is the latest
release version.
>> 
>> Regards,
>> 
>> Tim
>> 
>> 
>>> On 13 Sep 2017, at 15:42, alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>
wrote:
>>> 
>>> Thanks Tim for the update.
>>> 
>>> I tried the approach with providing a factory config in karaf.dir/etc/org.apache.aries.tx.control.jpa.xa.cfg
with config as:
>>> osgi.unit.name <http://osgi.unit.name/>=DSContext2
>>> osgi.jdbc.driver.class=org.h2.Driver
>>> url=jdbc:h2:mem:article
>>> user=sa
>>> password=
>>> 
>>> whilst having a mininmal persistence.xml like:
>>> <persistence-unit name="DSContext" >
>>>         <properties>
>>>             <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"
/>
>>>         </properties>
>>>     </persistence-unit>
>>> 
>>> (without the dialect I see another exception; Access to DialectResolutionInfo
cannot be null when 'hibernate.dialect' not set).
>>> 
>>> Now I get further in the process (transaction enlistment works) but when actually
accessing the database, the entity manager throws a NPE while trying to open the connection.
In JPAEntityManagerProviderFactoryImpl.EnlistingDataSource.enlistedConnection() while calling
supplier.call, the supplier.delegate member is null:
>>> 
>>> org.osgi.service.transaction.control.TransactionException: There was a problem
getting hold of a database connection
>>>         at org.apache.aries.tx.control.jpa.xa.impl.JPAEntityManagerProviderFactoryImpl$EnlistingDataSource.enlistedConnection(JPAEntityManagerProviderFactoryImpl.java:241)
~[?:?]
>>>         at org.apache.aries.tx.control.jpa.xa.impl.JPAEntityManagerProviderFactoryImpl$EnlistingDataSource.getConnection(JPAEntityManagerProviderFactoryImpl.java:193)
~[?:?]
>>>         at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
~[?:?]
>>>         at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:35)
~[?:?]
>>>         at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:99)
~[?:?]
>>>         at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:129)
~[?:?]
>>>         at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.connection(StatementPreparerImpl.java:47)
~[?:?]
>>>         at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
~[?:?]
>>>         at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
~[?:?]
>>>         at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
~[?:?]
>>>         at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1940)
~[?:?]
>>>         at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
~[?:?]
>>>         at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
~[?:?]
>>>         at org.hibernate.loader.Loader.doQuery(Loader.java:932) ~[?:?]
>>>         at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
~[?:?]
>>>         at org.hibernate.loader.Loader.doList(Loader.java:2615) ~[?:?]
>>>         at org.hibernate.loader.Loader.doList(Loader.java:2598) ~[?:?]
>>>         at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
~[?:?]
>>>         at org.hibernate.loader.Loader.list(Loader.java:2425) ~[?:?]
>>>         at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
~[?:?]
>>>         at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153)
~[?:?]
>>>         at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:991)
~[?:?]
>>>         at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:147)
~[?:?]
>>>         at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
~[?:?]
>>>         at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1459)
~[?:?]
>>>         at com.brodos.ds.persistence.h2.TestRepositoryImpl.lambda$checkHealth$0(TestRepositoryImpl.java:47)
~[?:?]
>>>         at org.apache.aries.tx.control.service.common.impl.AbstractTransactionControlImpl$TransactionBuilderImpl.doWork(AbstractTransactionControlImpl.java:161)
[241:tx-control-service-xa:0.0.3]
>>>         at org.apache.aries.tx.control.service.common.impl.AbstractTransactionControlImpl$TransactionBuilderImpl.required(AbstractTransactionControlImpl.java:84)
[241:tx <https://maps.google.com/?q=84)+%5B241:tx&entry=gmail&source=g>-control-service-xa:0.0.3]
>>>         at org.apache.aries.tx.control.service.common.impl.AbstractTransactionControlImpl.required(AbstractTransactionControlImpl.java:263)
[241:tx-control-service-xa:0.0.3]
>>>         at com.brodos.ds.persistence.h2.TestRepositoryImpl.checkHealth(TestRepositoryImpl.java:44)
[160:com.brodos.example.ds.DSContext-infrastructure:1.0.0.SNAPSHOT]
>>>         at com.brodos.ds.service.impl.MainHealthCheck.checkHealth(MainHealthCheck.java:29)
[209:com.brodos.example.ds.DSContext-service:1.0.0.SNAPSHOT]
>>>         at com.brodos.ds.application.boundary.impl.HealthCheckImpl.checkHealth(HealthCheckImpl.java:37)
[212:com.brodos.example.ds.DSContext-application:1.0.0.SNAPSHOT]
>>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
>>>         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
~[?:?]
>>>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
~[?:?]
>>>         at java.lang.reflect.Method.invoke(Method.java:497) ~[?:?]
>>>         at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:189) [85:org.apache.cxf.cxf-rt-frontend-jaxrs:3.1.12]
>>>         at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99) [85:org.apache.cxf.cxf-rt-frontend-jaxrs:3.1.12]
>>>         at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
[84:org.apache.cxf.cxf-core:3.1.12]
>>>         at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:263)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:189)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:299)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:223)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [69:javax.servlet-api:3.1.0]
>>>         at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:274)
[92:org.apache.cxf.cxf-rt-transports-http:3.1.12]
>>>         at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
[128:org.eclipse.jetty.servlet:9.3.14.v20161028]
>>>         at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584)
[128:org.eclipse.jetty.servlet:9.3.14.v20161028]
>>>         at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71)
[150:org.ops4j.pax.web.pax-web-jetty:6.0.6]
>>>         at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
[125:org.eclipse.jetty.security:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284)
[150:org.ops4j.pax.web.pax-web-jetty:6.0.6]
>>>         at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
[128:org.eclipse.jetty.servlet:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
[150:org.ops4j.pax.web.pax-web-jetty:6.0.6]
>>>         at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.Server.handle(Server.java:534) [127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
[127:org.eclipse.jetty.server:9.3.14.v20161028]
>>>         at org.eclipse.jetty.io <http://org.eclipse.jetty.io/>.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
[119:org.eclipse.jetty.io <http://org.eclipse.jetty.io/>:9.3.14.v20161028]
>>>         at org.eclipse.jetty.io <http://org.eclipse.jetty.io/>.FillInterest.fillable(FillInterest.java:95)
[119:org.eclipse.jetty.io <http://org.eclipse.jetty.io/>:9.3.14.v20161028]
>>>         at org.eclipse.jetty.io <http://org.eclipse.jetty.io/>.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
[119:org.eclipse.jetty.io <http://org.eclipse.jetty.io/>:9.3.14.v20161028]
>>>         at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
[130:org.eclipse.jetty.util:9.3.14.v20161028]
>>>         at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
[130:org.eclipse.jetty.util:9.3.14.v20161028]
>>>         at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
[130:org.eclipse.jetty.util:9.3.14.v20161028]
>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
[130:org.eclipse.jetty.util:9.3.14.v20161028]
>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
[130:org.eclipse.jetty.util:9.3.14.v20161028]
>>>         at java.lang.Thread.run(Thread.java:745) [?:?]
>>> Caused by: java.lang.NullPointerException
>>>         at org.apache.aries.tx.control.jpa.xa.impl.JPAEntityManagerProviderFactoryImpl$EnlistingDataSource.lambda$getConnection$4(JPAEntityManagerProviderFactoryImpl.java:193)
~[?:?]
>>>         at org.apache.aries.tx.control.jpa.xa.impl.JPAEntityManagerProviderFactoryImpl$EnlistingDataSource.enlistedConnection(JPAEntityManagerProviderFactoryImpl.java:230)
~[?:?]
>>>         ... 78 more
>>> 
>>> Best, Alexander
>>> 
>>> 
>>> 
>>> Hi Alexander,
>>> 
>>> So what you’re doing is passing a fully configured EntityManagerFactory to
the resource provider factory. If you create the provider this way then you are responsible
for setting up all of the EntityManagerFactory’s configuration, including how it’s going
to integrate with transaction control. For local transactions there is nothing to integrate
with , but in the general case this is actually quite hard to do, and I would advise not trying
to do it.
>>> 
>>> As you can see the EntityManagerFactory version of the provider factory <https://github.com/apache/aries/blob/ed8dbc79758766081203056cff27eb0bcbd7efb3/tx-control/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/JPAEntityManagerProviderFactoryImpl.java#L122>
does quite a bit less setup on your behalf than the configuration-driven version does <https://github.com/apache/aries/blob/ed8dbc79758766081203056cff27eb0bcbd7efb3/tx-control/tx-control-providers/jpa/tx-control-provider-jpa-xa/src/main/java/org/apache/aries/tx/control/jpa/xa/impl/XAJPAEMFLocator.java#L72>.
If you were to 
>>> provide a factory configuration for the “org.apache.aries.tx.control.jpa.xa”
pid containing “osgi.unit.name <http://osgi.unit.name/>=<your persistence unit’s
name>” and any necessary datasource configuration (i.e. that’s not coming from the
persistence xml) then you could inject the JPAEntityManagerProvider directly as a service.
>>> 
>>> More documentation about configuration-driven resources for Aries Tx-Control
is available at http://aries.apache.org/modules/tx-control/xaJPA.html#creating-a-resource-using-a-factory-configuration
<http://aries.apache.org/modules/tx-control/xaJPA.html#creating-a-resource-using-a-factory-configuration>
>>> 
>>> Another thing that probably could be done would be to look at dynamically installing
the plugin when using the EntityManagerFactoryBuilder version of the factory method. This,
however, would need a patch to Aries Transaction Control, and would still not make your existing
code work.
>>> 
>>> Regards,
>>> 
>>> Tim
>>> 
>>> 
>>>> On 13 Sep 2017, at 10:59, <alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>>
<alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>> wrote:
>>>> 
>>>> Hi Tim,
>>>> 
>>>> I use a JPAEntityManagerProviderFactory (providerFactory) which I inject
as a service reference into my repository class. 
>>>> Furthermore, I inject a EntityManagerFactory (emf) into the repository class
as well as the TransactionControl (txControl).
>>>> 
>>>> The provider Factory is created by pax-jdbc (I use hibernate).
>>>> 
>>>> This provider factory is then used to get the Entity manager like this:
>>>> 
>>>> EntityManager em = providerFactory.getProviderFor(emf, null).getResource(txControl);
>>>> 
>>>> It fails giving an exception telling that transaction cannot be joined, because
it's not open.
>>>> 
>>>> The wrapping call is like this:
>>>> txControl.build()
>>>>                 .required(
>>>>                         () -> repo.store(article));
>>>> 
>>>> Best, Alexander.
>>>> 
>>>> 
>>>> 
>>>> Hi Alexander,
>>>> 
>>>> Do you have a code example of how you’re obtaining and using the EntityManager?
There should be no usage of the OSGiJtaPlatform from the tx-control XA JPA resource provider,
which means that there’s either a bug in the resource provider, or something is misconfigured.
If you are a member of the Aries user mailing list then that would be a better place to continue
this discussion.
>>>> 
>>>> Regards,
>>>> 
>>>> Tim
>>>> 
>>>>> On 13 Sep 2017, at 09:21, Guillaume Nodet <gnodet@apache.org <mailto:gnodet@apache.org>>
wrote:
>>>>> 
>>>>> Fwiw, you should ask on the Aries mailing list, where tx-control is developed.
>>>>> 
>>>>> I've recently worked on a new project called pax-transx which provides
an abstraction layer on top of transaction managers so that some features can be accessed
in a common way.  I think this should be used in tx-control instead of wrapping the tm again
and not being flexible.
>>>>> Right now, tx-control uses its own instance of transaction manager and
there's no way around afaik, so you can't use the karaf transaction feature if you want to
use it.
>>>>> Anyway, I'd gladly support you if you go to the aries mailing list to
raise this point !
>>>>> 
>>>>> 2017-09-13 9:52 GMT+02:00  <alexander.sahler@brodos.de <mailto:alexander.sahler@brodos.de>>:
>>>>> Hello.
>>>>> 
>>>>> I'm trying to get tx-control with XA transactions running (local is working).

>>>>> I found that tx-control opens a JTA transaction using RecoveryWorkAroundTransactionManager
(derived from geronimo's TransactionManager Implementation) explicitly instead of using the
registered TransactionManager (aries in my case for karaf 4.0.9). When hibernate EntityManager
implementation tries to join the transaction it fails because it uses the TransactionManager
provided by OsgiJtaPlatform (from hibernate-osgi) which is of course the one registered in
osgi ecosystem.
>>>>> 
>>>>> I think that the tx-control implementation has to use the TransactionManager
registered with OSGi.
>>>>> 
>>>>> Has anyone got that thing ever running?
>>>>> 
>>>>> Best Alexander.
>>>>> 
>>>>> 
>>>>> 
>>>>> -- 
>>>>> ------------------------
>>>>> Guillaume Nodet
>>>>> 
>>>> 
>>> 
>> 
> 
> 
> 
> 
> -- 
> ------------------------
> Guillaume Nodet


Mime
View raw message