Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Question regarding TransactionProxyFactoryBean declaration

  1. #1

    Default Question regarding TransactionProxyFactoryBean declaration

    Hi all,

    I've read spring reference about using spring support for transaction management declaratively (Chapter 12), I came across the following declaration in configuration xml :

    <beans>
    ...

    <bean id="myTxManager" class="org.springframework.orm.hibernate.Hibernate TransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <bean id="myProductServiceTarget" class="product.ProductServiceImpl">
    <property name="productDao" ref="myProductDao"/>
    </bean>

    <bean id="myProductService"
    class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager" ref="myTxManager"/>
    <property name="target" ref="myProductServiceTarget"/>
    <property name="transactionAttributes">
    <props>
    <prop key="increasePrice*">PROPAGATION_REQUIRED</prop>
    <prop key="someOtherBusinessMethod">PROPAGATION_REQUIRES _NEW</prop>
    <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
    </props>
    </property>
    </bean>

    </beans>

    What I don't understand from the above declaration is when should we call & use the myProductService declaration ?

    Any help would be greatly appreciated.

    Regards,

    Setya

  2. #2
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    What I don't understand from the above declaration is when should we call & use the myProductService declaration ?
    I'll try to answer...

    The bean myProductService uses another bean myProductServiceTarget, which defines a number of operations (e.g. increasePriceA(...), increasePriceB(...)). Each of these methods may call multiple DAOs or other resources managed by the transaction manager bean, myTxManager. If you want those operations to occur within transactions (as defined by myProductService), you'd use the myProductService instead of myProductServiceTarget (which is nearly always the case).

    Typically, for a web application you would use the myProductService in a web-controller. Take a look at the samples in the Spring distribution for examples.

  3. #3

    Smile

    Quote Originally Posted by katentim
    I'll try to answer...

    The bean myProductService uses another bean myProductServiceTarget, which defines a number of operations (e.g. increasePriceA(...), increasePriceB(...)). Each of these methods may call multiple DAOs or other resources managed by the transaction manager bean, myTxManager. If you want those operations to occur within transactions (as defined by myProductService), you'd use the myProductService instead of myProductServiceTarget (which is nearly always the case).
    OK, I understand now. Thank you very much for your explanation.

  4. #4

    Default "Could not find UserTransaction in JNDI" exception

    Hi,

    Question 1:
    ========

    I define transactions as follows :

    Code:
    ...
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    	
    <bean id="target.service.research" class="com.mycompany.research.ResearchServiceImpl" lazy-init="true"/>
    
    <bean name="service.research" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager" ref="txManager"/>
       <property name="target" ref="target.service.research"/>
       <property name="transactionAttributes">
          <props>
             <prop key="save*">PROPAGATION_REQUIRED</prop>
             <prop key="delete*">PROPAGATION_REQUIRED</prop>
          </props>
       </property>
    </bean>
    
    
    <bean id="target.service.admin" class="com.mycompany.admin.AdminServiceImpl" lazy-init="true"/>
    
    <bean name="service.admin" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager" ref="txManager"/>
       <property name="target" ref="target.service.admin"/>
          <property name="transactionAttributes">
             <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
            </props>
          </property>
    </bean>
    
    ...
    When I run my application it throws the following exception:

    Code:
    ERROR (JTATransaction.java:61) - Could not find UserTransaction in JNDI
    javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:640)
    	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:243)
    	at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:280)
    	at javax.naming.InitialContext.lookup(InitialContext.java:347)
    	at org.hibernate.transaction.JTATransaction.begin(JTATransaction.java:58)
    	at org.hibernate.transaction.JTATransactionFactory.beginTransaction(JTATransactionFactory.java:53)
    	at org.hibernate.jdbc.JDBCContext.beginTransaction(JDBCContext.java:271)
    	at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1079)
    	at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:426)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:281)
    	at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:217)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:89)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
    	at $Proxy1.save(Unknown Source)
    	at com.farbeyond.dbengine.ModelSet.save(ModelSet.java:565)
    	at com.farbeyond.test.crud.TestCRUDSEditing.testCRUDSEditing(TestCRUDSEditing.java:49)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:324)
    	at junit.framework.TestCase.runTest(TestCase.java:154)
    	at junit.framework.TestCase.runBare(TestCase.java:127)
    	at junit.framework.TestResult$1.protect(TestResult.java:106)
    	at junit.framework.TestResult.runProtected(TestResult.java:124)
    	at junit.framework.TestResult.run(TestResult.java:109)
    	at junit.framework.TestCase.run(TestCase.java:118)
    	at junit.framework.TestSuite.runTest(TestSuite.java:208)
    	at junit.framework.TestSuite.run(TestSuite.java:203)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
    I believe it thinks that I'm running my application within application server, in fact I'm not.

    But when I change the definition as follows :

    Code:
    ...
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    	
    <bean id="target.service.research" class="com.mycompany.research.ResearchServiceImpl" lazy-init="true"/>
    
    <bean name="service.research" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager" ref="txManager"/>
       <property name="target" ref="target.service.research"/>
       <property name="transactionAttributes">
          <props>
             <prop key="save*">PROPAGATION_REQUIRED</prop>
             <prop key="delete*">PROPAGATION_REQUIRED</prop>
          </props>
       </property>
    </bean>
    
    <bean id="service.admin" class="com.mycompany.admin.AdminServiceImpl" lazy-init="true"/>
    
    ...
    my application runs without problem, as you can see from above definition it only works if I define transaction only for one service, no more.

    What's the problem ?


    Question 2:
    =========

    Actually class 'com.mycompany.admin.AdminServiceImpl' and class 'com.mycompany.admin.ResearchServiceImpl' derive from the same abstract class, i.e com.mycompany.base.AbstractServiceImpl in which all 'save*' and 'delete*' methods are defined.

    Since 'com.mycompany.base.AbstractServiceImpl' is an abstract class is it possible to define transaction on this class once instead of in those two descendant classes ? So that I don't have to repeatedly define transactions everytime I create classes that derive from 'com.mycompany.base.AbstractServiceImpl' and the methods (save* and delete*) are located in their parent class anyway.


    Thanks in advanced.


    Setya

  5. #5
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    Question 1: I believe it thinks that I'm running my application within application server, in fact I'm not
    In that case you need to use a product like JOTM.

  6. #6
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    Question 2: Is it possible to define transaction on this class once instead of in those two descendant classes
    Sort of - you can define an abstract bean which defines most of the transactional proxy. Your then define descendant beans for the two descendant classes.

    So that I don't have to repeatedly define transactions everytime I create classes that derive from 'com.mycompany.base.AbstractServiceImpl'
    If AbstractServiceImpl defines the services, why not just make this the concrete implementation of the service layer and use it everywhere. If you are concerned about XML proliferation, you can always use auto-wiring.

  7. #7

    Default

    Thanks for the response,


    Quote Originally Posted by katentim
    Sort of - you can define an abstract bean which defines most of the transactional proxy. Your then define descendant beans for the two descendant classes.
    So far I've come up with the following configuration, but it's not working :

    Code:
    ...
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    <bean id="baseTransactionProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager" ref="txManager"/>
       <property name="transactionAttributes">
          <props>
             <prop key="save">PROPAGATION_REQUIRED</prop>
             <prop key="delete">PROPAGATION_REQUIRED</prop>
          </props>
       </property>
    </bean>
    
    <bean id="baseOperation" abstract="true" parent="baseTransactionProxy">
       <property name="target">
          <bean class="com.mycompany.base.AbstractServiceImpl"/>
       </property>
    </bean>
    
    <bean id="service.research" parent="baseOperation">
       <property name="target">
          <bean class="com.mycompany.research.ResearchServiceImpl" lazy-init="true"/>
       </property>
    </bean>
    
    <bean id="service.admin" parent="baseOperation">
       <property name="target">
          <bean class="com.mycompany.admin.AdminServiceImpl" lazy-init="true"/>
       </property>
    </bean>
    ...
    Is this the correct way to define abstract bean as you suggested ?

    Regards,


    Setya

  8. #8
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    So far I've come up with the following configuration, but it's not working
    Can you post a stack trace or description of the problem?

    Is this the correct way to define abstract bean as you suggested ?
    Looks OK at a glance. NB - there's an example in Spring's JPetStore sample's applicationContext.xml.

  9. #9

    Default

    [QUOTE=katentim]Can you post a stack trace or description of the problem?

    Actually the application does not throw any exception, but after I call session.save the database does not get updated. I call the session.save through HibernateTemplate's callback method.

  10. #10

    Default

    When I turn the log on, it produces the following stacktrace:

    Code:
    DEBUG (AbstractFlushingEventListener.java:267) - executing flush
    DEBUG (AbstractFlushingEventListener.java:294) - post flush
    DEBUG (AbstractPlatformTransactionManager.java:668) - Triggering beforeCompletion synchronization
    DEBUG (TransactionSynchronizationManager.java:184) - Removed value [org.springframework.orm.hibernate3.SessionHolder@a6af6e] for key [org.hibernate.impl.SessionFactoryImpl@830122] from thread [main]
    DEBUG (AbstractPlatformTransactionManager.java:492) - Initiating transaction commit
    DEBUG (HibernateTransactionManager.java:486) - Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1469658]
    DEBUG (JDBCTransaction.java:83) - commit
    DEBUG (SessionImpl.java:323) - automatically flushing session
    DEBUG (JDBCContext.java:278) - before transaction completion
    DEBUG (SessionImpl.java:372) - before transaction completion
    DEBUG (JDBCTransaction.java:96) - committed JDBC Connection
    DEBUG (JDBCContext.java:283) - after transaction completion
    DEBUG (SessionImpl.java:403) - after transaction completion
    DEBUG (AbstractPlatformTransactionManager.java:692) - Triggering afterCompletion synchronization
    DEBUG (SessionImpl.java:403) - after transaction completion
    DEBUG (SessionFactoryUtils.java:773) - Closing Hibernate Session
    DEBUG (SessionImpl.java:269) - closing session
    DEBUG (ConnectionManager.java:317) - closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    DEBUG (GooGooStatementCache.java:197) - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 7; checked out: 0; num connections: 2; num keys: 7
    DEBUG (NewPooledConnection.java:294) - A Throwable occurred while trying to reset the typeMap property of our Connection to Collections.EMPTY_MAP!
    java.sql.SQLException: The Connection.setTypeMap(Map) method is not implemented.
    	at net.sourceforge.jtds.jdbc.ConnectionJDBC2.notImplemented(ConnectionJDBC2.java:1519)
    	at net.sourceforge.jtds.jdbc.ConnectionJDBC2.setTypeMap(ConnectionJDBC2.java:2123)
    	at com.mchange.v2.c3p0.impl.NewPooledConnection.reset(NewPooledConnection.java:290)
    	at com.mchange.v2.c3p0.impl.NewPooledConnection.markClosedProxyConnection(NewPooledConnection.java:247)
    	at com.mchange.v2.c3p0.impl.NewProxyConnection.close(NewProxyConnection.java:1148)
    	at org.hibernate.connection.C3P0ConnectionProvider.closeConnection(C3P0ConnectionProvider.java:42)
    	at org.hibernate.jdbc.ConnectionManager.closeConnection(ConnectionManager.java:327)
    	at org.hibernate.jdbc.ConnectionManager.cleanup(ConnectionManager.java:262)
    	at org.hibernate.jdbc.ConnectionManager.close(ConnectionManager.java:194)
    	at org.hibernate.impl.SessionImpl.close(SessionImpl.java:289)
    	at org.springframework.orm.hibernate3.SessionFactoryUtils.doClose(SessionFactoryUtils.java:775)
    	at org.springframework.orm.hibernate3.SessionFactoryUtils.closeSessionOrRegisterDeferredClose(SessionFactoryUtils.java:763)
    	at org.springframework.orm.hibernate3.SessionFactoryUtils.access$100(SessionFactoryUtils.java:86)
    	at org.springframework.orm.hibernate3.SessionFactoryUtils$SpringSessionSynchronization.afterCompletion(SessionFactoryUtils.java:958)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:724)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:696)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:533)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:468)
    	at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:258)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
    	at $Proxy1.save(Unknown Source)
    	at com.farbeyond.dbengine.ModelSet.save(ModelSet.java:565)
    	at com.farbeyond.test.crud.TestCRUDSEditing.testCRUDSEditing(TestCRUDSEditing.java:49)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:324)
    	at junit.framework.TestCase.runTest(TestCase.java:154)
    	at junit.framework.TestCase.runBare(TestCase.java:127)
    	at junit.framework.TestResult$1.protect(TestResult.java:106)
    	at junit.framework.TestResult.runProtected(TestResult.java:124)
    	at junit.framework.TestResult.run(TestResult.java:109)
    	at junit.framework.TestCase.run(TestCase.java:118)
    	at junit.framework.TestSuite.runTest(TestSuite.java:208)
    	at junit.framework.TestSuite.run(TestSuite.java:203)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
    I believe that explains why I can not update the database.

    Please help,

    Setya

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •