为什么在托管模式下运行GWT App Engine应用程序时会出现ClassNotPersistableException?

当我尝试在GWT / App Engine应用程序的本地JDO数据存储上执行查询时,我正在随机获取org.datanucleus.exceptions.ClassNotPersistableException。 这只发生在我在托管模式下运行应用程序时。 当我将它部署到Google App Engine时,一切都很完美。

堆栈跟踪:

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类是一个非常简单的JDO持久化类:

@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; } 

}

数据存储区查询通过以下方法执行:

 public ArrayList getPosts() { final ArrayList posts = new ArrayList(); final PersistenceManager persistenceManager = PMF.get() .getPersistenceManager(); final Extent winePostExtent = persistenceManager.getExtent( WinePost.class, false); for (final WinePost winePost : winePostExtent) { posts.add(winePost.getWinePostModel()); } winePostExtent.closeAll(); return posts; } 

我很确定您的代码没有任何问题。 您收到此错误的原因是Datanucleus增强器出现问题。

如果您看到此错误,请退出Jetty并检查Eclipse内的控制台(您需要在控制台窗口上方的小工具栏中选择正确的控制台)。 它应该说:

DataNucleus Enhancer(版本1.1.4):类的增强DataNucleus Enhancer已成功完成X类。 计时:输入= 547毫秒,增强= 76毫秒,总计= 623毫秒。 有关详细信息,请参阅日志

…其中X是它处理的类数。 该数字应该等于您定义的“实体”数量。

但有时,由于某种原因,它会说0,这就是为什么你得到ClassNotPersistableException错误。

要修复,打开实体类并更改某些内容(添加空格或其他内容)并保存。 检查控制台,直到它说它已经增强了所有实体类。 然后重新启动调试器并再试一次。

尽管这是一个老线程,但是为任何遇到同样问题的人发布以供将来参考。

我遇到了“同样”的问题,发现我的类路径有多个datanucleus-appengine-1.0.7.final.jar实例。 当我尝试构建我的工作区时,我从日志中了解到这一点。 这是日志内容。

java.lang.RuntimeException:com.google.appengine.toolsr.Enhancer.execute(Enhancer.java:59)在com.google.appengine.tools.enhancer.Enhance。(Enhance.java:60)处出现意外exceptioncom.google.appengine.tools.enhancer.Enhance.main(Enhance.java:41)由sun.reflect.NativeMethodAccessorImpl.invoke的sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)引起的java.lang.reflect.InvocationTargetException (NativeMethodAccessorImpl.java:39)位于com.google.appengine.tools.enhancer的java.lang.reflect.Method.invoke(Method.java:597)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)。 Enhancer.execute(Enhancer.java:57)… 2更多引起:org.datanucleus.exceptions.NucleusException:插件(Bundle)“org.datanucleus.store.appengine”已经注册。 确保类路径中没有相同插件的多个JAR版本。 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“已经注册,您正在尝试注册位于URL的相同插件”文件:/ G:/WS_Quotemandu/quotemandu/war/WEB-INF/lib/datanucleus-appengine-1.0。 7.final.jar“。 org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:434)org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:340)org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensions(NonManagedPluginRegistry.java:222) )org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensionPoints(NonManagedPluginRegistry.java:153)org.datanucleus.plugin.PluginManager.registerExtensionPoints(PluginManager.java:82)org.datanucleus.OMFContext。(OMFContext.java:160)at atg.datanucleus。 org.datanucleus.enhancer.DataNucleusEnhancer。(DataNucleusEnhancer.java:172)org.datanucleus.enhancer.DataNucleusEnhancer。(DataNucleusEnhancer.java:150)org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1157)..还有7个

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

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

希望这可以帮助!

我之前看过一些非常相似的东西,它与persistantManager同时被不同的方法调用有关。 这种情况发生’因为pm应该是单个实例 (不是单例,所以你必须自己管理它)。

一旦部署,开发环境和生产环境之间的条件可能会发生变化,这也可以解释您所看到的内容。

通过在使用pm的方法的声明中使用synchronized来解决该问题。

也许这不是你的情况,但你可能想尝试一下。

由于安装了2个版本,我遇到了同样的问题。

首先我安装了Google App Engine Sdk 1.8.8 ,然后进行了更新,eclipse下载了Google App Engine Sdk 1.8.9

有两个版本导致抛出此错误。 尽管一切编译得很好,我没有意识到datanucleus增强器控制台日志在编译时警告我这个错误,只是发现控制台存在;-)

在我的例子中,解决方案是仅保留删除旧版本的新版本:

  • 右键单击项目 – >属性
  • 深入研究Google / App Engine
  • 在右侧,您将看到名为Configure SDKs的按钮链接
  • 将打开一个新窗口,显示安装的所有SDK版本
  • 选择不需要的版本并单击“ 删除”按钮

在此处输入图像描述

确保完全删除旧版本(1.8.8):

  • 打开文件资源管理器C:\Users\XXX\.eclipse\org.eclipse.platform_4.3.0_1709980481_win32_win32_x86_64\plugins ,其中XXX是您的Windows用户。
  • 如果存在com.google.appengine.eclipse.sdkbundle_1.8.8文件夹,请将其删除!

现在,如果您打开datanucleus enhancer控制台,该类似乎已成功增强。

datanucleus enhancer控制台日志

检查您的编译器版本。 应该是1.7或更少。 它不应该是1.8。 我也有同样的事情,我改变了编译器,然后它对我有用。

我遇到过同样的问题。 在我的情况下,代码在构建期间通过maven clean + install正确处理,请参阅下面的日志摘录:

ENHANCED(Persistable):nl.jdoexample.model.Product ENHANCED(Persistable):nl.jdoexample.model.Book

出现问题的是,在执行之前执行(在Intellij中)(参见此运行/调试配置),执行命令’make’,从而删除增强的java文件。 这导致错误弹出。

在Intellij中修复问题(但也可以在Eclipse或Netbeans中完成): – jdo-example – 生命周期: – 编辑配置(运行/调试配置): – jdo-example [install]命令行:clean install

  • 运行/调试配置: – 应用程序: – 删除’make’ – 新执行定义: – 名称:execute main jdoExample – 配置: – 主类:nl.jdoexample.main

这样,在执行之前不会再次编译应用程序,从而删除增强的java文件。 这在我的情况下是成功的。 希望这可以帮助。

“类com.wayd.server.beans.WinePost”不是可持久的。这意味着它要么没有被增强,要么文件的增强版本不在CLASSPATH中(或者被未增强的版本隐藏),或找不到该类的元数据/注释。“

那么为什么不检查这三个条件呢? 其中一个是真的。