karaf-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Guillaume Nodet <gno...@apache.org>
Subject Re: Antw: Re: OSGi Transaction control fails with hibernate
Date Thu, 14 Sep 2017 09:46:00 GMT
2017-09-14 11:40 GMT+02:00 Timothy Ward <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 ?

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> <
> 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 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=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 JPAEntityManagerProviderFactor
> yImpl.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.NonContextualJdbcConnectionAcc
> ess.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.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
> [119:org.eclipse.jetty.io:9.3.14.v20161028]
>         at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
> [119:org.eclipse.jetty.io:9.3.14.v20161028]
>         at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
> [119: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=<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
>
> 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> <
> 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> 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>:
>
>> 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