GWT + Google App EngineとJDOを使用して、AppEngineデータストアにオブジェクトを保存しています。
以下のオブジェクトをウェブインターフェースを介してクライアント側で作成し、RemoteProcedureCallを介してサーバーに渡します。サーバーでオブジェクトはGoogleAppEngineデータストアに保存されます。オブジェクトがサーバーに正常に送信されるため、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
あなたの役に立つ答えを見るのを楽しみにしています!
前もって感謝します!