Pergunta

Já corri através do Google Web Toolkit StockWatcher Tutorial usando Eclipse e Google Plugin , e eu estou tentando fazer algumas mudanças básicas a ele para que eu possa entender melhor o quadro RPC.

Eu modificado o método "getStocks" na classe do lado do servidor StockServiceImpl para que ele retorna uma matriz de objetos da em vez de objetos String. A aplicação compila perfeitamente, mas o Google Web Toolkit está retornando o seguinte erro:

"No código fonte está disponível para o tipo com.google.gwt.sample.stockwatcher.server.Stock;? Você se esqueceu de herdar um módulo obrigatório"

Google web Toolkit Modo Hospedado

Parece que as classes do lado do cliente não consegue encontrar uma implementação do objeto da, mesmo que a classe tenha sido importado. Para referência, aqui está uma imagem da minha hierarquia de pacotes:

Pacote Eclipse Hierarquia

Eu suspeito que eu estou faltando alguma coisa em web.xml, mas eu não tenho idéia o que é. Alguém pode me apontar na direção certa?

EDIT:. Esqueceu-se de mencionar que o da classe é persistente, por isso precisa ficar no lado do servidor do

Foi útil?

Solução

Depois de muita tentativa e erro, eu consegui encontrar uma maneira de fazer isso. Pode não ser o melhor caminho, mas funciona. Espero que este post pode salvar alguém um monte de tempo e esforço.

Essas instruções supõem que você tenha concluído tanto o básica StockWatcher tutorial e os Google App Engine StockWatcher modificações .

Criar uma implementação do lado do cliente da da Classe

Há um par de coisas para manter em mente sobre GWT:

  1. aulas do lado do servidor pode importar classes do lado do cliente, mas não vice-versa (geralmente).
  2. A do lado do cliente não pode importar qualquer bibliotecas do Google App Engine (ou seja com.google.appengine.api.users.User)

Devido a ambos os itens acima, o cliente nunca pode implementar o da classe que criamos em com.google.gwt.sample.stockwatcher.server. Em vez disso, vamos criar uma nova classe Stock client-side chamado 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;
  }
}

Classes Modificar cliente para usar StockClient [] em vez de String []

Agora vamos fazer algumas modificações simples para as classes de cliente para que eles saibam que a chamada RPC retorna StockClient [] em vez 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:

Adicione uma importação:

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

Todas as outras estadias de código o mesmo, exceto addStock, loadStocks e 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 a classe StockServiceImpl para retorno StockClient []

Por fim, modificar o método getStocks da classe StockServiceImpl para que ele traduz as classes do lado do servidor de Stock em classes StockClient do lado do cliente antes de retornar a matriz.

StockServiceImpl.java

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

Precisamos mudar o método addStock um pouco para que o ID gerado é retornado:

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 os outros métodos permanecer o mesmo, exceto 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]);
}

Resumo

O código acima funciona perfeitamente para mim quando implantado para o Google App Engine, mas desencadeia um erro no Google Web Toolkit Modo Hospedado:

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

Deixe-me saber se você encontrar o mesmo problema ou não. O fato de que ele funciona no Google App Engine parece indicar um bug no modo hospedado.

Outras dicas

GWT precisa do arquivo .java, além do arquivo .class. Além disso, Stock precisa estar no local "cliente" de um módulo GWT.

O compilador GWT não sabe sobre da, porque não é em um local que parece. Você pode movê-lo para a pasta do cliente, ou se faz mais sentido licença-lo onde está e criar um ModuleName.gwt .xml que referências quaisquer outras classes que você deseja, e obter o seu arquivo Main.gwt.xml para herdar a partir daí.

por exemplo: DomainGwt.gwt.xml

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

e

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

Não há uma resposta melhor aqui: GWT problema caso de uso RPC simples: código incluído

Basicamente, você pode adicionar parâmetros para o arquivo APPNAME.gwt.xml para que o compilador para dar o compilador um caminho para a classe do lado do servidor.

Eu estava recebendo o mesmo problema e "mvn gwt: compilação" de saída não foi muito útil. Em vez disso, quando eu tentei implantar a tomcat (através do maven tomcat plugin: mvn tomcat: deploy) Eu tenho mensagens de erro votos.

Algumas coisas que eu tinha que arrumar:

  1. Faça o objeto que é enviado a partir do cliente para o servidor implementar Serializable
  2. Adicionar um construtor vazio-arg a esse mesmo objeto

Sim, é certo que precisamos usar a serialização para obter os objetos do servidor para o cliente. Estes modile ?? configurações de arquivo não irá funcionar para usar o da classe no lado do cliente.

No seu caso você tenha apenas uma classe de estoque e você pode criar um StockClient no lado do cliente. Isso é fácil. Mas o que vai ser a solução se alguém ter mais classes. Algo como as propriedades desta classe são também algum outro tipo de classes.

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

getEOD voltará outra classe com a data dada e que a classe tem o método getHigh.

O que fazer em tais grandes casos? Eu não acho que a criação de todas as classes que implementam a serialização em lado do cliente é bom para isso. Então nós temos que escrever o código no servidor e cliente. todas as classes duas vezes.

Keying fora da resposta de rustyshelf acima ...

No meu caso eu precisava para editar o arquivo ModuleName.gwt.xml e adicione a seguinte:

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

Eu criei o meu projecto com o Novo-> projeto de aplicação Web assistente mas desmarcado a Gerar código de exemplo do projeto opção. Eu, então, criou o pacote compartilhada. Eu não tinha desmarcado disso, o pacote teria sido criado por mim e o arquivo xml modificado per acima.

Há uma solução muito mais simples e fácil para isso. Se você quiser enviar um objeto de sua classe personalizada concebido a partir do lado do servidor para o lado do cliente que você deve definir esta classe personalizada em compartilhada pacote.

Por exemplo, para o seu caso a você apenas tem que carregar a classe Stock.java (por arrastar e soltar) para

com.google.gwt.sample.stockwatcher.shared

pacote. No entanto a partir de sua hierarquia pacote imagem de tela parece que você tinha excluído este pacote compartilhada. Apenas re-criar este pacote e soltar o Stock.java no seu interior e deixar o jogo começar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top