java 为什么在托管模式下运行 GWT App Engine 应用程序时会出现 ClassNotPersistableException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1004968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do I get ClassNotPersistableException while running GWT App Engine application in hosted mode?
提问by Otavio
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.
当我尝试对我的 GWT/App Engine 应用程序的本地 JDO 数据存储执行查询时,我随机得到一个 org.datanucleus.exceptions.ClassNotPersistableException。这仅在我在托管模式下运行应用程序时发生。当我将它部署到 Google App Engine 时,一切正常。
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:
WinePost 类是一个非常简单的 JDO 持久化类:
@PersistenceCapable(identityType = IdentityType.APPLICATION) public class WinePost {
@PersistenceCapable(identityType = IdentityType.APPLICATION) 公共类 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;
}
回答by Mo'in Creemers
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.
我很确定您的代码没有任何问题。出现此错误的原因是 Datanucleus 增强器存在问题。
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:
如果您看到此错误,请退出 Jetty 并检查 Eclipse 中的控制台(您需要在控制台窗口上方的小工具栏中选择正确的控制台)。它应该是这样的:
DataNucleus Enhancer (version 1.1.4) : Enhancement of classes DataNucleus Enhancer completed with success for Xclasses. Timings : input=547 ms, enhance=76 ms, total=623 ms. Consult the log for full details
DataNucleus Enhancer(1.1.4 版):类的增强 DataNucleus Enhancer 已成功完成X类。计时:输入=547 毫秒,增强=76 毫秒,总计=623 毫秒。查看日志以获取完整详细信息
... where Xis the number of classes it has processed. The number should be equal to the number of 'entity' classed you have defined.
... 其中X是它已处理的类数。该数量应等于您定义的“实体”分类数量。
But sometimes, for some reason it will say 0 which is why you get the ClassNotPersistableException error.
但有时,出于某种原因,它会说 0,这就是您收到 ClassNotPersistableException 错误的原因。
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.
要修复,打开一个实体类并更改某些内容(添加空格或其他内容)并保存。检查控制台,直到它说它已经增强了您的所有实体类。然后重新启动调试器并重试。
回答by James
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.
我遇到了“相同”的问题,发现我的类路径有多个 datanucleus-appengine-1.0.7.final.jar 实例。我从尝试构建工作区时提示的日志中了解到这一点。这是日志内容。
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
确保类路径中没有同一个插件的多个 JAR 版本。网址“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 "file:/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.registry2.java:340(NonManagedPluginRegistry.java:340) ) 在 org.datanucleus.plugin.NonManagedPluginRegistry。
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:/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 。罐
file:/G:/WS_Quotemandu/quotemandu/war/WEB-INF/lib/datanucleus-appengine-1.0.7.final.jar
文件:/G:/WS_Quotemandu/quotemandu/war/WEB-INF/lib/datanucleus-appengine-1.0.7.final.jar
Hope this helps!
希望这可以帮助!
回答by JohnIdol
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 singletonso you have to manage it yourself).
我以前见过非常相似的东西,它与同时被不同方法调用的persistantManager有关。发生这种情况是因为 pm 应该是单个实例(它不是单例,因此您必须自己管理它)。
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 synchronizedin the declarations of methods which use the pm.
这个问题是通过synchronized在使用 pm 的方法声明中使用来解决的。
Maybe it's not your case but you might wanna give it a shot.
也许这不是你的情况,但你可能想试一试。
回答by Rishi0405
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.
检查您的编译器版本。它应该是 1.7 或更小。它不应该是 1.8。我也得到了同样的东西,我改变了编译器,然后它对我有用。
回答by SamuGG
I had the same issue, caused by having 2 versions installed.
我有同样的问题,因为安装了 2 个版本。
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.
首先我安装了Google App Engine Sdk 1.8.8,然后有一个更新进来,eclipse 下载了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 ;-)
拥有 2 个版本会导致抛出此错误。尽管一切都编译得很好,但我没有意识到 datanucleus 增强器控制台日志在编译时警告我这个错误,只是发现控制台存在;-)
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 Removebutton
- 右键单击项目-> 属性
- 深入到 Google/App Engine
- 在右侧,您将看到一个名为Configure SDKs的按钮链接
- 将打开一个新窗口,显示已安装的所有 SDK 版本
- 选择不需要的版本,然后单击删除按钮


To ensure the old version (1.8.8) was completely removed:
为确保完全删除旧版本 (1.8.8):
- Open file explorer
C:\Users\XXX\.eclipse\org.eclipse.platform_4.3.0_1709980481_win32_win32_x86_64\pluginswhere XXX is your Windows user. - If folder
com.google.appengine.eclipse.sdkbundle_1.8.8exists, delete it!
- 打开文件资源管理器
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存在,删除它!
Now, if you open the datanucleus enhancer console, the class appears successfully enhanced.
现在,如果您打开 datanucleus 增强器控制台,该类将显示成功增强。


回答by Rob
I had the same issue. In my case the code was correctly processed during building via maven clean + install, see below the excerpt from the logging:
我遇到过同样的问题。在我的情况下,代码在通过 maven clean + install 构建过程中得到了正确处理,请参见下面的日志摘录:
ENHANCED (Persistable) : nl.jdoexample.model.Product ENHANCED (Persistable) : nl.jdoexample.model.Book
增强(持久):nl.jdoexample.model.Product 增强(持久):nl.jdoexample.model.Book
What went wrong was that when executing (in Intellij) prior to the execution (see for this Run / Debug Configurations) the command 'make' was executed, thereby removing the enhanced java files. This caused the error to pop up.
出错的是,在执行之前(在 Intellij 中)执行时(请参阅此运行/调试配置),执行了命令“make”,从而删除了增强的 java 文件。这导致错误弹出。
Reparation of the problem in Intellij (but can also be done in Eclipse or Netbeans): - jdo-example - Lifecycle: - edit configuration (Run / Debug Configurations): - jdo-example [install] Command line: clean install
修复 Intellij 中的问题(但也可以在 Eclipse 或 Netbeans 中完成): - jdo-example - 生命周期: - 编辑配置(运行 / 调试配置): - jdo-example [安装] 命令行:全新安装
- Run / Debug Configurations: -Application: - Remove 'make' - New execution definition: - Name: execute main jdoExample - Configuration: - Main class: nl.jdoexample.main
- 运行/调试配置:-应用程序:-删除'make'-新的执行定义:-名称:执行主jdoExample-配置:-主类:nl.jdoexample.main
In this way the application will not be compiled again before execution, thereby removing the enhanced java files. This was successful in my situation. Hope this helps.
这样应用程序在执行前就不会被再次编译,从而删除增强的java文件。这在我的情况下是成功的。希望这可以帮助。
回答by DataNucleus
"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."
“类“com.wayd.server.beans.WinePost”不是持久化的。这意味着它要么没有被增强,要么文件的增强版本不在CLASSPATH中(或被未增强版本隐藏),或者找不到该类的元数据/注释。”
So why not check each of those 3 conditions ? One of them is true.
那么为什么不检查这三个条件中的每一个呢?其中之一是真的。

