Why do I get ClassNotPersistableException while ru

2019-04-19 05:34发布

I am randomly getting an org.datanucleus.exceptions.ClassNotPersistableException when I try to perform a query on the local JDO data store of my GWT/App Engine application. This only happens when I run the application on Hosted mode. When I deploy it to the Google App Engine everything works perfectly.

Stack Trace:

org.datanucleus.exceptions.ClassNotPersistableException: The class "com.wayd.server.beans.WinePost" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
    at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:305)
    at org.datanucleus.ObjectManagerImpl.getExtent(ObjectManagerImpl.java:3700)
    at org.datanucleus.jdo.JDOPersistenceManager.getExtent(JDOPersistenceManager.java:1515)
    at com.wayd.server.WinePostServiceImpl.getPosts(WinePostServiceImpl.java:212)
    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:585)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:527)
    ... 25 more
Caused by: org.datanucleus.exceptions.ClassNotPersistableException: The class "com.wayd.server.beans.WinePost" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found.
    at org.datanucleus.ObjectManagerImpl.assertClassPersistable(ObjectManagerImpl.java:3830)
    at org.datanucleus.ObjectManagerImpl.getExtent(ObjectManagerImpl.java:3693)
    ... 32 more)

WinePost class is a very simple JDO persistence capable class:

@PersistenceCapable(identityType = IdentityType.APPLICATION) public class WinePost {

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private User author;

@Persistent
private String grape;

@Persistent
private String comment;

public WinePost(final User author, final String grape,
        final String comment) {
    super();
    this.grape = grape;
    this.comment = comment;
}

public User getAuthor() {
    return author;
}

public void setAuthor(final User author) {
    this.author = author;
}

public Long getId() {
    return id;
}

public void setId(final Long id) {
    this.id = id;
}

public String getGrape() {
    return grape;
}

public void setGrape(final String grape) {
    this.grape = grape;
}

public String getComment() {
    return comment;
}

public void setComment(final String comment) {
    this.comment = comment;
}

public String getUserNickname() {
    String retVal = null;
    if (author != null) {
        retVal = author.getNickname();
    }
    return retVal;
}

public WinePostModel getWinePostModel() {
    final WinePostModel winePostModel = new WinePostModel(grape, vintage, getUserNickName());
    return winePostModel;
}

}

The datastore query is performed by the following method:

public ArrayList<WinePostModel> getPosts() {
        final ArrayList<WinePostModel> posts = new ArrayList<WinePostModel>();
        final PersistenceManager persistenceManager = PMF.get()
        .getPersistenceManager();

        final Extent<WinePost> winePostExtent = persistenceManager.getExtent(
                WinePost.class, false);
        for (final WinePost winePost : winePostExtent) {
            posts.add(winePost.getWinePostModel());
        }
        winePostExtent.closeAll();

        return posts;
    }

7条回答
Animai°情兽
2楼-- · 2019-04-19 05:39

Posting for future reference for anybody running into same problem, despite this being an old thread.

I ran into the 'same' problem, and found that my classpath had multiple instances of datanucleus-appengine-1.0.7.final.jar. I got to know this from the log which was prompted when I tried to build my workspace. Here's the log content.

java.lang.RuntimeException: Unexpected exception at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:59) at com.google.appengine.tools.enhancer.Enhance.(Enhance.java:60) at com.google.appengine.tools.enhancer.Enhance.main(Enhance.java:41) 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:57) ... 2 more Caused by: org.datanucleus.exceptions.NucleusException: Plugin (Bundle) "org.datanucleus.store.appengine" is already registered. Ensure you dont have multiple JAR versions of the same plugin in the classpath. The URL "file:/G:/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.4_1.3.4.v201005212032/appengine-java-sdk-1.3.4/lib/user/orm/datanucleus-appengine-1.0.7.final.jar" is already registered, and you are trying to register an identical plugin located at URL "file:/G:/WS_Quotemandu/quotemandu/war/WEB-INF/lib/datanucleus-appengine-1.0.7.final.jar." at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:434) at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:340) at org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensions(NonManagedPluginRegistry.java:222) at org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensionPoints(NonManagedPluginRegistry.java:153) at org.datanucleus.plugin.PluginManager.registerExtensionPoints(PluginManager.java:82) at org.datanucleus.OMFContext.(OMFContext.java:160) at org.datanucleus.enhancer.DataNucleusEnhancer.(DataNucleusEnhancer.java:172) at org.datanucleus.enhancer.DataNucleusEnhancer.(DataNucleusEnhancer.java:150) at org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1157) ... 7 more

G:/eclipse/plugins/com.google.appengine.eclipse.sdkbundle.1.3.4_1.3.4.v201005212032/appengine-java-sdk-1.3.4/lib/user/orm/datanucleus-appengine-1.0.7.final.jar

file:/G:/WS_Quotemandu/quotemandu/war/WEB-INF/lib/datanucleus-appengine-1.0.7.final.jar

Hope this helps!

查看更多
一纸荒年 Trace。
3楼-- · 2019-04-19 05:39

I had the same issue, caused by having 2 versions installed.

First I had installed Google App Engine Sdk 1.8.8, then an update came in and eclipse downloaded Google App Engine Sdk 1.8.9.

Having the 2 versions caused this error to be thrown. Despite everything compiled well, I didn't realize that datanucleus enhancer console log was warning me about this error on compilation time, just discovered that console existed ;-)

The solution, in my case, was to keep only the newer version removing the old one:

  • Right click on porject -> Properties
  • Drill down to Google/App Engine
  • On the right side, you will see a button link named Configure SDKs
  • A new window opens showing all SDK versions installed
  • Select undesired versions and click Remove button

enter image description here

To ensure the old version (1.8.8) was completely removed:

  • Open file explorer C:\Users\XXX\.eclipse\org.eclipse.platform_4.3.0_1709980481_win32_win32_x86_64\plugins where XXX is your Windows user.
  • If folder com.google.appengine.eclipse.sdkbundle_1.8.8 exists, delete it!

Now, if you open the datanucleus enhancer console, the class appears successfully enhanced.

datanucleus enhancer console log

查看更多
We Are One
4楼-- · 2019-04-19 05:45

"The class "com.wayd.server.beans.WinePost" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found."

So why not check each of those 3 conditions ? One of them is true.

查看更多
老娘就宠你
5楼-- · 2019-04-19 05:52

I've seen something very similar before and it was related to the persistantManager being called by different methods at the same time. This happens 'cause the pm is supposed to be a single instance (which is not a singleton so you have to manage it yourself).

Conditions could change between the development environment and the production one once deployed, so that could explain also what you're seeing.

The problem was solved by using synchronized in the declarations of methods which use the pm.

Maybe it's not your case but you might wanna give it a shot.

查看更多
来,给爷笑一个
6楼-- · 2019-04-19 05:58

Check for your compiler version. It should be 1.7 or less. It should not be 1.8. I also got the same thing and I changed the compiler, then it worked for me.

查看更多
劫难
7楼-- · 2019-04-19 05:59

I am pretty sure there's nothing wrong with your code. The reason you get this error is because of a problem with the Datanucleus enhancer.

If you see this error, quit Jetty and check the console inside Eclipse (you'll need to select the correct console in the little toolbar above the console window). It should say something like:

DataNucleus Enhancer (version 1.1.4) : Enhancement of classes DataNucleus Enhancer completed with success for X classes. Timings : input=547 ms, enhance=76 ms, total=623 ms. Consult the log for full details

... where X is the number of classes it has processed. The number should be equal to the number of 'entity' classed you have defined.

But sometimes, for some reason it will say 0 which is why you get the ClassNotPersistableException error.

To fix, open an entity class and change something (add a space or something) and save. Check the console until it says that it has enhanced all of your entity classes. Then restart the debugger and try again.

查看更多
登录 后发表回答