java 有 JDO 问题的 GWT
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/988217/
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
GWT with JDO problem
提问by Maksim
I just start playing with GWT I'm having a really hard time to make GWT + JAVA + JDO + Google AppEngine working with DataStore. I was trying to follow different tutorial but had no luck. For example I wend to these tutorials: TUT1TUT2
我刚开始玩 GWT 我真的很难让 GWT + JAVA + JDO + Google AppEngine 与 DataStore 一起工作。我试图遵循不同的教程,但没有运气。例如我去了这些教程:TUT1 TUT2
I was not able to figure out how and what i need to do in order to make this work. Please look at my simple code and tell me what do i need to do so i can persist it to the datastore:
我无法弄清楚我需要做什么和做什么才能完成这项工作。请查看我的简单代码并告诉我我需要做什么才能将其持久化到数据存储区:
1. ADDRESS ENTITY
1. 地址实体
package com.example.rpccalls.client;
import java.io.Serializable;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
public class Address implements Serializable{
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private int addressID;
@Persistent private String address1;
@Persistent private String address2;
@Persistent private String city;
@Persistent private String state;
@Persistent private String zip;
public Address(){}
public Address(String a1, String a2, String city, String state, String zip){
this.address1 = a1;
this.address2 = a2;
this.city = city;
this.state = state;
this.zip = zip;
}
/* Setters and Getters */
}
2. PERSON ENTITY
2. 个人实体
package com.example.rpccalls.client;
import java.io.Serializable;
import java.util.ArrayList;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
@PersistenceCapable
public class Person implements Serializable{
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent private String name;
@Persistent private int age;
@Persistent private char gender;
@Persistent ArrayList<Address> addresses;
public Person(){}
public Person(String name, int age, char gender){
this.name = name;
this.age = age;
this.gender = gender;
}
/* Getters and Setters */
}
3. RPCCalls
3.RPC调用
package com.example.rpccalls.client;
import java.util.ArrayList;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
public class RPCCalls implements EntryPoint {
private static final String SERVER_ERROR = "An error occurred while attempting to contact the server. Please check your network connection and try again.";
private final RPCCallsServiceAsync rpccallService = GWT.create(RPCCallsService.class);
TextBox nameTxt = new TextBox();
Button btnSave = getBtnSave();
public void onModuleLoad() {
RootPanel.get("inputName").add(nameTxt);
RootPanel.get("btnSave").add(btnSave);
}
private Button getBtnSave(){
Button btnSave = new Button("SAVE");
btnSave.addClickHandler(
new ClickHandler(){
public void onClick(ClickEvent event){
saveData2DB(nameTxt.getText());
}
}
);
return btnSave;
}
void saveData2DB(String name){
AsyncCallback<String> callback = new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
Window.alert("WOOOHOOO, ERROR: " + SERVER_ERROR);
// TODO: Do something with errors.
}
public void onSuccess(String result) {
Window.alert("Server is saying: ' " + result + "'");
}
};
ArrayList<Address> aa = new ArrayList<Address>();
aa.add(new Address("123 sasdf","", "Some City", "AZ", "93923-2321"));
aa.add(new Address("23432 asdf", "Appt 34", "Another City", "AZ", "43434-4432"));
Person p = new Person();
p.setName(name);
p.setAge(23);
p.setGender('m');
p.setAddresses(aa);
// !!!!!!!!!!!!!!!!!! SERVER CALL !!!!!!!!!!!!!!!!!!
rpccallService.saveName(p, callback);
// !!!!!!!!!!!!!!!!!! SERVER CALL !!!!!!!!!!!!!!!!!!
}
}
4. RPCCallsService
4. RPCCallsService
package com.example.rpccalls.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath("calls")
public interface RPCCallsService extends RemoteService {
String saveName(Person p);
}
5. RPCCallsServiceAsync
5. RPCCallsServiceAsync
package com.example.rpccalls.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface RPCCallsServiceAsync {
void saveName(Person p, AsyncCallback<String> callback);
}
6. **RPCCalls.gwt.xml
6. **RPCCalls.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module rename-to='rpccalls'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<entry-point class='com.example.rpccalls.client.RPCCalls'/>
</module>
I tried to add Key class and everything else in those tutorials but it looks like i'm missing something.
我尝试在这些教程中添加 Key 类和其他所有内容,但看起来我遗漏了一些东西。
Here is my error: alt text http://vasura.s3.amazonaws.com/Picture2.png
这是我的错误: 替代文本 http://vasura.s3.amazonaws.com/Picture2.png
or before i was getting this error:
或在我收到此错误之前:
Key cannot be resolved to a type
键无法解析为类型
What is the best solution to make this working?
使这个工作的最佳解决方案是什么?
回答by dfrankow
Sriram Narayansays to String-encode the Key to get it to pass through GWT's RPC mechanism:
Sriram Narayan说对密钥进行字符串编码以使其通过 GWT 的 RPC 机制:
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class SomeDomainClass implements Serializable {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
String id;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class SomeDomainClass implements Serializable {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
String id;
回答by Sudhir Jonathan
回答by Nick Siderakis
You can use the Key class in GWT code by adding these additional jar files:
您可以通过添加这些额外的 jar 文件在 GWT 代码中使用 Key 类:
http://www.resmarksystems.com/code/
http://www.resmarksystems.com/code/
- appengine-utils-client-1.0.jar
- appengine-utils-server-1.0.jar
- appengine-utils-client-1.0.jar
- appengine-utils-server-1.0.jar
This basically gives the GWT compiler a GWT-friendly version of the Key and other AppEngine classes. (like Text, Blob and User..)
这基本上为 GWT 编译器提供了 Key 和其他 AppEngine 类的 GWT 友好版本。(如文本、Blob 和用户..)
To use:
使用:
- Add the appengine-utils-client-1.0.jar anywhere in your build path.
- Put the appengine-utils-server-1.0.jar in your WEB-INF/lib folder.
- Add the following to your GWT module:
- < inherits name="com.resmarksystems.AppEngineDataTypes"/>
- 在构建路径中的任意位置添加 appengine-utils-client-1.0.jar。
- 将 appengine-utils-server-1.0.jar 放在您的 WEB-INF/lib 文件夹中。
- 将以下内容添加到您的 GWT 模块中:
- <继承名称="com.resmarksystems.AppEngineDataTypes"/>
回答by Robert Munteanu
The second tutorial you've referenced has a section on shadowing the com.google.appengine.api.datastore.Keyclass, since it's not available to GWT:
您引用的第二个教程有一个关于隐藏com.google.appengine.api.datastore.Key类的部分,因为它不适用于 GWT:
Since I'm not doing anything with the Key class on the client I'm going to stub it out. This actually requires a few steps and involves the super-src feature of GWT XML module files.
因为我没有对客户端上的 Key 类做任何事情,所以我将把它存根。这实际上需要几个步骤,并且涉及 GWT XML 模块文件的 super-src 特性。
You might want to take a look at the GWT documentation, which states that
您可能需要查看GWT 文档,其中指出
The heart of GWT is a compiler that converts Java source into JavaScript
GWT 的核心是一个将 Java 源代码转换为 JavaScript 的编译器
, therefore you need to have the source code available to use a given class in the client code.
,因此您需要有可用的源代码才能在客户端代码中使用给定的类。
回答by digitaljoel
Another option would be to implement a DTO ( Data Transfer Object ) that you are using in the client instead of using the persistent objects directly. Or, you could go to JPA instead of JDO. In the example data class in the appengine JPA docs the Id is a Long instead of that Key implementation http://code.google.com/appengine/docs/java/datastore/usingjpa.html
另一种选择是实现您在客户端中使用的 DTO(数据传输对象),而不是直接使用持久对象。或者,您可以使用 JPA 而不是 JDO。在 appengine JPA 文档中的示例数据类中,Id 是 Long 而不是 Key 实现http://code.google.com/appengine/docs/java/datastore/usingjpa.html
回答by Samuel Chandra
Could it be that you forgot to create the implementation for the RPCCallsService? I can't see it from the list of files that you have.
可能是您忘记为 RPCCallsService 创建实现吗?我无法从您拥有的文件列表中看到它。
You should have a file called RPCCallsServiceImpl.java in RPCCalls/src/com/example/rpccalls/server/, it is the implementation file for the interface RPCCallsService.java.
你应该在 RPCCalls/src/com/example/rpccalls/server/ 中有一个名为 RPCCallsServiceImpl.java 的文件,它是接口 RPCCallsService.java 的实现文件。
It will look something like this:
它看起来像这样:
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.example.rpccalls.client.RPCCallsService;
public class RPCCallsServiceImpl extends RemoteServiceServlet implements RPCCallsService {
// Factory to get persistence manager object later
private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactional-optional");
public String saveName(Person p) {
// Data Store need persistence manager object for writing to it
PersistenceManager pm = PMF.getPersistenceManager();
// Recommended way to save an object to the data store
try {
pm.makePersistent(p);
} finally {
pm.close();
}
// You want it to return string
return p.getName();
}
}
Hopefully this help you to solve the problem. Cheers :)
希望这可以帮助您解决问题。干杯:)

