Pregunta

Me he encontrado a través de la Google Web Toolkit StockWatcher Tutorial usando Eclipse y la Google Plugin , y yo estoy tratando de hacer algunos cambios básicos en lo que yo pueda entender mejor el marco RPC.

He modificado el método "getStocks" en la clase del lado del servidor StockServiceImpl para que devuelva un conjunto de objetos de archivo en lugar de objetos String. La aplicación compila perfectamente, pero el Google Web Toolkit está devolviendo el siguiente error:

"Sin código fuente está disponible para el tipo com.google.gwt.sample.stockwatcher.server.Stock;? ¿Usted se olvidó de heredar un módulo requerido"

Google web Toolkit Alojado Mode

Parece que las clases del cliente no pueden encontrar una implementación de la Bolsa de objeto, a pesar de que la clase ha sido importado. Para referencia, aquí es una captura de pantalla de mi jerarquía de paquetes:

Eclipse paquete Jerarquía

Sospecho que me falta algo en web.xml, pero no tengo ni idea de lo que es. ¿Puede alguien me punto en la dirección correcta?

EDIT:. Se me olvidó mencionar que la clase de valores es con persistencia, por lo que necesita para mantenerse en el lado del servidor

¿Fue útil?

Solución

Después de mucho ensayo y error, he conseguido encontrar una manera de hacer esto. Puede que no sea la mejor manera, pero funciona. Esperemos que este post puede salvar a otra persona una gran cantidad de tiempo y esfuerzo.

Estas instrucciones se supone que ha completado tanto el básica StockWatcher tutorial y las modificaciones de la Google App Engine StockWatcher .

crear una implementación del lado del cliente de la Bolsa de Clase

Hay un par de cosas a tener en cuenta sobre GWT:

    clases
  1. en el servidor puedan importar clases del lado del cliente, pero no viceversa (por lo general).
  2. El lado del cliente no puede importar cualquier biblioteca de Google App Engine (es decir com.google.appengine.api.users.User)

Debido a los dos puntos anteriores, el cliente nunca se puede poner en práctica la Bolsa de clase que hemos creado en com.google.gwt.sample.stockwatcher.server. En su lugar, vamos a crear un nuevo lado del cliente de la clase llamada StockClient.

StockClient.java:

package com.google.gwt.sample.stockwatcher.client;

import java.io.Serializable;
import java.util.Date;

public class StockClient implements Serializable {

  private Long id;
  private String symbol;
  private Date createDate;

  public StockClient() {
    this.createDate = new Date();
  }

  public StockClient(String symbol) {
    this.symbol = symbol;
    this.createDate = new Date();
  }

  public StockClient(Long id, String symbol, Date createDate) {
    this();
    this.id = id;
    this.symbol = symbol;
    this.createDate = createDate;
  }

  public Long getId() {
      return this.id;
  }

  public String getSymbol() {
      return this.symbol;
  }

  public Date getCreateDate() {
      return this.createDate;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public void setSymbol(String symbol) {
      this.symbol = symbol;
  }
}

Modificar Clases cliente para utilizar StockClient [] en lugar de String []

Ahora hacemos algunas modificaciones sencillas en las clases de cliente para que sepan que la llamada RPC vuelve StockClient [] en lugar de String [].

StockService.java:

package com.google.gwt.sample.stockwatcher.client;

import com.google.gwt.sample.stockwatcher.client.NotLoggedInException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("stock")
public interface StockService extends RemoteService {
  public Long addStock(String symbol) throws NotLoggedInException;
  public void removeStock(String symbol) throws NotLoggedInException;
  public StockClient[] getStocks() throws NotLoggedInException;
}

StockServiceAsync.java:

package com.google.gwt.sample.stockwatcher.client;

import com.google.gwt.sample.stockwatcher.client.StockClient;
import com.google.gwt.user.client.rpc.AsyncCallback;

public interface StockServiceAsync {
  public void addStock(String symbol, AsyncCallback<Long> async);
  public void removeStock(String symbol, AsyncCallback<Void> async);
  public void getStocks(AsyncCallback<StockClient[]> async);
}

StockWatcher.java:

Añadir una importación:

import com.google.gwt.sample.stockwatcher.client.StockClient;

El resto de código permanece igual, excepto addStock, loadStocks y displayStocks:

private void loadStocks() {
    stockService = GWT.create(StockService.class);
    stockService.getStocks(new AsyncCallback<String[]>() {
        public void onFailure(Throwable error) {
            handleError(error);
        }

        public void onSuccess(String[] symbols) {
            displayStocks(symbols);
        }
    });
}

private void displayStocks(String[] symbols) {
    for (String symbol : symbols) {
        displayStock(symbol);
    }
}

private void addStock() {
    final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
    newSymbolTextBox.setFocus(true);

    // Stock code must be between 1 and 10 chars that are numbers, letters,
    // or dots.
    if (!symbol.matches("^[0-9a-zA-Z\\.]{1,10}$")) {
        Window.alert("'" + symbol + "' is not a valid symbol.");
        newSymbolTextBox.selectAll();
        return;
    }

    newSymbolTextBox.setText("");

    // Don't add the stock if it's already in the table.
    if (stocks.contains(symbol))
        return;

    addStock(new StockClient(symbol));
}

private void addStock(final StockClient stock) {
    stockService.addStock(stock.getSymbol(), new AsyncCallback<Long>() {
        public void onFailure(Throwable error) {
            handleError(error);
        }

        public void onSuccess(Long id) {
            stock.setId(id);
            displayStock(stock.getSymbol());
        }
    });
}

modificar la clase StockServiceImpl devolver StockClient []

Por último, modificamos el método getStocks de la clase StockServiceImpl para que traduce las clases del lado del servidor de archivo en clases StockClient del lado del cliente antes de devolver la matriz.

StockServiceImpl.java

import com.google.gwt.sample.stockwatcher.client.StockClient;

Es necesario cambiar el método addStock un poco para que se devuelve el identificador generado:

public Long addStock(String symbol) throws NotLoggedInException {
  Stock stock = new Stock(getUser(), symbol);
  checkLoggedIn();
  PersistenceManager pm = getPersistenceManager();
  try {
    pm.makePersistent(stock);
  } finally {
    pm.close();
  }
  return stock.getId();
}

Todos los demás métodos permanecen igual, excepto getStocks:

public StockClient[] getStocks() throws NotLoggedInException {
  checkLoggedIn();
  PersistenceManager pm = getPersistenceManager();
  List<StockClient> stockclients = new ArrayList<StockClient>();
  try {
    Query q = pm.newQuery(Stock.class, "user == u");
    q.declareParameters("com.google.appengine.api.users.User u");
    q.setOrdering("createDate");
    List<Stock> stocks = (List<Stock>) q.execute(getUser());
    for (Stock stock : stocks)
    {
       stockclients.add(new StockClient(stock.getId(), stock.getSymbol(), stock.getCreateDate()));
    }
  } finally {
    pm.close();
  }
  return (StockClient[]) stockclients.toArray(new StockClient[0]);
}

Resumen

El código anterior funciona perfectamente para mí cuando se despliegan en Google App Engine, pero desencadena un error en Google Web Toolkit modo de host:

SEVERE: [1244408678890000] javax.servlet.ServletContext log: Exception while dispatching incoming RPC call
com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract com.google.gwt.sample.stockwatcher.client.StockClient[] com.google.gwt.sample.stockwatcher.client.StockService.getStocks() throws com.google.gwt.sample.stockwatcher.client.NotLoggedInException' threw an unexpected exception: java.lang.NullPointerException: Name is null

Quiero saber si se produce el mismo problema o no. El hecho de que funciona en Google App Engine parece indicar un error en modo de host.

Otros consejos

GWT necesita el archivo .java además del archivo .class. Además, Stock tiene que estar en el "cliente" ubicación de un módulo de GWT.

El compilador GWT no sabe acerca de, porque no es en un lugar que se ve en. Usted puede moverlo a la carpeta del cliente, o si tiene más sentido dejar donde está y crear una ModuleName.gwt .xml que hace referencia a ninguna otra clase que desea, y obtener su archivo Main.gwt.xml heredar de eso.

por ejemplo: DomainGwt.gwt.xml

<module>
    <inherits name='com.google.gwt.user.User'/>
    <source path="javapackagesabovethispackagegohere"/>
</module>

y

<module rename-to="gwt_ui">
    <inherits name="com.google.gwt.user.User"/>
    <inherits name="au.com.groundhog.groundpics.DomainGwt"/>

    <entry-point class="au.com.groundhog.groundpics.gwt.client.GPicsUIEntryPoint"/>
</module>

Hay una mejor respuesta aquí: GWT problema caso de uso simple RPC: código incluido

Básicamente, se puede añadir parámetros a su archivo APPNAME.gwt.xml lo que el compilador para dar el compilador de un camino a la clase del lado del servidor.

Me estaba el mismo tema y la: salida "mvn compile gwt" no era muy útil. En cambio, cuando traté de despliegue de Tomcat (a través del plugin de Maven Tomcat: Tomcat mvn: desplegar) Tengo mensajes de error útiles.

Algunas cosas que tenía que arreglar:

  1. Hacer que el objeto que se envía desde el cliente al servidor implementar Serializable
  2. Añadir un constructor vacío-arg a ese mismo objeto

Sí, es seguro que tenemos que utilizar la serialización para conseguir los objetos del servidor al cliente. Estos Modile ?? configuración del archivo no funcionarán a utilizar la clase de valores en el lado del cliente.

En el caso de que tenga una sola clase de, y puede crear un StockClient en el lado del cliente. Es fácil. Pero, ¿qué va a ser la solución si alguien tiene más clases. Algo así como las propiedades de esta clase son también algún otro tipo de clases.

Ejemplo: stock.getEOD(date).getHigh();

getEOD volverá otra clase con la fecha dada y que la clase tiene el método getHigh.

¿Qué hacer en estos casos grandes? No creo que la creación de todas las clases que implementan la serialización en el lado del cliente es bueno para eso. Entonces tenemos que escribir el código en el servidor y el cliente. todas las clases dos veces.

Incrustación fuera de la respuesta de rustyshelf arriba ...

En mi caso necesitaba para editar el archivo ModuleName.gwt.xml y añadir lo siguiente:

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

He creado mi proyecto con el Nuevo-> Proyecto de Aplicación Web asistente, pero sin marcar, los> opción Generar código de ejemplo del proyecto

No es una solución mucho más simple y fácil para eso. Si desea enviar un objeto de su clase diseñado a medida del lado del servidor para el lado del cliente debe definir esta clase personalizada en compartida paquete.

Por ejemplo, para el caso de que el solo hay que llevar a la clase Stock.java (arrastrar y soltar) en

  

com.google.gwt.sample.stockwatcher.shared

paquete. Sin embargo, desde su paquete jerarquía pantalla parece que se ha suprimido este paquete compartido. Sólo volver a crear este paquete y soltar el Stock.java su interior y dejar que el juego comience.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top