6

我刚开始玩 GWT 我很难让 GWT + JAVA + JDO + Google AppEngine 与 DataStore 一起工作。我试图遵循不同的教程,但没有运气。例如,我去了这些教程:TUT1 TUT2

我无法弄清楚我需要如何以及做什么才能完成这项工作。请查看我的简单代码并告诉我需要做什么才能将其保存到数据存储区:

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. 个人实体

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. 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

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

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

<?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>

我试图在这些教程中添加 Key 类和其他所有内容,但看起来我错过了一些东西。

这是我的错误: 替代文字 http://vasura.s3.amazonaws.com/Picture2.png

或在我收到此错误之前:

无法将键解析为类型

使这个工作的最佳解决方案是什么?

4

6 回答 6

8

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;

于 2009-06-21T14:58:29.893 回答
3

您引用的第二个教程有一个关于隐藏com.google.appengine.api.datastore.Key类的部分,因为它对 GWT 不可用:

由于我没有对客户端上的 Key 类做任何事情,我将把它存根。这实际上需要几个步骤,并且涉及到 GWT XML 模块文件的 super-src 特性。

您可能想查看GWT 文档,其中指出

GWT 的核心是将 Java 源代码转换为 JavaScript 的编译器

,因此您需要有可用于在客户端代码中使用给定类的源代码。

于 2009-06-15T13:15:34.550 回答
3

一旦您厌倦了 JDO,请看一下objectify。我发现使用它要好得多,并且它具有完整的 GWT 互操作性,而无需 DTO。

于 2010-02-16T16:09:34.380 回答
3

您可以通过添加这些额外的 jar 文件在 GWT 代码中使用 Key 类:

http://www.resmarksystems.com/code/

  • appengine-utils-client-1.0.jar
  • appengine-utils-server-1.0.jar

这基本上为 GWT 编译器提供了 Key 和其他 AppEngine 类的 GWT 友好版本。(如文本、Blob 和用户..)

要使用:

  • 在构建路径中的任何位置添加 appengine-utils-client-1.0.jar。
  • 将 appengine-utils-server-1.0.jar 放入您的 WEB-INF/lib 文件夹中。
  • 将以下内容添加到您的 GWT 模块中:
    • <继承名称="com.resmarksystems.AppEngineDataTypes"/>
于 2010-10-08T01:47:34.880 回答
1

另一种选择是实现您在客户端中使用的 DTO(数据传输对象),而不是直接使用持久对象。或者,你可以去 JPA 而不是 JDO。在 appengine JPA 文档中的示例数据类中,Id 是 Long 而不是 Key 实现http://code.google.com/appengine/docs/java/datastore/usingjpa.html

于 2009-06-12T18:59:58.870 回答
1

会不会是您忘记为 RPCCallsService 创建实现?我无法从您拥有的文件列表中看到它。

在 RPCCalls/src/com/example/rpccalls/server/ 中应该有一个名为 RPCCallsServiceImpl.java 的文件,它是接口 RPCCallsService.java 的实现文件。

它看起来像这样:

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();
  }

}

希望这可以帮助您解决问题。干杯:)

于 2009-06-13T06:48:40.557 回答