Announcement Announcement Module
Collapse
No announcement yet.
@Transaction working for TestCase but not static main() Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transaction working for TestCase but not static main()

    Howdy,

    I started a new project today and can't figure out what I am doing wrong. I have a good classpath (built with Maven against spring-aspects 2.0, looks like everything is there transitively and no CNFs) and no errors are coming out, but I have this very peculiar behavior: This code does not work:

    Code:
        public static void main(String[] args) {
            ClassPathResource resource = new ClassPathResource("applicationContext.xml");
            BeanFactory factory = new XmlBeanFactory(resource);
            FeedManager fm = (FeedManager) factory.getBean("feedManager");
            fm.processFeeds();
        }
    This code does:

    Code:
    public class FeedTest extends AbstractTransactionalSpringContextTests {
        public void testFeed() throws Exception {
            FeedManager feedManager = (FeedManager)applicationContext.getBean("feedManager");
            feedManager.processFeeds();
        }
    
        protected String[] getConfigLocations() {
            return new String[] {"applicationContext.xml"};
        }
    }
    When I say "works", I mean that the call to getBean("feedManager") returns the feedManager bean wrapped with the transactional proxy code.

    Here's my FeedManagerImpl:

    Code:
    @Transactional
    public class FeedManagerImpl extends HibernateDaoSupport implements FeedManager {
    
        public void processFeeds() {
            HibernateTemplate hibernateTemplate = getHibernateTemplate();
            for (Feed feed : (List<Feed>) hibernateTemplate.find("from Feed")) {
                // do something interesting
                hibernateTemplate.save(...);
            }
        }
    }
    In the case of the TestCase version, I get "DEBUG org.springframework.aop.framework.JdkDynamicAopPro xy - Creating JDK dynamic proxy for [foo.service.impl.FeedManagerImpl]", but I do not get that at all in the static main version.

    These are both using the same context configuration file:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="location" value="classpath:hibernate.properties"/>
        </bean>
    
        <bean id="hibernate" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="properties">
                <ref local="hibernateProperties"/>
            </property>
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${hibernate.connection.driver_class}"/>
            <property name="url" value="${hibernate.connection.url}"/>
            <property name="username" value="${hibernate.connection.username}"/>
            <property name="password" value="${hibernate.connection.password}"/>
        </bean>
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="configLocation">
                <value>classpath:hibernate.cfg.xml</value>
            </property>
            <property name="configurationClass">
                <value>org.hibernate.cfg.AnnotationConfiguration</value>
            </property>
            <property name="hibernateProperties">
                <ref local="hibernateProperties"/>
            </property>
        </bean>
    
        <bean id="feedManager" class="foo.service.impl.FeedManagerImpl">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
    </beans>
    Any ideas what I might be missing? I tried to keep this as simple as the examples on the new docs (which look great, BTW), but have also tried a lot of different variations as well. Any help appreciated!

  • #2
    Hi topping

    Gah! Apologies for causing you any headbanging-throwing-the-pc-out-of-the-cube moments (as you do), but the automatic creation of transactional proxies only works if you are using a Spring ApplicationContext, and not a plain vanilla BeanFactory.

    The AbstractXXXSpringContextTests (gee, that class name is just toooo long to type out) uses an ApplicationContext implementation internally, so that is why that case is working. In your main method code snippet, you are creating an XmlBeanFactory... try using a ClassPathXmlApplicationContext instead and all will be gravy.

    I apologised at the start because I've just realised that this slight nuance isn't actually mentioned in the reference documentation. Bah! I'll go redress this deficincy immediately.

    Cheers
    Rick

    Comment


    • #3
      Awesome. I remember blindly considering such when I was putting my LCD back together with super glue, but alas, I haven't been able to try it until a new monitor came in today ;-D

      Thanks a bunch for your info!

      :B

      Comment


      • #4
        HibernateTemplate @Transactional

        Hi,

        My save statment in the BaseDAO does not commit to the database. Please help me figure out why it is not automatically committing?
        Is this because im using XmlBeanFactory(new FileSystemResource("web/WEB-INF/applicationContext.xml"))?


        here is the BaseDAO.java




        @Repository
        @Transactional(propagation = Propagation.REQUIRED)
        public class BaseDAO extends HibernateDaoSupport {
        private static final Log log = LogFactory.getLog(BaseDAO.class);

        @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
        public void save(final Object object)
        {
        log.debug("saving BankAccMovement instance");
        try {
        getHibernateTemplate().saveOrUpdate(object);
        log.debug("save successful");
        } catch (RuntimeException re) {
        log.error("save failed", re);
        throw re;
        }
        }
        }

        here is the testcase


        public class AnnotationsTest extends TestBase{
        public void testHibernateAnnotations()
        {

        BaseDAO baseDAO = (BaseDAO) getBeanFactory()
        .getBean("BaseDAO");

        ErrorCodes errorCodes = new ErrorCodes("1000");

        errorCodes.setErrorCodeDesc("hello");
        errorCodes.setExternalCode("00");
        baseDAO.save(errorCodes);

        }
        }

        here is the applicationContext.xml


        <tx:annotation-driven transaction-manager="transactionManager"/>

        <bean id="BaseDAO" class="dto.BaseDAO">
        <property name="sessionFactory">
        <ref bean="localSessionFactoryBean" />
        </property>
        </bean>

        </beans>

        regards vaughn

        Comment


        • #5
          Try using a ClassPathXmlApplicationContext.
          What class does AnnotationTest test class extends ? (TestBase) What transactionManager are you using ?

          Comment


          • #6
            Hi and thank you for your reply.

            Here is the rest of the information in the applicationContext.xml

            <bean id="localSessionFactoryBean"
            class="org.springframework.orm.hibernate3.LocalSes sionFactoryBean">
            <property name="configLocation"
            value="classpath:hibernate.cfg.xml">
            </property>
            </bean>
            <bean id="transactionManager" class="org.springframework.orm.hibernate3.Hibernat eTransactionManager">
            <property name="sessionFactory">
            <ref bean="localSessionFactoryBean" />
            </property>
            </bean>

            <tx:annotation-driven transaction-manager="transactionManager"/>

            <bean id="BaseDAO" class="dto.BaseDAO">
            <property name="sessionFactory">
            <ref bean="localSessionFactoryBean" />
            </property>
            </bean>

            Here is the TestBase class which all unit test extend from.



            public abstract class TestBase extends TestCase {

            private BeanFactory beanFactory;

            public BeanFactory getBeanFactory() {

            beanFactory = new XmlBeanFactory(new FileSystemResource(
            "web/WEB-INF/applicationContext.xml"));

            return beanFactory;
            }

            }


            Also im running a web application that uses the following java file as a base for all jsf beans.




            public class JSFBase {


            protected WebApplicationContext webContext ;
            protected JSFBase()
            {
            ServletContext context = (ServletContext)FacesContext.getCurrentInstance(). getExternalContext().getContext();
            webContext = WebApplicationContextUtils.getRequiredWebApplicati onContext(context);
            }
            }

            Will @Transaction work with WebApplicationContext ?

            Much appreciated
            Regards Vaughn

            Comment


            • #7
              Please use [ code][/code ] tags when posting code!

              As suggested before use an ApplicationContext NOT a BeanFactory... The reference guide (chapter 3) explains the differences between the 2.

              Comment

              Working...
              X