Results 1 to 7 of 7

Thread: @Transaction working for TestCase but not static main()

  1. #1
    Join Date
    Apr 2006
    Posts
    17

    Default @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. #2
    Join Date
    Oct 2004
    Location
    Fareham, England
    Posts
    313

    Default

    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

  3. #3
    Join Date
    Apr 2006
    Posts
    17

    Default

    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

  4. #4

    Default 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

  5. #5
    Join Date
    Mar 2007
    Posts
    515

    Default

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

  6. #6

    Default

    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

  7. #7
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Posting Permissions

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