GWT + JDO = ClassCastException

时间:2013-03-10 20:45:46

标签: google-app-engine google-cloud-datastore jdo gwt-rpc

我正在使用GWT + Google App Engine和JDO在App Engine数据存储区中存储对象。

我在客户端通过Web界面创建下面的对象,并通过RemoteProcedureCall将其传递到服务器,并将其存储到Google App Engine数据存储区中。当对象成功传输到服务器时,RPC工作正常。但是当我在服务器上调用pm.makePersistent(myCustomObject)时,它会崩溃并显示以下错误日志:

  

java.lang.ClassCastException:org.datanucleus.identity.IdentityReference无法强制转换为org.datanucleus.identity.OID

要存储的对象:

package at.fhooe.mc.shared;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.annotations.EmbeddedOnly;
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.gwt.user.client.rpc.IsSerializable;

@PersistenceCapable
public class Questionnaire implements IsSerializable {

// ************************************
// * MEMBER VARIABLES
// ************************************

/**
 * Unique identifier of the questionnaire. This Id is used as primary key in
 * the datastore.
 */
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
String key;

/**
 * Title of the questionnaire.
 */
private String m_title;

/**
 * List of the actual questions in the questionnaire.
 */
@Persistent
private List<Question> m_questions;

// ************************************
// * CONSTRUCTOR
// ************************************

/**
 * Constructor.
 */
public Questionnaire() {
    m_questions = new ArrayList<Question>();
}

/**
 * Constructor.
 * 
 * @param _title
 *            Title of the questionnaire.
 */
public Questionnaire(String _title) {
    m_title = _title;
    m_questions = new ArrayList<Question>();
}

// ************************************
// * GETTERS / SETTERS
// ************************************

/**
 * Gets the Id of the question. This Id is also used as primary key in the
 * datastore.
 * 
 * @return Id the questionnaire.
 */
public String getId() {
    return key;
}

/**
 * Gets the title of the questionnaire.
 * 
 * @return Title of the questionnaire as string.
 */
public String getTitle() {
    return m_title;
}

/**
 * Sets the title of the questionnaire.
 * 
 * @param _title
 *            Title of the questionnaire.
 */
public void setTitle(String _title) {
    m_title = _title;
}

/**
 * Gets all available questions of the questionnaire.
 * 
 * @return All available questions of the questionnaire.
 */
public List<Question> getQuestions() {
    return m_questions;
}

/**
 * Adds a question to the questionnaire.
 * 
 * @param _question
 *            The question to be added.
 */
public void addQuestion(Question _question) {

    m_questions.add(_question);

}

// ************************************
// * INNER CLASS
// ************************************

/**
 * This class represents a single question of a questionnaire. It consists
 * of the actual question-text and the answer-type.
 */
@PersistenceCapable
@EmbeddedOnly
public static class Question implements IsSerializable {

    /**
     * Defines the answer-type of the question (e.g.: yes-or-no,
     * likert-scale, etc).
     */
    public enum AnswerType {

        YES_OR_NO("yes_or_no"), LIKERT("likert");

        private String stringValue;

        private AnswerType(String _stringValue) {
            stringValue = _stringValue;
        }

        @Override
        public String toString() {
            return stringValue;
        }
    }

    public Question() {

    }

    /**
     * Constructor.
     * 
     * @param _text
     *            The actual question as String.
     * @param _answerType
     *            The answertype as enum.
     * @param _answer
     *            The user-answer.
     */
    public Question(String _text, AnswerType _answerType, int _answer) {
        m_text = _text;
        m_answerType = _answerType;
        m_answer = _answer;
    }

    /**
     * The selected answer-type of the question.
     */
    @Persistent
    private AnswerType m_answerType;

    /**
     * The actual question as string.
     */
    @Persistent
    private String m_text;

    /**
     * The actual answer to the question.
     */
    @Persistent
    private int m_answer;

}

}

生成的堆栈跟踪:

javax.servlet.ServletContext log: Exception while dispatching incoming RPC call
com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract void at.fhooe.mc.client.PushMessageService.sendMessages(at.fhooe.mc.shared.Questionnaire)' threw an unexpected exception: java.lang.ClassCastException: org.datanucleus.identity.IdentityReference cannot be cast to org.datanucleus.identity.OID
at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:389)
at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:579)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:409)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: java.lang.ClassCastException: org.datanucleus.identity.IdentityReference cannot be cast to org.datanucleus.identity.OID
at com.google.appengine.datanucleus.EntityUtils.extractChildKey(EntityUtils.java:915)
at com.google.appengine.datanucleus.StoreFieldManager.getDatastoreObjectForCollection(StoreFieldManager.java:983)
at com.google.appengine.datanucleus.StoreFieldManager.storeRelations(StoreFieldManager.java:877)
at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:367)
at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218)
at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381)
at org.datanucleus.state.JDOStateManager.makePersistent(JDOStateManager.java:2357)
at org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:1896)
at org.datanucleus.ObjectManagerImpl.persistObjectWork(ObjectManagerImpl.java:1745)
at org.datanucleus.ObjectManagerImpl.persistObject(ObjectManagerImpl.java:1602)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:731)
at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:756)
at at.fhooe.mc.server.PushMessageServiceImpl.sendMessages(PushMessageServiceImpl.java:38)
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.development.agent.runtime.Runtime.invoke(Runtime.java:115)
at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:561)
... 38 more

期待看到您的有用答案!

提前致谢!

0 个答案:

没有答案