Announcement Announcement Module
Collapse
No announcement yet.
tx:annotation-driven does not work, but aop:config works Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • tx:annotation-driven does not work, but aop:config works

    Hi All,

    We are using ENV Spring 3.1.1 + JPA(hibernate).

    Originally, Everything worked fine including the transaction. We originally utilized aop:config to configure transaction, and it does work.
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="*" propagation="REQUIRED" />

    </tx:attributes>
    </tx:advice>

    <aop:config>
    <aopointcut id="allManagerMethod"
    expression="execution(* com.hp.et.log.service.*.*(..))" />
    <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" />
    </aop:config>

    Now, we want to change to annotation @Transactional, so we removed the above configuration and add
    <tx:annotation-driven transaction-manager="transactionManager"/>.

    In our Service concrete class, we put @Transactional ahead. The service class internally will call DAO.

    @Transactional(readOnly=false)
    public class Authentication

    However, when it call DAO in service's method, we will get Exception, checking log file, the transaction was never started
    java.lang.RuntimeException: javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!

    The question is, why aop:config worked fine but annotation doesn't work? Is there anything wrong with our configuraion?

    Below is the full configuration:
    <bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.Pr opertyPlaceholderConfigurer">
    <property name="location" value="classpath:datasource.properties" />
    </bean>



    <bean id="logJpaDs" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
    </bean>



    <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
    <property name="dataSource" ref="logJpaDs" />
    <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
    <property name="showSql" value="false" />
    <property name="generateDdl" value="false" />
    <property name="database" value="ORACLE" />
    </bean>
    </property>
    <property name="jpaProperties">
    <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.Orac le10gDialect</prop>
    </props>
    </property>
    </bean>



    <!-- to avoid repeated loading the datasource: use JPA transaction to replace the transaction of jdbc-->
    <bean id="transactionManager"
    class="org.springframework.orm.jpa.JpaTransactionM anager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <context:annotation-config/>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="hostDao" class="com.hp.et.log.dao.jpaimpl.HostJpaDao">
    </bean>

    <bean id="authentication" class="com.hp.et.log.service.Authentication" autowire="byName">
    </bean>


    @Transactional(readOnly=false)
    public class Authentication
    {

    private static Logger logger = LoggerFactory.getLogger(Authentication.class);

    private IHostDao hostDao;

    public String register(ApplicationInstance applicationInstance, @Context HttpServletRequest request) throws Exception
    {
    logger.info("Enter register");
    logger.debug(applicationInstance.debugString());

    //1.validate ip from host table.
    String ipAddress = request.getRemoteAddr();
    Host host = this.hostDao.getHostByIpAddress(ipAddress);
    ....
    }

    public class HostJpaDao{
    @PersistenceContext
    protected EntityManager entityManager;

    public List<Host> findAllHost()
    {
    Query query = entityManager.createNamedQuery("Host.findAll");
    try
    {
    return (List<Host>)query.getResultList();
    }
    catch(NoResultException e)
    {
    return null;
    }
    }

    The "Session is closed" exception is thrown at the RED code.

    This issue took me several hours , still could not find the root cause and resolve it, thanks a lot for any of your advice and ideas.

  • #2
    Please use [ code][/code ] tags when posting code, that way it remains readable!

    With the tx:annotation-driven tell it to use class proxies and make sure that cglib is on the classpath because you need class proxies as you don't implement interfaces.

    Comment


    • #3
      Thanks for your response.
      Yes, the @Transactional was set for concrete class, NOT interface, and I double checked that cglib is in the classpath, I think if there is any class missing, I should get ClassNotFound error, now it's "Session is closed" error, and before the Service's class is called, I didn't find any spring's log which indicate transaction is created, I think this is the root cause, seems AOP didn't happen, but the it's really weird, when I use aop:config to configure, it does work, and I could find spring's log which indicate the transaction is started before entering the service's method. I really don't know what's wrong with the tx:annotation-driven.

      Comment


      • #4
        Could anyone help on this, thanks a lot in advance.
        I tried to remove all unnecessary beans in configuration, and instead of using auto-wire, I configure bean relationship directly in spring configuration file, I tried to move the @transactional to DAO concrete class, still doesn't work, I could not find any log indicating the transaction is started before entering the method, seems the tx:annotation-driven is totally ignored by Spring.

        Comment

        Working...
        X