title: GoogleAppEngine : ClassNotFoundException : javax.jdo.metadata.ComponentMetadata
body: <p>I'm trying to deploy my application to a locally running GoogleAppEngine development server, but I'm getting the following stack trace when I start the server </p>
  
  <pre><code>Apr 23, 2010 9:03:33 PM com.google.apphosting.utils.jetty.JettyLogger warn
  WARNING: Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientDao' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/jdo/metadata/ComponentMetadata:
  java.lang.ClassNotFoundException: javax.jdo.metadata.ComponentMetadata
          at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
          at java.security.AccessController.doPrivileged(Native Method)
          at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:319)
          at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:151)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:264)
          at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:332)
          at java.lang.Class.forName0(Native Method)
          at java.lang.Class.forName(Class.java:264)
          at javax.jdo.JDOHelper$18.run(JDOHelper.java:2009)
          at javax.jdo.JDOHelper$18.run(JDOHelper.java:2007)
          at java.security.AccessController.doPrivileged(Native Method)
          at javax.jdo.JDOHelper.forName(JDOHelper.java:2006)
          at javax.jdo.JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(JDOHelper.java:1155)
          at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:803)
          at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:698)
          at org.datanucleus.jpa.EntityManagerFactoryImpl.initialisePMF(EntityManagerFactoryImpl.java:482)
          at org.datanucleus.jpa.EntityManagerFactoryImpl.&lt;init&gt;(EntityManagerFactoryImpl.java:255)
          at org.datanucleus.store.appengine.jpa.DatastoreEntityManagerFactory.&lt;init&gt;(DatastoreEntityManagerFactory.java:68)
          at org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider.createContainerEntityManagerFactory(DatastorePersistenceProvider.java:45)
          at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:224)
          at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
          at java.security.AccessController.doPrivileged(Native Method)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
          at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
          at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
          at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
          at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
          at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1245)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
          at java.security.AccessController.doPrivileged(Native Method)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
          at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
          at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
          at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
          at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
          at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
          at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
          at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
          at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
          at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530)
          at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
          at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
          at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)
          at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
          at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
          at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
          at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
          at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
          at org.mortbay.jetty.Server.doStart(Server.java:217)
          at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
          at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:181)
          at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:116)
          at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:217)
          at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:162)
          at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
          at com.google.appengine.tools.development.DevAppServerMain.&lt;init&gt;(DevAppServerMain.java:113)
          at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:89)
  The server is running at http://localhost:1234/
  </code></pre>
  
  <p>I'm a little confused over this, since I have the same application running locally on GlassFish/MySQL. All I have done is to swap in the relevant jar files, and change the <code>persistence.xml</code>.</p>
  
  <p>My applicationContext.xml looks as follows : </p>
  
  <pre><code>&lt;context:annotation-config/&gt;
      &lt;bean id="clientDao" class="com.jameselsey.salestracker.dao.jpa.JpaDaoClient"&gt;
          &lt;property name="entityManagerFactory" ref="entityManagerFactory"/&gt;
      &lt;/bean&gt;
  
      &lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"/&gt;
  
      &lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
          &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
      &lt;/bean&gt;
  
  
      &lt;bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
    class="com.jameselsey.salestracker.util.GaeFixInternalPersistenceAnnotationProcessor" /&gt;
  
  
  
      &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;
  
      &lt;tx:annotation-driven/&gt;
  
      &lt;bean id="clientService" class="com.jameselsey.salestracker.service.ClientService"/&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>My JPA DAO looks like this</p>
  
  <pre><code>public class JpaDao extends JpaDaoSupport
  {
      protected &lt;T&gt; List&lt;T&gt; findAll(Class&lt;T&gt; clazz)
      {
          return getJpaTemplate().find("select c from " + clazz.getName() + " c");
      }
      protected &lt;T&gt; T findOne(String jpql, Map params)
      {
          List&lt;T&gt; results = getJpaTemplate().findByNamedParams(jpql, params);
          if(results.isEmpty())
          {
              return null;
          }
          if(results.size() &gt; 1)
          {
              throw new IncorrectResultSizeDataAccessException(1, results.size());
          }
          return results.get(0);
      }
  }
  </code></pre>
  
  <p>And an example implemented method looks like this : </p>
  
  <pre><code>@Override
      public Client getClientById(Integer clientId)
      {
          String jpql = "SELECT c " +
                  "FROM com.jameselsey.salestracker.domain.Client c " +
                  "WHERE c.id = " + clientId;
  
          return (Client) getJpaTemplate().find(jpql).get(0);
      }
  </code></pre>
  
  <p>Like I say, this works ok on Glassfish/MySQL, is it possible this error could be a red herring to something else?</p>