GWT с проблемой JDO - PullRequest
       27

GWT с проблемой JDO

6 голосов
/ 12 июня 2009

Я только начинаю играть с 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. RPCCalls

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

или до того, как я получил эту ошибку:

Ключ не может быть определен для типа

Как лучше всего это сделать?

Ответы [ 6 ]

8 голосов
/ 21 июня 2009

Шрирам Нараян говорит String-кодировать ключ, чтобы он прошел через механизм RPC GWT:

@PersistenceCapable(identityType = IdentityType.APPLICATION)<br> public class SomeDomainClass implements Serializable {<br> @PrimaryKey<br> @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)<br> @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")<br> String id;<br>

3 голосов
/ 08 октября 2010

Вы можете использовать класс Key в коде GWT, добавив следующие дополнительные файлы jar:

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

  • AppEngine-Utils-клиент-1.0.jar
  • AppEngine-Utils-сервера 1.0.jar

Это в основном дает компилятору GWT GWT-дружественную версию Key и других классов AppEngine. (например, «Текст», «Blob» и «Пользователь»)

Для использования:

  • Добавьте appengine-utils-client-1.0.jar в любом месте вашего пути сборки.
  • Поместите appengine-utils-server-1.0.jar в папку WEB-INF / lib.
  • Добавьте следующее в ваш модуль GWT:
    • <наследует имя = "com.resmarksystems.AppEngineDataTypes" />
3 голосов
/ 16 февраля 2010

Когда вы сыт по горло JDO, взгляните на objectify . Я обнаружил, что с ним гораздо приятнее работать, и он имеет полное взаимодействие с GWT без DTO.

3 голосов
/ 15 июня 2009

Во втором уроке, на который вы ссылаетесь, есть раздел о затенении класса com.google.appengine.api.datastore.Key, так как он не доступен для GWT:

Поскольку я ничего не делаю с классом Key на клиенте, я собираюсь заглушить это. Это на самом деле требует нескольких шагов и включает в себя функцию супер-src файлов модуля GWT XML.

Возможно, вы захотите взглянуть на документацию GWT , в которой говорится, что

Сердцем GWT является компилятор, который преобразует исходный код Java в JavaScript

, поэтому вам необходимо иметь исходный код для использования данного класса в клиентском коде.

1 голос
/ 13 июня 2009

Может быть, вы забыли создать реализацию для RPCCallsService? Я не вижу его в списке файлов, которые у вас есть.

У вас должен быть файл RPCCallsServiceImpl.java в RPCCalls / src / com / example / rpccalls / server /, это файл реализации интерфейса 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();
  }

}

Надеюсь, это поможет вам решить проблему. Ура:)

1 голос
/ 12 июня 2009

Другой вариант - реализовать DTO (объект передачи данных), который вы используете в клиенте, а не напрямую использовать постоянные объекты. Или вы можете пойти в JPA вместо JDO. В примере класса данных в документации JPA приложения Id - это Long вместо реализации Key http://code.google.com/appengine/docs/java/datastore/usingjpa.html

...