3

At first the applicationContext.xml is:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <bean class="info.ems.config.EMSConfigurer"/>

    <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>

    <bean id="ems" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>        
    <property name="target">            
        <bean class="info.ems.EMSImpl" init-method="init">
            <property name="dao" ref="dao"/>
            <property name="passwordEncoder" ref="passwordEncoder"/>
            <property name="localeList" value="${ems.locales}"/>
            <property name="releaseVersion" value="${ems.version}"/>
            <property name="releaseTimestamp" value="${ems.timestamp}"/>
            <property name="emsHome" value="${ems.home}"/>
        </bean>
    </property>       
    </bean>   

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="dataSource" class="info.ems.datasource.DataSourceFactory">
    <property name="driverClassName" value="${database.driver}"/>
    <property name="url" value="${database.url}"/>
    <property name="username" value="${database.username}"/>
    <property name="password" value="${database.password}"/>
    <property name="validationQuery" value="${database.validationQuery}"/>
    <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
    </bean>     

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

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation">
            <value>/WEB-INF/hibernate.cfg.xml</value>
        </property>
    <property name="configurationClass">
        <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>        
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>        
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
            <prop key="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</prop>
        </props>
    </property>        
    </bean>

    <bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
    <property name="hibernateTemplate">
        <bean class="org.springframework.orm.hibernate3.HibernateTemplate">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    </property>        
    <property name="schemaHelper">
        <bean class="info.ems.hibernate.SchemaHelper">                                
            <property name="driverClassName" value="${database.driver}"/>
            <property name="url" value="${database.url}"/>
            <property name="username" value="${database.username}"/>
            <property name="password" value="${database.password}"/>
            <property name="hibernateDialect" value="${hibernate.dialect}"/>   
            <property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
        </bean>                
    </property>
    </bean>       
</beans>

The service layer that is EMS.java interface:

public interface EMS extends UserDetailsService {

    public void saveUser(User user);
}

And its implementation EMSImpl.java:

@Service("emsImpl")
@Transactional(readOnly=true)
public class EMSImpl implements EMS {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("dao")
    private EMSDao dao;


    //some other code


    @Transactional(readOnly=false)
    public void saveUser(User user) {

    }
}

The interface dao is EMSDAO.java:

@Transactional(readOnly=true)
public interface EMSDao {

    public void saveUser(User user);
}

And its implementation HibernateEMSDao.java

@Repository("EMSDao")
public class HibernateEMSDao extends HibernateDaoSupport implements EMSDao {

    private final Logger logger = LoggerFactory.getLogger(getClass());  

    private SchemaHelper schemaHelper;

    public void setSchemaHelper(SchemaHelper schemaHelper) {
        this.schemaHelper = schemaHelper;
    }

    @Transactional(readOnly=false)
    public synchronized void saveUser(final User user) {        
        Session session = getSessionFactory().getCurrentSession();
        session.merge(user);
    }


    public void createSchema() {        
        try {
            getHibernateTemplate().find("from User user where user.id = 1");
        } catch (Exception e) {
            logger.warn("expected database schema does not exist, will create. Error is: " + e.getMessage());
            schemaHelper.createSchema();
            User admin = new User();
            admin.setUsername("admin");
            admin.setName("Admin");
            admin.setEmail("admin");
            admin.setPassword("21232f297a57a5a743894a0e4a801fc3");
            admin.setRoles(new HashSet<Role>(Arrays.asList(new Role("admin", "ADMINISTRATOR"))));
            logger.info("inserting default admin user into database");
            saveUser(admin);

            logger.info("schema creation complete");                        
            return;
        }
        logger.info("database schema exists, normal startup");              
    }
}

When I am deploying the war after inserting User admin I am getting this error:

12:40:11,111 INFO  [STDOUT] 2011-05-30 12:40:11,111 [ScannerThread] INFO [info.ems.datasource.DataSourceFactory] - Attempting to shut down embedded HSQLDB database.
12:40:11,217 INFO  [STDOUT] 2011-05-30 12:40:11,217 [ScannerThread] INFO [info.ems.datasource.DataSourceFactory] - Embedded HSQLDB database shut down successfully.
12:40:11,220 INFO  [STDOUT] 2011-05-30 12:40:11,218 [ScannerThread] ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ems' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot create inner bean 'info.ems.EMSImpl#586f403e' of type [info.ems.EMSImpl] while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'info.ems.EMSImpl#586f403e' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'dao' while setting bean property 'dao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dao' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: merge is not valid without active transaction

What I am doing wrong and is there anything I missed?

Thanks and regards.

3
  • You are catching all exceptions in createSchema(). I dont think that what you intended. You should be catching a more specific exception, for the exception handling logic assumes the presence of certain conditions, like the presence of a Transaction. Commented May 30, 2011 at 7:30
  • @Vineet Reynolds thanks. Yes after the createSchema() the console is printing the exception messages. So what are you suggesting in this case? Is the configuration is okay? Commented May 30, 2011 at 7:34
  • You'll need catch and handle specific exceptions. Catching generic exceptions would result in the possibility of handling scenarios that your code is unprepared for, which might be true in this case. Commented May 30, 2011 at 7:39

1 Answer 1

4

Here is what may be happening. You declared method saveUser() @Transactional, however you call it from createSchema() which is not @Transactional. Therefore, you actually call not proxied method saveUser() and it fails. You best shot here is to use HibernateTemplate. Since createSchema() is init method @Transactional probably would not work on it.

Also notice that @Transactional on interface will have no effect.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks. You are right and your suggestion of using HibernateTemplate works, but after that with the same configuration I am getting java.lang.IllegalArgumentException: Either 'transactionAttributeSource' or 'transactionAttributes' is required: If there are no transactional methods, then don't use a transaction aspect. Can you please help me the solve this?
it is solved, as I am using TransactionProxyFactoryBean for creating bean with id="ems" but didn't use any transactionAttributes. After adding these attributes that problem is solved. Thank you very much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.