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.DataSourceFac开发者_JAVA技巧tory] - 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.
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.
精彩评论