Using Spring Data JPA on Google Appengine

google-app-engine, spring-data, spring-data-jpa

Solution

In standalone environments we recommend to use the Spring support classes to set up a `EntityManagerFactory`. So if you change your configuration to the following the additional bean declaration should not be necessary:

 @Bean
 public AbstractEntityManagerFactoryBean entityManagerFactory() {

   LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
   factory.setPersistenceUnitName("eventual-reads-short-deadlines");
   return factory;
 }

 @Bean
 public PlatformTransactionManager transactionManager() {

    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return txManager;
}

The crucial part is making the `FactoryBean` implementation available as Spring bean as it implements `PersistenceExceptionTranslator`.

Problem

I'm trying to use Spring 3.2 and Spring Data on GAE and having some trouble getting my configuration right. It's minimal but from the Spring Data documentation it seems like you don't need much more than just the entitymanagerfactory bean. Here's my configuration and the exception I am getting at startup. Can someone please provide a solution for the exception I am receiving with Datanucleus JPA 2.0? pom.xml ``` <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <version>1.0.0-SNAPSHOT</version> <groupId>com.foo</groupId> <artifactId>bar</artifactId> <properties> <appengine.version>1.7.5</appengine.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <slf4j.version>1.7.2</slf4j.version> <datanucleus.version>3.0.6</datanucleus.version> <spring.version>3.2.1.RELEASE</spring.version> <spring-data.version>1.3.0.RELEASE</spring-data.version> </properties> <dependencies> <!-- Compile/runtime dependencies --> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-1.0-sdk</artifactId> <version>${appengine.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-data.version}</version> </dependency> <!-- Logging dependencies --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>${slf4j.version}</version> </dependency> <!-- JPA 2.0 for GAE --> <dependency> <groupId>com.google.appengine.orm</groupId> <artifactId>datanucleus-appengine</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-api-jpa</artifactId> <version>${datanucleus.version}</version> </dependency> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-core</artifactId> <version>${datanucleus.version}</version> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jpa_2.0_spec</artifactId> <version>1.0</version> </dependency> <!-- Test Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-testing</artifactId> <version>${appengine.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-stubs</artifactId> <version>${appengine.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <version>2.5.1</version> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <archiveClasses>true</archiveClasses> <webResources> <!-- in order to interpolate version from pom into appengine-web.xml --> <resource> <directory>${basedir}/src/main/webapp/WEB-INF</directory> <filtering>true</filtering> <targetPath>WEB-INF</targetPath> </resource> </webResources> </configuration> </plugin> <plugin> <groupId>com.google.appengine</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>${appengine.version}</version> </plugin> </plugins> </build> </project> ``` JPA Configuration ``` @Configuration @EnableJpaRepositories("com.foo.bar.domain") @EnableTransactionManagement class JpaApplicationConfig { private static final Logger logger = Logger .getLogger(JpaApplicationConfig.class.getName()); @Bean public EntityManagerFactory entityManagerFactory() { logger.info("Loading Entity Manager..."); return Persistence .createEntityManagerFactory("eventual-reads-short-deadlines"); } @Bean public PlatformTransactionManager transactionManager() { logger.info("Loading Transaction Manager..."); final JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } } ``` Exception ``` [INFO] SEVERE: Context initialization failed [INFO] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) [INFO] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) [INFO] at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) [INFO] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) [INFO] at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) [INFO] at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) [INFO] at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [INFO] at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) [INFO] at org.mortbay.jetty.servlet.Context.startContext(Context.java:136) [INFO] at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250) [INFO] at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) [INFO] at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.jetty.Server.doStart(Server.java:224) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:228) [INFO] at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:255) [INFO] at com.google.appengine.tools.development.AbstractServer.startup(AbstractServer.java:79) [INFO] at com.google.appengine.tools.development.DevAppServerImpl$Servers.startup(DevAppServerImpl.java:451) [INFO] at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:198) [INFO] at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:333) [INFO] at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) [INFO] at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:269) [INFO] at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:245) [INFO] Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142) [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:103) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1506) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.access$000(AbstractAutowireCapableBeanFactory.java:116) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$5.run(AbstractAutowireCapableBeanFactory.java:1468) [INFO] at java.security.AccessController.doPrivileged(Native Method) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1466) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) [INFO] ... 30 more [INFO] [INFO] Mar 12, 2013 11:10:49 AM com.google.apphosting.utils.jetty.JettyLogger warn [INFO] WARNING: Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext@2912ee3c{/,/home/tim/workspace-me/Dating/target/dating-1.0.0-SNAPSHOT} [INFO] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:532) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) [INFO] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) [INFO] at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) [INFO] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) [INFO] at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) [INFO] at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) [INFO] at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [INFO] at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) [INFO] at org.mortbay.jetty.servlet.Context.startContext(Context.java:136) [INFO] at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250) [INFO] at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) [INFO] at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.jetty.Server.doStart(Server.java:224) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:228) [INFO] at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:255) [INFO] at com.google.appengine.tools.development.AbstractServer.startup(AbstractServer.java:79) [INFO] at com.google.appengine.tools.development.DevAppServerImpl$Servers.startup(DevAppServerImpl.java:451) [INFO] at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:198) [INFO] at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:333) [INFO] at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) [INFO] at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:269) [INFO] at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:245) [INFO] Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142) [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:103) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1506) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.access$000(AbstractAutowireCapableBeanFactory.java:116) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$5.run(AbstractAutowireCapableBeanFactory.java:1468) [INFO] at java.security.AccessController.doPrivileged(Native Method) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1466) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) [INFO] ... 30 more [INFO] [INFO] Mar 12, 2013 11:10:49 AM com.google.apphosting.utils.jetty.JettyLogger warn [INFO] WARNING: Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.: [INFO] java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142) [INFO] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70) [INFO] at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:103) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1506) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.access$000(AbstractAutowireCapableBeanFactory.java:116) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$5.run(AbstractAutowireCapableBeanFactory.java:1468) [INFO] at java.security.AccessController.doPrivileged(Native Method) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1466) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) [INFO] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) [INFO] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) [INFO] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) [INFO] at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) [INFO] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) [INFO] at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) [INFO] at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) [INFO] at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [INFO] at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) [INFO] at org.mortbay.jetty.servlet.Context.startContext(Context.java:136) [INFO] at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250) [INFO] at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) [INFO] at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130) [INFO] at org.mortbay.jetty.Server.doStart(Server.java:224) [INFO] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) [INFO] at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:228) [INFO] at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:255) [INFO] at com.google.appengine.tools.development.AbstractServer.startup(AbstractServer.java:79) [INFO] at com.google.appengine.tools.development.DevAppServerImpl$Servers.startup(DevAppServerImpl.java:451) [INFO] at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:198) [INFO] at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:333) [INFO] at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48) [INFO] at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:269) [INFO] at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:245) [INFO] [INFO] Mar 12, 2013 11:10:49 AM com.google.apphosting.utils.jetty.JettyLogger debug ```

Original source