Spring + GAE incorrect initialization of spring container
I am trying to write an aoolication enabled with Spring + GAE but I've faced with a very strange problem.
For persistence layer I user JPA with following persistence.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="transactions-optional">
<provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
<properties>
<property name="datanucleus.NontransactionalRead" value="true" />
<property name="datanucleus.NontransactionalWrite" value="true" />
<property name="datanucleus.ConnectionURL" value="appengine" />
</properties>
</persistence-unit>
</persistence>
Also I have spring config file with following declaration:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<tx:annotation-driven />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="transactions-optional" />
</bean>
<bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="datastoreService" class="com.google.appengine.api.datastore.DatastoreServiceFactory" factory-method="getDatastoreService" />
<bean id="memcacheServiceUser" class="com.google.appengine.api.memcache.MemcacheServiceFactory" factory-method="getMemcacheService">
<constructor-arg value="UserCache"/>
</bean>
</beans>
And finnaly I have DAO component which is marked ad @Repository and extends JpaDaoSupport this bean configured to be scanned with
And after attempt to initialize that DAO bean I receive following exception:
Caused by: java.lang.IllegalArgumentException: entityManagerFactory or jpaTemplate is required
at org.springframework.orm.jpa.support.JpaDaoSupport.checkDaoConfig(JpaDaoSupport.java:120)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$5.run(AbstractAutowireCapableBeanFactory.java:1467)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1465)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 30 more
Then I've looked at the log and I can see that entityManagerFactory creates successfully befor DAO init, but just before actual start of initialization of DAO object, spring just destroys all singletons including this one. There is a lot of logs but I defenitly sure that entityManagerFactory creates as well, the one thing that is very strange to me it is why spring destroys all singletons with following log message:
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1594a88: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,entityManagerFactory,transactionManager,datastoreService,memcacheServiceUser,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,userDaoJpa,employeeDS,messageSource]; root of factory hierarchy
Jan 14, 2011 11:12:12 AM org.springframework.beans.factory.support.DisposableBeanAdapter destroy
FINE: Invoking destroy() on bean with name 'entityManagerFactory'
Jan 14, 2011 11:12:12 AM org.springframework.orm.jpa.AbstractEntityManagerFactoryBean destroy
INFO: Closing JPA EntityManagerFactory for persistence unit 'transactions-optional'
Jan 14, 2011 11:12:12 AM org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context init开发者_JAVA技巧ialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDaoJpa' defined in file
The class JpaDaoSupport expects you to set the EntityManagerFactory
or JpaTemplate
on construction. Something like this should do it:
@Repository
public class YourDAOImpl extends JpaDaoSupport implements YourDAO
{
@Autowired
public YourDAOImpl(EntityManagerFactory entityManagerFactory)
{
setEntityManagerFactory(entityManagerFactory);
}
...
}
You can automatically inject the entity manager using below.
@PersistenceContext
private EntityManager entityManager;
@Autowired
public ClaseDaoImpl(EntityManagerFactory entityManagerFactory) {
setEntityManagerFactory(entityManagerFactory);
}
Each implemented by Dao.
精彩评论