【问题标题】:GWT with JDO problemGWT 与 JDO 问题
【发布时间】:2010-11-02 13:25:15
【问题描述】:

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

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

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 类和其他所有内容,但看起来我遗漏了一些东西。

这是我的错误: alt text http://vasura.s3.amazonaws.com/Picture2.png

或在我收到此错误之前:

无法将键解析为类型

使这项工作发挥作用的最佳解决方案是什么?

【问题讨论】:

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


    【解决方案1】:

    Sriram Narayan 对 Key 进行字符串编码以使其通过 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;

    【讨论】:

      【解决方案2】:

      您引用的第二个教程有一节介绍了 com.google.appengine.api.datastore.Key 类的影子,因为它不适用于 GWT:

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

      您可能想看看the GWT documentation,它指出

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

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

      【讨论】:

      • 这是一个常见的错误,因为您基本上可以在应用程序的客户端拥有 java.lang 和 java.util 类。例如,通过这种方式,您将无法将 Key 或 User 对象发送到客户端。
      • 第二个教程是一个卑鄙的黑客。有没有更好的办法?
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

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

        使用方法:

        • 在构建路径中的任意位置添加 appengine-utils-client-1.0.jar。
        • 将 appengine-utils-server-1.0.jar 放入您的 WEB-INF/lib 文件夹中。
        • 将以下内容添加到您的 GWT 模块中:

        【讨论】:

        • FWIW resmark 解决方案在 GWT 2.1.0//GAE 1.3.8 上非常适合我。
        【解决方案5】:

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

        【讨论】:

        • 这就是我试图遵循的教程(顶部的 TUT2 链接)。尝试先阅读我的帖子,然后再回复。谢谢你。
        • 对不起原来的答案,你是对的,它没有帮助。我阅读了这个问题,但没有点击链接。
        • 是的,我只是能够创建 JPA 来工作,但是我如何将对象从/到 GWT 传递?
        • 您需要在code.google.com/webtoolkit/doc/1.6/… 查看 GWT 开发人员关于服务器通信的指南@ 他们在示例中的方法传递一个字符串作为参数和返回类型,但您可以传递和返回任何对象遵守同样在同一个文档中的序列化规则。
        • 也就是说,您需要查看 rustyshelf 对您的 TUT1 链接的回答,了解将用于客户端/服务器通信的类型放在哪里以及如何让 GWT 看到它们。
        【解决方案6】:

        可能是您忘记为 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();
          }
        
        }
        

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

        【讨论】:

          猜你喜欢
          • 2010-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-03
          • 1970-01-01
          • 1970-01-01
          • 2011-01-12
          • 1970-01-01
          相关资源
          最近更新 更多