2010-02-10 8 views
7

Estoy tratando de averiguar cómo enviar un objeto de dominio desde el lado del servidor al lado del cliente usando GWT RPC. He codificado un caso de uso realmente simple que representa el tipo de cosas que yo (y otros?) Necesito poder hacer, pero que en este momento no puedo ponerme a trabajar.GWT Problema de uso de RPC simple: Código incluido

He rastreado los documentos, tutoriales y foros, pero o bien muestran cadenas que se transmiten u ofrecen explicaciones que (cuando las aplico a esto) todavía no funcionan.

Esperemos que alguien pueda explicarnos a mí y a otros por qué este código no funciona y cómo hacerlo funcionar.

Gracias.

Aquí están los mensajes de error.

13:12:54.328 [DEBUG] [org.redboffin.worldhug.Test] Validating newly compiled units 
13:12:54.328 [ERROR] [org.redboffin.worldhug.Test] Errors in 'file:/C:/Documents%20and%20Settings/Darren/workspace/WorldHug/src/org/redboffin/worldhug/client/test/TestService.java' 
13:12:54.343 [ERROR] [org.redboffin.worldhug.Test] Line 14: No source code is available for type org.redboffin.worldhug.server.test.TestObject; did you forget to inherit a required module? 
13:12:54.515 [ERROR] [org.redboffin.worldhug.Test] Errors in 'file:/C:/Documents%20and%20Settings/Darren/workspace/WorldHug/src/org/redboffin/worldhug/client/test/TestServiceAsync.java' 
13:12:54.515 [ERROR] [org.redboffin.worldhug.Test] Line 12: No source code is available for type org.redboffin.worldhug.server.test.TestObject; did you forget to inherit a required module? 
13:12:55.953 [ERROR] [org.redboffin.worldhug.Test] Errors in 'file:/C:/Documents%20and%20Settings/Darren/workspace/WorldHug/src/org/redboffin/worldhug/client/test/TestView.java' 
13:12:55.968 [ERROR] [org.redboffin.worldhug.Test] Line 42: No source code is available for type org.redboffin.worldhug.server.test.TestObject; did you forget to inherit a required module? 
13:12:55.968 [ERROR] [org.redboffin.worldhug.Test] Line 46: No source code is available for type org.redboffin.worldhug.server.test.InnerObject; did you forget to inherit a required module? 
13:12:55.984 [ERROR] [org.redboffin.worldhug.Test] Line 48: No source code is available for type org.redboffin.worldhug.server.test.ListObject; did you forget to inherit a required module? 
13:12:56.765 [INFO] [org.redboffin.worldhug.Test] Module org.redboffin.worldhug.Test has been loaded 

Aquí están las clases de proyecto y los archivos.

Test.gwt.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.0/distro-source/core/src/gwt-module.dtd"> 
<module> 
    <inherits name="com.google.gwt.user.User" /> 
    <source path="client/test" /> 
    <entry-point class="org.redboffin.worldhug.client.test.Test"></entry-point> 
</module> 

Web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE web-app 
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
"http://java.sun.com/dtd/web-app_2_3.dtd"> 

<web-app> 

    <!-- Servlets --> 

    <servlet> 
    <servlet-name>testServlet</servlet-name> 
    <servlet-class>org.redboffin.worldhug.server.test.TestServiceImpl</servlet-class> 
    </servlet> 

    <servlet-mapping> 
    <servlet-name>testServlet</servlet-name> 
    <url-pattern>/worldhug/test/testService</url-pattern> 
    </servlet-mapping> 

    <!-- Default page to serve --> 
    <welcome-file-list> 
    <welcome-file>test.html</welcome-file> 
    </welcome-file-list> 

</web-app> 

TestObject.java

package org.redboffin.worldhug.server.test; 

import java.util.ArrayList; 
import java.util.List; 

import com.google.gwt.user.client.rpc.IsSerializable; 

public class TestObject implements IsSerializable { 

    private String testObjectString; 
    private InnerObject innerObject; 
    private List<ListObject> listObjects = new ArrayList<ListObject>(); 

    public TestObject() {} 

    // Getters and setters removed for brevity 

} 

InnerObject.java

package org.redboffin.worldhug.server.test; 

import com.google.gwt.user.client.rpc.IsSerializable; 

public class InnerObject implements IsSerializable { 

    private String innerObjectString; 

    public InnerObject() {} 

     // Getters and setters removed for brevity 

} 

ListObject.java

package org.redboffin.worldhug.server.test; 

import com.google.gwt.user.client.rpc.IsSerializable; 

public class ListObject implements IsSerializable { 

    private String listObjectString; 

    public ListObject() {} 

     // Getters and setters removed for brevity. 

} 

TestService.java

package org.redboffin.worldhug.client.test; 

import org.redboffin.worldhug.server.test.TestObject; 

import com.google.gwt.user.client.rpc.RemoteService; 
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; 

/** 
* The client side stub for the Test Service. 
* @author Darren 
*/ 
@RemoteServiceRelativePath("testService") 
public interface TestService extends RemoteService { 

    TestObject test(); 

} 

TestServiceAsync.java

package org.redboffin.worldhug.client.test; 

import org.redboffin.worldhug.server.test.TestObject; 

import com.google.gwt.user.client.rpc.AsyncCallback; 

/** 
* The async counterpart of <code>TestService</code>. 
* @author Darren 
*/ 
public interface TestServiceAsync { 

    void test(AsyncCallback<TestObject> callback); 

} 

TestServiceImpl.java

package org.redboffin.worldhug.server.test; 

import java.util.List; 

import org.redboffin.worldhug.client.test.TestService; 

import com.google.gwt.user.server.rpc.RemoteServiceServlet; 

/** 
* The server side implementation of the RPC service. 
* @author Darren 
*/ 
@SuppressWarnings("serial") 
public class TestServiceImpl extends RemoteServiceServlet implements TestService { 

    @Override 
    public TestObject test() { 

     TestObject testObject = new TestObject();  
     testObject.setTestObjectString("Test Object String"); 

     InnerObject innerObject = new InnerObject(); 
     innerObject.setInnerObjectString("Inner Object String"); 

       testObject.setInnerObject(innerObject); 

     List<ListObject> listObjects = testObject.getListObjects(); 

     ListObject listObjectOne = new ListObject(); 
     listObjectOne.setListObjectString("List Object One"); 
     listObjects.add(0, listObjectOne); 

     ListObject listObjectTwo = new ListObject(); 
     listObjectTwo.setListObjectString("List Object Two"); 
     listObjects.add(0, listObjectTwo); 

     ListObject listObjectThree = new ListObject(); 
     listObjectThree.setListObjectString("List Object Three"); 
     listObjects.add(0, listObjectThree); 

     return testObject; 
    } 

} 

TestView.java

package org.redboffin.worldhug.client.test; 

import java.util.ArrayList; 
import java.util.Iterator; 

import org.redboffin.worldhug.server.test.InnerObject; 
import org.redboffin.worldhug.server.test.ListObject; 
import org.redboffin.worldhug.server.test.TestObject; 

import com.google.gwt.core.client.GWT; 
import com.google.gwt.event.dom.client.ClickEvent; 
import com.google.gwt.uibinder.client.UiBinder; 
import com.google.gwt.uibinder.client.UiField; 
import com.google.gwt.uibinder.client.UiHandler; 
import com.google.gwt.user.client.rpc.AsyncCallback; 
import com.google.gwt.user.client.ui.Button; 
import com.google.gwt.user.client.ui.Composite; 
import com.google.gwt.user.client.ui.Label; 
import com.google.gwt.user.client.ui.VerticalPanel; 

public class TestView extends Composite { 

    private static TestViewUiBinder uiBinder = GWT.create(TestViewUiBinder.class); 

    interface TestViewUiBinder extends UiBinder<VerticalPanel, TestView> {} 

    @UiField Label testObjectStringLabel; 
    @UiField Label innerObjectStringLabel; 
    @UiField VerticalPanel listObjectsPanel; 
    @UiField Button button; 
    @UiField Label errorMessageLabel; 

    public TestView(String firstName) { 
     initWidget(uiBinder.createAndBindUi(this)); 
    } 

    @UiHandler("button") 
    void onClick(ClickEvent e) { 

     TestServiceAsync testService = (TestServiceAsync) GWT.create(TestService.class); 

     AsyncCallback<TestObject> callback = new AsyncCallback<TestObject>() { 

      public void onSuccess(TestObject testObject) { 
       testObjectStringLabel.setText(testObject.getTestObjectString()); 
       InnerObject innerObject = testObject.getInnerObject(); 
       innerObjectStringLabel.setText(innerObject.getInnerObjectString()); 
       ArrayList<ListObject> listObjects = (ArrayList<ListObject>) testObject.getListObjects(); 
       Iterator<ListObject> iterator = listObjects.iterator(); 
       while(iterator.hasNext()) { 
        ListObject listObject = (ListObject) iterator.next(); 
        listObjectsPanel.add(new Label(listObject.getListObjectString())); 
       } 
      } 

      public void onFailure(Throwable caught) { 
       errorMessageLabel.setText("Error : "+caught.getMessage()); 
      } 
      }; 

      testService.test(callback); 

    } 

} 

TestView.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> 
<ui:UiBinder 
    xmlns:ui="urn:ui:com.google.gwt.uibinder" 
    xmlns:g="urn:import:com.google.gwt.user.client.ui"> 

    <g:VerticalPanel> 
     <g:Label>Test Object</g:Label> 
     <g:Label ui:field="testObjectStringLabel"></g:Label> 
     <g:VerticalPanel> 
      <g:Label>Inner Object</g:Label> 
      <g:Label ui:field="innerObjectStringLabel"></g:Label> 
     </g:VerticalPanel> 
     <g:VerticalPanel ui:field="listObjectsPanel"> 
      <g:Label>List Objects</g:Label> 
     </g:VerticalPanel> 
     <g:Button ui:field="button">Display Test Object</g:Button> 
     <g:Label ui:field="errorMessageLabel"></g:Label> 
    </g:VerticalPanel> 

</ui:UiBinder> 

Gracias por leer hasta aquí y para cualquier ayuda que puede ser capaz de mí (y otros) dar.

+0

La cantidad de código repetitivo en Java RPC me molesta más que cualquier otra cosa en Java. Realmente deseo, en este caso al menos, que adopten el enfoque de Convención sobre la configuración de Ruby y solo te permitan dejar caer un objeto serializable en la línea. De hecho, he intentado este enfoque, teniendo un método arriveAt (llamado) cuando llegaste a una nueva máquina virtual. Fue realmente resbaladizo, pero el método arriveAt tenía una tendencia a llevar todo el cliente y el servidor a cada compilación. Salimos pero tengo la idea de poder etiquetar los métodos @client o @server y compilarlos condicionalmente ... –

Respuesta

10

Debe identificar todos los paquetes que contengan fuente que se compilará GWT.

p. Ej.

<source path="client/test"/> 
<source path="server/test"/> 

Puede ser una mejor opción para poner sus clases de dominio NO en el paquete del servidor. A menudo hacemos este tipo de cosas:

<source path="client"/> 
<source path="shared"/> 

donde compartido contiene los DTO pasados ​​entre el cliente y el servidor.

+0

Gracias, Craig, eso ahora funciona perfectamente. Excelente consejo sobre el uso de un paquete 'compartido'. – Darren

0

Si utiliza el DTO debe insertar el objeto transferible en la carpeta compartida (convención). Si utiliza un objeto de dominio no compartido y no "transfiere" puede insertar una carpeta (por ejemplo, "dominio") en la carpeta del servidor, pero este "tipo" no se puede usar para llamadas asincrónicas. Moral: si un objeto se transfiere debe ser "compartido", de lo contrario, puede usarlo de forma segura en la carpeta del servidor.

+0

Estoy de acuerdo con compartir. Pero insertar los archivos de clase dentro de la carpeta del servidor es una forma incorrecta. –

Cuestiones relacionadas