3

I am trying to build my first Google App Engine WAR and am setting up my own external (outside of Eclipse) Ant build to be executed from the terminal. I'm trying to get the <enhance_war/> Ant macro working and am running into a bizarre NoSuchMethodError.

Here's my Ant target:

<target name="package" depends="gendocs">
    <echo message="Enhancing WAR JDO classes." />
    <enhance_war war="war" />

    <echo message="Packaging the WAR file." />
    <war destfile="gen/dist/myapp.war" webxml="war/web.xml">
        <fileset dir="war">
            <includes name="**/*.xml" />
        </fileset>
        <lib dir="war/WEB-INF/lib" />
        <classes dir="war/WEB-INF/classes" />
    </war>
</target>

Here's the Ant output when it attempts to execute the package target:

package:
     [echo] Enhancing WAR JDO classes.
  [enhance] Encountered a problem: Unexpected exception
  [enhance] Please see the logs [/tmp/enhance4426322586552955387.log] for further information.

BUILD FAILED
/home/myuser/sandbox/workbench/eclipse/workspace/myapp/build/build-local.xml:193: The following error occurred while executing this line:
/home/myuser/sandbox/workbench/google/gae-sdk/1.7.1/appengine-java-sdk-1.7.1/config/user/ant-macros.xml:95: Java returned: 1

That ant-macros.xml:95 corresponds to the following line:

<enhance failonerror="true" api="@{api}">
    <!-- Rest of the enhance task def -->
</enhance>

So something is going wrong while executing this <enhance /> task, but I can't figure out what.

And finally the log file at /tmp/enhance4426322586552955387.log:

java.lang.RuntimeException: Unexpected exception
    at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:76)
    at com.google.appengine.tools.enhancer.Enhance.<init>(Enhance.java:71)
    at com.google.appengine.tools.enhancer.Enhance.main(Enhance.java:51)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:74)
    ... 2 more
Caused by: java.lang.NoSuchMethodError: org.datanucleus.plugin.PluginManager.<init>(Lorg/datanucleus/PersistenceConfiguration;Lorg/datanucleus/ClassLoaderResolver;)V
    at org.datanucleus.OMFContext.<init>(OMFContext.java:159)
    at org.datanucleus.enhancer.DataNucleusEnhancer.<init>(DataNucleusEnhancer.java:172)
    at org.datanucleus.enhancer.DataNucleusEnhancer.<init>(DataNucleusEnhancer.java:150)
    at org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1157)
    ... 7 more

What's going on here? I don't think it's a classpath issue because the org.datanucleus.plugin.PluginManager class is defined inside of datanucleus-core-1.1.5.jar, which I absolutely have on the build classpath. Plus its a NoSuchMethodError, so it makes me feel like I have a JAR hell/versioning issue going on. Any ideas?

IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • 1
    If the enhancer process says that method doesn't exist (in its CLASSPATH) then it doesn't. So you have some other version of datanucleus-core present with the enhancer. Obviously that is an old unsupported version of DataNucleus in use there so better advised to use something recent (with a recent GAE JDO plugin) – DataNucleus Jan 28 '13 at 08:26
  • Thanks @DataNucleus (+1) - I see another version of DataNucleus under `lib/opt/user/v2/datanucleus`... it's version 3.1.0-m3. Could this be the more recent plugin you're speaking of? – IAmYourFaja Jan 28 '13 at 13:05

1 Answers1

1

You have a different version of datanucleus-core in your classpath to what the enhancer requires. Verify what the enhancer is using and fix it. See http://code.google.com/p/datanucleus-appengine/wiki/Compatibility for conpatibility requirements.

The latest GAE SDK provides "GAE JDO plugin" v2.1.1 IIRC, which is the most recent release (though there is more recent not yet released fwiw), and it is present under lib/opt/blahblahblah. This makes use of DataNucleus v3.1.x. This is what people are recommended to run against. The GAE JDO plugin is developed at http://code.google.com/p/datanucleus-appengine/

DataNucleus
  • 15,497
  • 3
  • 32
  • 37
  • Thanks again @DataNucleus (+1) - I think your statement "*Verify what the enhancer is using and fix it*" is the root of my problem. I found the `EnhancerTask` (what the `ant-macros.xml` is using under the hood for the `` task) and looked at it's source code, but it didn't help me verify what JDO/DataNucleus classes or versions it was looking for. How would you verify the JAR dependencies here? Once I find the exact JARs that `` is running against, I can change them, or tweak the `ant-macros.xml` file to point to the correct JAR(s)/versions. Thanks again! – IAmYourFaja Jan 28 '13 at 18:39
  • The DN enhancer EnhancerTask takes in a classpath arg, as per http://www.datanucleus.org/products/accessplatform_3_1/enhancer.html#ant so somewhere this is being set. – DataNucleus Jan 28 '13 at 19:09
  • The Ant `` arg that the `ant-macros.xml` file configures consists of two `pathelements` and a `fileset`; collectively: `war/WEB-INF/lib`, `war/WEB-INF/classes` and `${GAE_SDK_HOME}/lib/appengine-tools-api.jar` are set to this `classpath` arg. Inside `war/WEB-INF/lib` are the correct versions (3.1.0) of all the `datanucleus` JARs. I guess these were put there automatically for me when I used the Google-Eclipse plugin to create a new Web Application Project. – IAmYourFaja Jan 28 '13 at 19:50
  • So I guess I do have the right JARs on the classpath that the enhancer task is using. As part of my Ant build I am pulling in older `datanucleus` JARs (out of ignorance) into `MyApp/lib/main` and then adding them to a `build.classpath` Ant PATH. But this `build.classpath` should have nothing to do with the classpath arg that the enhance task is using, so I'm still at a loss as to how I'm getting the original error... – IAmYourFaja Jan 28 '13 at 19:52
  • 1
    your error was using the older version of the GAE JDO plugin (v1.x) which needs DN 1.1, and it had DN3.x in the enhancer classpath hence the exception. If you're now using GAE JDO plugin v2.x then you need DN3.x in the classpath for the enhancer. Depends which GAE plugin you're using now – DataNucleus Jan 28 '13 at 19:54
  • Starting to make sense...just so you understand, this is still not fixed (from your last response I can't tell if I am implying that I fixed this!). So it sounds like the GAE JDO "plugin" is the culprit here: if you use v1, then you need DN 1.1. If you use v2 of the plugin, then you need DN 3.x. Is that correct? It sounds like I am using v1 of the plugin, but have DN 3.x on the classpath - is this what you're telling me? If so, how do I configure which plugin (v1 or v2) to use? Thanks again for all your help so far! – IAmYourFaja Jan 28 '13 at 20:02
  • Google docs explain all about how to use v2 https://developers.google.com/appengine/docs/java/datastore/jdo/overview-dn2 see some "enhancerVersion=v2" amongst other things. – DataNucleus Jan 28 '13 at 20:10