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

时间:2009-06-17 03:28:59

标签: java google-app-engine gwt

当我尝试在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) 公共类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<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 个答案:

答案 0 :(得分:15)

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

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

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

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

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

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

答案 1 :(得分:5)

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

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

java.lang.RuntimeException:意外的异常     在com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:59)     在com.google.appengine.tools.enhancer.Enhance。(Enhance.java:60)     在com.google.appengine.tools.enhancer.Enhance.main(Enhance.java:41) 引起: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)     在java.lang.reflect.Method.invoke(Method.java:597)     在com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:57)     ......还有2个 引起:org.datanucleus.exceptions.NucleusException:插件(Bundle)“org.datanucleus.store.appengine”已经注册。确保类路径中没有相同插件的多个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的相同插件”文件:/ 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)     在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

希望这有帮助!

答案 2 :(得分:2)

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

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

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

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

答案 3 :(得分:1)

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

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

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

在我的情况下,解决方案是仅保留删除旧版本的新版本:

  • 右键点击项目 - &gt;特性
  • 深入研究Google / App Engine
  • 在右侧,您会看到名为配置SDK
  • 的按钮链接
  • 将打开一个新窗口,显示已安装的所有SDK版本
  • 选择不需要的版本,然后点击删除按钮

enter image description here

确保完全删除旧版本(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 console log

答案 4 :(得分:1)

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

答案 5 :(得分:0)

我有同样的问题。 在我的情况下,代码在构建期间通过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'      - 新的执行定义:          - 名称:执行主jdoExample          - 配置:              - 主类:nl.jdoexample.main

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

答案 6 :(得分:-1)

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

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