-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Session not being flushed upon jta commit
PostPosted: Fri Feb 01, 2008 12:14 am 
Newbie

Joined: Tue Jan 29, 2008 2:30 am
Posts: 7
Hi,

I've tried posting a couple of times (difference subjects) with little (i.e. no) response. so hopefully I get some better luck this time ....

I've a application that is using Hibernate as a JPA provider. Spring is creating the entity manager and also invoking the reference to a WeblogicJtaTransactionManager. I'm deploying the app to a WebLogic 10 server.

The code being run is:
Code:
   @Transactional
   public void poll() {
      Collection<GtTradeLeg> waitingTradeLegs = gtTradeLegDao.findWaiting();
      Collection<GtTradeLeg> allowableTradeLegs = filterChain.filter(waitingTradeLegs);
      Collation<GtTrade, GtTradeLeg> tradeCollation = tradeLegCollator.collate(allowableTradeLegs);
      incomingDealPublisher.publish(tradeCollation.getCollated());
      Collection<GtTradeLeg> waitingMultiLegDeals = tradeCollation.getUncollated();
      gtTradeLegDao.delete(from(waitingTradeLegs).exclude(waitingMultiLegDeals));
   }


The general jist is that a list gets read from the database, gtTradeLegDao.findWaiting(). The list is processed. Some elements are placed onto a JMS queue and then deleted from the database gtTradeLefgDao.delete(...).

All of this works just fine, except that the Hibernate Session is never being flushed, and this the deletion is not being written to the database.

I have tested the flushing by placing another gtTradeLegDao.findWaiting() after the delete(...), which forces the flush. When I do this the deletion is written out correctly. So, this indicates that the Session is not calling flush when the JTATransaction commits.

My transaction/persistence wiring looks as follows:

Code:
  <bean id="jpaVendorAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:databasePlatform="org.hibernate.dialect.HSQLDialect"/>

  <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="datasource"
    p:jpaVendorAdapter-ref="jpaVendorAdapter"
    p:jpaPropertyMap-ref="jpaPropertyMap"/>

    <bean
      id="transactionManager"
      class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/>
   
    <util:map id="jpaPropertyMap">
      <entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
      <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WeblogicTransactionManagerLookup"/>
      <entry key="hibernate.current_session_context_class" value="org.hibernate.context.JTASessionContext"/>
    </util:map>
     
    <tx:annotation-driven />


And here is the log trace on debug mode, which clearly highlights that the transaction is being used:

Code:
DEBUG WebLogicJtaTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@17bb56d]
DEBUG WebLogicJtaTransactionManager - Creating new transaction with name [com.cbaib.gm.gtout.poller.Poller.poll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG TransactionSynchronizationManager - Initializing transaction synchronization
DEBUG WebLogicJtaTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@c40bf8]
DEBUG WebLogicJtaTransactionManager - Participating in existing transaction
DEBUG EntityManagerFactoryUtils - Opening JPA EntityManager
DEBUG EntityManagerFactoryUtils - Registering transaction synchronization for JPA EntityManager
DEBUG TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@edd37b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@91e124] to thread [DefaultQuartzScheduler_Worker-4]
DEBUG SQL - select gttradeleg0_.temp_id as temp1_0_, gttradeleg0_.action as action0_, gttradeleg0_.autocover as autocover0_, gttradeleg0_.broker_code as broker4_0_, gttradeleg0_.ccy1_amount as ccy5_0_, gttradeleg0_.ccy1_buy_sell as ccy6_0_, gttradeleg0_.ccy1_code as ccy7_0_, gttradeleg0_.ccy2_amount as ccy8_0_, gttradeleg0_.ccy2_code as ccy9_0_, gttradeleg0_.customer_account as customer10_0_, gttradeleg0_.dealt_ccy_code as dealt11_0_, gttradeleg0_.delivery_type as delivery12_0_, gttradeleg0_.cd_deal_id as cd13_0_, gttradeleg0_.forward_settle_date as forward14_0_, gttradeleg0_.insert_time as insert15_0_, gttradeleg0_.inverted_rate_flg as inverted16_0_, gttradeleg0_.entry_type as entry17_0_, gttradeleg0_.login_id as login18_0_, gttradeleg0_.modification_level as modific19_0_, gttradeleg0_.optional_settlement_date as optional20_0_, gttradeleg0_.revision_date as revision21_0_, gttradeleg0_.saved_swap_id as saved22_0_, gttradeleg0_.security_group as security23_0_, gttradeleg0_.settlement_date as settlement24_0_, gttradeleg0_.spot_date as spot25_0_, gttradeleg0_.status as status0_, gttradeleg0_.swap_id as swap27_0_, gttradeleg0_.trade_date as trade28_0_, gttradeleg0_.trade_number as trade29_0_, gttradeleg0_.internal_external_trade as internal30_0_, gttradeleg0_.deal_rate as deal31_0_, gttradeleg0_.deal_type as deal32_0_ from GT_TRAD_DETAILS_FXTG gttradeleg0_
DEBUG WebLogicJtaTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@1a6699c]
DEBUG WebLogicJtaTransactionManager - Participating in existing transaction
DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@edd37b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@91e124] bound to thread [DefaultQuartzScheduler_Worker-4]
DEBUG SQL - select smalltrade0_.smll_i as smll1_1_ from SMLL smalltrade0_
DEBUG WebLogicJtaTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@63ef4d]
DEBUG WebLogicJtaTransactionManager - Participating in existing transaction
DEBUG TransactionSynchronizationManager - Bound value [org.springframework.jms.connection.JmsResourceHolder@1ab7a89] for key [weblogic.jms.client.JMSXAConnectionFactory@9b212f] to thread [DefaultQuartzScheduler_Worker-4]
DEBUG JmsTemplate - Executing callback on JMS Session: weblogic.jms.client.WLSessionImpl@f9f3b2
DEBUG JmsTemplate - Sending created message: ObjectMessage[null,com.cbaib.gm.gtout.model.GtTrade@19fa]
DEBUG WebLogicJtaTransactionManager - Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@15c46dd]
DEBUG WebLogicJtaTransactionManager - Participating in existing transaction
DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@edd37b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@91e124] bound to thread [DefaultQuartzScheduler_Worker-4]
DEBUG TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@edd37b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@91e124] bound to thread [DefaultQuartzScheduler_Worker-4]
DEBUG WebLogicJtaTransactionManager - Triggering beforeCommit synchronization
DEBUG WebLogicJtaTransactionManager - Triggering beforeCompletion synchronization
DEBUG TransactionSynchronizationManager - Removed value [org.springframework.orm.jpa.EntityManagerHolder@edd37b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@91e124] from thread [DefaultQuartzScheduler_Worker-4]
DEBUG TransactionSynchronizationManager - Removed value [org.springframework.jms.connection.JmsResourceHolder@1ab7a89] for key [weblogic.jms.client.JMSXAConnectionFactory@9b212f] from thread [DefaultQuartzScheduler_Worker-4]
DEBUG WebLogicJtaTransactionManager - Initiating transaction commit
DEBUG WebLogicJtaTransactionManager - Triggering afterCommit synchronization
DEBUG WebLogicJtaTransactionManager - Triggering afterCompletion synchronization
DEBUG TransactionSynchronizationManager - Clearing transaction synchronization


I obviously don't want to call gtTradeLegDao.findWaiting() to force a flush, it should happen when the transaction is committed. Any help???

Cheers

Ryan


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 03, 2008 9:08 pm 
Newbie

Joined: Tue Jan 29, 2008 2:30 am
Posts: 7
After some more intensive research I've managed to discover the following:

1. It's not possible to set the value hibernate.transaction.flush_before_completion, this is automatically overriden to 'false' by EJB3Configuration.

- This means that the session is not flushed by the org.hibernate.transaction.CacheSynchronization that is registered with the JTATransaction.

2. Spring's org.springframework.orm.jpa.EntityManagerFactoryUtils$EntityManagerSynchronization makes a call to close the EntityManager. This is used when Spring retrieves an EntityManager from Hibernate on a transactional basis.

3. Using a hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactory ensures that Hibernate believes it is participating in a JTA transaction.

4. Using Spring's org.springframework.orm.jpa.JpaTransactionManager makes an explicit call to org.hibernate.ejb.TransactionImpl.commit(), which in turn flushes the session.

So, I'm trying to work out exactly where the responsibility of commiting (and thus flushing) a JPA Entity Manager within a container managed JTA transaction lies?

I would have thought that since Hibernate is aware of the JTA transaction, it should be able to provide its own synchronization hooks into ensuring the session is flushed upon a commit. No?

If the property hibernate.transaction.flush_before_completion was able to be set then I could ensure flushing as part of the CacheSynchronization. I can only assume this enforcement is to adhere to part of the JPA spec?

Am I missing a configuration setting somewhere?

Any comments would be great?

Thanks

Ryan


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 03, 2008 9:50 pm 
Newbie

Joined: Tue Jan 29, 2008 2:30 am
Posts: 7
Finally managed to resolve my issue (after trawling the source).

I ended up with the following configuration:

Code:
  <util:map id="jpaPropertyMap">
    <entry key="javax.persistence.transactionType" value="jta"/>
    <entry key="hibernate.transaction.factory_class" value="org.hibernate.ejb.transaction.JoinableCMTTransactionFactory"/>
    <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WeblogicTransactionManagerLookup"/>
    <entry key="hibernate.current_session_context_class" value="org.hibernate.context.JTASessionContext"/>
  </util:map>


Its listed as Spring config, but the hibernate properties all need to be set. I think the 2 key ones that I was missing was the javax.persistence.transactionType=jta and org.hibernate.transaction.factory_class=org.hibernate.ejb.transaction.JoinableCMTTransactionFactory.

These ensured that 1. I was using JTA (without the javax.persistence.transactionType hibernate was still configured to use RESOURCE_LOCAL transactions) and 2. That the JoinableCMTTransaction was able to provide the synchronization hook that committed the transaction.

Hope this helps someone?!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 05, 2008 6:38 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
weird,
Code:
    <entry key="javax.persistence.transactionType" value="jta"/>
    <entry key="hibernate.transaction.factory_class" value="org.hibernate.ejb.transaction.JoinableCMTTransactionFactory"/>

those are the default when building an Hibernate EntityManager from the standard (JPA) APIs and configuration files (persistence.xml) if you use a jta datasource. I guess Spring does play around forcing you to be explicit.

especially, nobody should be aware of JoinableCMTTransactionFactory in their configuration, it's bad and exposes some of the internals of HEM.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 08, 2008 4:40 am 
Newbie

Joined: Tue Jan 29, 2008 2:30 am
Posts: 7
Hmmm ....

Nice to know that they are defaults, but I'm guessing that they would be set if you use the
Code:
<jta-data-source>...</jta-data-source>

in your persistence.xml. However, I didn't specify a datasource and instead injected a datasource into Spring's EntityManagerFactory. Which I guess in turn injects it into the necessary transactional EntityManager.

So, I would guess that if you dont specify a datasource in persistence.xml then the jta defaults wouldnt be set. So, from this point of view I guess Hibernate never has a chance of setting any other defaults unless it can somehow inspect the datasource that Spring injects?

Nonetheless, it was nice to eventually solve the problem.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 09, 2008 1:34 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
As a matter of that there is a standard way to inject a DS using the PersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo info, Map)

PersistenceUnitInfo.getJtaDataSource() returns a DS to the persistence provider.

Spring does not seem to follow that path though.

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.