Announcement Announcement Module
Collapse
No announcement yet.
Transactions in a non-managed environment Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transactions in a non-managed environment

    Hi,

    Again, another noob question - doubly embarassing as I gave up on my other problem (trying to get a JTA under Tomcat - it worked in JBoss, but I was trying to get something that started quicker). Given I am only using one resource, I probably do not need JTA anyway and so perhaps its a configuration issue.

    We have another process that uses Spring/JPA/Hibernate for DB access. This is currently a standalone JVM app - not in JBoss/a container. Perhaps the solution is to move it into JBoss...

    The problem is that the EntityManager instance is not being initialised. Its largely using the same spring config/classes as we use in the webapp via JBoss.

    In particular here are the relevant bits of the config:

    Code:
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
          <property name="entityManagerFactory" ref="entityManagerFactory"/>
        </bean>
    
        <tx:annotation-driven/>
    
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!--
                    <property name="loadTimeWeaver">
                        <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
                    </property>
            -->
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <!--<property name="showSql" value="true"/>-->
                </bean>
            </property>
        </bean>
    
        <bean id="dataSource" class="oracle.jdbc.pool.OracleConnectionPoolDataSource">
            <property name="user" value="???"/>
            <property name="password" value="???"/>
            <property name="URL" value="jdbc:oracle:thin:@zsts490705:9501:SOPHI2DV"/> 
        </bean>
    The service classes (which are the same for both processes) are marked like this:
    Code:
    @Transactional(readOnly = true)
    public class TemplateManager {
    and the DAOs like this:
    Code:
        @PersistenceContext
        private EntityManager entityManager;
    I don't get any specific errors, just that the entityManager stays null.

    Its like there is some further bootstrapping missing that I need to do. Perhaps something gets done in a webapp through default bean wiring and I am missing in the non-webapp version.

    I have tried adding a transaction interceptor, but that was based on a fairly old blog and is possibly the wrong route:
    Code:
        <bean id="transactionInterceptor"
              class="org.springframework.transaction.interceptor.TransactionInterceptor">
          <property name="transactionManager" ref="transactionManager" />
          <property name="transactionAttributeSource">
            <bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" />
          </property>
        </bean>
    
        <bean id="templateDaoTarget" class="com.rabobank.mithrasweb.dao.template.impl.TemplateDaoJdbc">
        </bean>
    
      <bean id="templateDao"
            class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces">
          <value>com.rabobank.mithrasweb.dao.template.TemplateDao</value>
        </property>
        <property name="interceptorNames">
          <list>
            <idref local="transactionInterceptor" />
            <idref local="templateDaoTarget" />
          </list>
        </property>
      </bean>
    So, any tips on where I am going wrong?

  • #2
    How are you initializing the ApplicationContext in your standalone application?

    Also your templateDao definition is wrong!

    Code:
     <bean id="templateDao"
            class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces">
          <value>com.rabobank.mithrasweb.dao.template.TemplateDao</value>
        </property>
        <property name="interceptorNames">
          <list>
            <idref local="transactionInterceptor" />
            <idref local="templateDaoTarget" />
          </list>
        </property>
      </bean>
    templateDaoTarget isn't an interceptor it is the target to which the interceptors should be applied! I prefer to work with inner classes in such a case. Also it should be the name of the bean not the bean itself.

    Code:
    <bean id="templateDao" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="proxyInterfaces" value="com.rabobank.mithrasweb.dao.template.TemplateDao"/>
      <property name="target">
        <bean class="com.rabobank.mithrasweb.dao.template.impl.TemplateDaoJdbc">
      </property>      
      <property name="interceptorNames">
        <list>
          transactionInterceptor
       </list> 
      </property>
    </bean>

    Comment


    • #3
      Hi,

      Thanks for the correction on the Interceptor, although it does not seem to have helped - should I need an interceptor?

      This is how I load my application context:

      Code:
              Resource resource = new FileSystemResource("quoteEngineContext.xml");
              BeanFactory factory = new XmlBeanFactory(resource);
      
              QuoteEngineServer server = (QuoteEngineServer) factory.getBean("quoteEngineServer");
      Thanks in advance,
      Chris

      Comment


      • #4
        You need an ApplicationContext instead of a BeanFactory...

        A BeanFactory only instantiates beans, a ApplicationContext also applies AOP stuff (Transactions, etc.). A more detailed clarification can be found here

        Code:
        Resource resource = new FileSystemResource("quoteEngineContext.xml");
        BeanFactory factory = new XmlBeanFactory(resource);
        Needs to be replaced.

        Code:
        ApplicationContext factory = new FileSystemXmlApplicationContext("quoteEngineContext.xml");

        Comment


        • #5
          HURRAY

          Thats done it - I now have an EntityManager.

          For the record, I didn't need the interceptors.

          Many Thanks,
          Chris

          Comment


          • #6
            Glad that it worked.

            For the interceptors if you want your transactions to work correctly yuo will need them...

            Comment


            • #7
              Hi,

              Thanks for the heads up on the interceptors - we are just reading data at the moment, so not an issue for now - but we will be soon.

              Regards,
              Chris

              Comment


              • #8
                In future, when you add transactions using AOP, have a look at Spring 2.0 AOP, will make it a much simpler configuration to apply a transaction advice, no more ProxyFactoryBean definition required.

                Comment

                Working...
                X