1

I am refactoring a GAE application which I developed few years ago (and works fine) to use Maven and Java 8. The application uses JDO & datanucleus. The app is being built with no errors and I can browse to the home page, but I encounter the following error when trying to access the database (for user-password validation at first phase...):

javax.jdo.JDOUserException: Persistent class "Class com.yang.model.User does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output." has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class.

I think i've read any forum question that can be related, including this one with no success of solving this.

Is there a special configuration that I should apply in order to init the database \ refer it locally or something with my code or environment is wrong? (I didn't try to deploy it as I have real users that use the app and I don't want to put it into risk...).

I made a lot of changes in configuration files and versions but didn't touch the java classes that access the database.

This is my 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-SNAPSHOT</version>

  <groupId>com.yang.astrology</groupId>
  <artifactId>yang-wisdom</artifactId>

  <properties>
    <appengine.maven.plugin.version>1.9.63</appengine.maven.plugin.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
    <spring.version>5.0.5.RELEASE</spring.version>
    <appengine.version>1.9.59</appengine.version>
    <datanucleus.version>3.1.0-release</datanucleus.version>
  </properties>

  <prerequisites>
    <maven>3.5.3</maven>
  </prerequisites>

  <dependencies>
    <!-- Compile/runtime dependencies -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.google.appengine</groupId>
      <artifactId>appengine-api-1.0-sdk</artifactId>
      <version>${appengine.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.google.appengine</groupId>
        <artifactId>appengine-endpoints</artifactId>
        <version>${appengine.version}</version>
    </dependency>

    <dependency>
       <groupId>com.google.appengine.orm</groupId>
       <artifactId>datanucleus-appengine</artifactId>
       <version>2.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.datanucleus</groupId>
        <artifactId>datanucleus-core</artifactId>
        <version>${datanucleus.version}</version>
    </dependency>
    <dependency>
        <groupId>org.datanucleus</groupId>
        <artifactId>datanucleus-api-jdo</artifactId>
        <version>${datanucleus.version}</version>
    </dependency>
    <dependency>
        <groupId>com.google.appengine</groupId>
        <artifactId>appengine-endpoints-deps</artifactId>
        <version>1.9.21</version>
    </dependency>   

    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.2</version>
    </dependency>


    <!-- Test Dependencies -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>


    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.4</version>
    </dependency>
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
     <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>persistence-api</artifactId>
        <version>1.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.jdo/ -->
    <dependency>
        <groupId>javax.jdo</groupId>
        <artifactId>jdo-api</artifactId>
        <version>3.1</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.gwt/gwt-servlet -->
    <dependency>
        <groupId>com.google.gwt</groupId>
        <artifactId>gwt-servlet</artifactId>
        <version>2.8.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.4</version>
    </dependency>

    <dependency>
        <groupId>com.torunski.crawler</groupId>
        <artifactId>crawler</artifactId>
        <version>0.6.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.11.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/net.sf.jtidy/jtidy -->
    <dependency>
        <groupId>net.sf.jtidy</groupId>
        <artifactId>jtidy</artifactId>
        <version>r938</version>
    </dependency>

  </dependencies>


  <build>
    <!-- for hot reload of the web application-->
    <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
    <pluginManagement>
        <plugins>
              <plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>maven-datanucleus-plugin</artifactId>
                <version>3.2.0-m1</version>
                <configuration>
                    <api>JDO</api>
                    <props>${basedir}/datanucleus.properties</props>
                    <verbose>true</verbose>
                    <enhancerName>ASM</enhancerName>
                </configuration>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.datanucleus</groupId>
                        <artifactId>datanucleus-core</artifactId>
                        <version>3.1.3</version>
                    </dependency>
                </dependencies>
            </plugin>
            <!-- plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>maven-datanucleus-plugin</artifactId>
                <version>3.1.0-release</version>
                <configuration>
                    <api>JDO</api>
                    <props>${basedir}/datanucleus.properties</props>        
                </configuration>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.datanucleus</groupId>
                        <artifactId>datanucleus-core</artifactId>
                        <version>${datanucleus.version}</version>
                    </dependency>
                </dependencies>
            </plugin-->
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.5</version>
            <executions>
              <execution>
                <phase>compile</phase>
                <goals>
                  <goal>display-dependency-updates</goal>
                  <goal>display-plugin-updates</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>appengine-maven-plugin</artifactId>
            <version>${appengine.maven.plugin.version}</version>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.1.1</version>
        </plugin>
        </plugins>
    </pluginManagement>

  </build>
</project>

This is the jdoconfig.xml file (located in src\main\webapp\WEB-INF\classes\META-INF):

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

    <persistence-manager-factory name="transactions-optional">
        <property name="javax.jdo.PersistenceManagerFactoryClass"
            value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>
        <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
        <property name="javax.jdo.option.NontransactionalRead" value="true"/>
        <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
        <property name="javax.jdo.option.RetainValues" value="true"/>
        <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
        <property name="datanucleus.appengine.singletonPMFForName" value="true"/>
    </persistence-manager-factory>
</jdoconfig>

The .project file of my Eclipse project does contain the com.google.appengine.eclipse.core.enhancerbuilder (specifying it after reading about it in forums):

<buildCommand>
        <name>com.google.appengine.eclipse.core.enhancerbuilder</name>
        <arguments>
        </arguments>
</buildCommand>

And I've downloaded the latest google app engine sdk (1.9.63).

This is how I access the DB:

public final class PMF {
    private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");

    private PMF() {
    }

    public static PersistenceManagerFactory get() {
        return pmfInstance;
    }
}

And in the DAO:

protected PersistenceManager getManager() {
    if (persistenceManager == null || persistenceManager.isClosed()) {
        persistenceManager = PMF.get().getPersistenceManager();
    }

    return persistenceManager;
}

public User findByUsername(String username) {
    Query q = getManager().newQuery(User.class);
    q.setFilter("username == usernameParam");
    q.declareParameters("String usernameParam");

    List<User> results = (List<User>) q.execute(username);
    if (results.isEmpty()) {
        return null;
    }

    return results.get(0);
}

I will really appreciate any assistance.

  • Hi there, does it work if you run the local server from the terminal using the app-maven-plugin? e.g. `mvn appengine:run`. – Patrick Flynn Apr 23 '18 at 12:43
  • I actually can't answer it since I eventually gave up and refactored the code to use the Google Datastore instead (the implementation was super easy BTW... The only thing left is to convert the old data structure to the new one. Thanks for your response... – Carmel Baumel-Ezra Apr 24 '18 at 06:48
  • Happy to hear it! – Patrick Flynn Apr 25 '18 at 12:52

0 Answers0