gpt4 book ai didi

java - 通过 GWT RPC 传递类对象的问题

转载 作者:IT老高 更新时间:2023-10-28 20:51:59 24 4
gpt4 key购买 nike

我浏览过 Google Web Toolkit StockWatcher Tutorial使用 EclipseGoogle Plugin ,并且我正在尝试对其进行一些基本更改,以便更好地理解 RPC 框架。

我修改了 StockServiceImpl 服务器端类的“getStocks”方法,使其返回一个 Stock 对象数组,而不是 String 对象。应用程序编译完美,但 Google Web Toolkit 返回以下错误:

“com.google.gwt.sample.stockwatcher.server.Stock 类型没有可用的源代码;您是否忘记继承所需的模块?”

Google Web Toolkit Hosted Mode

客户端类似乎找不到 Stock 对象的实现,即使该类已被导入。作为引用,这是我的包层次结构的屏幕截图:

Eclipse Package Hierarchy

我怀疑我在 web.xml 中遗漏了一些东西,但我不知道它是什么。谁能指出我正确的方向?

编辑:忘了说 Stock 类是可持久的,所以它需要留在服务器端。

最佳答案

经过多次尝试和错误,我设法找到了一种方法来做到这一点。这可能不是最好的方法,但它确实有效。希望这篇文章可以为其他人节省大量时间和精力。

这些说明假定您已完成 basic StockWatcher tutorialGoogle App Engine StockWatcher modifications .

创建 Stock 类的客户端实现

关于 GWT 有几点需要牢记:

  1. 服务器端类可以导入客户端类,但反之亦然(通常)。
  2. 客户端无法导入任何 Google App Engine 库(即 com.google.appengine.api.users.User)

由于以上两项,客户端永远无法实现我们在 com.google.gwt.sample.stockwatcher.server 中创建的 Stock 类。相反,我们将创建一个名为 StockClient 的新客户端 Stock 类。

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

修改客户端类以使用 StockClient[] 而不是 String[]

现在我们对客户端类进行一些简单的修改,以便他们知道 RPC 调用返回的是 StockClient[] 而不是 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:

添加一个导入:

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

所有其他代码保持不变,除了 addStock、loadStocks 和 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());
}
});
}

修改 StockServiceImpl 类以返回 StockClient[]

最后,我们修改 StockServiceImpl 类的 getStocks 方法,使其在返回数组之前将服务器端 Stock 类转换为客户端 StockClient 类。

StockServiceImpl.java

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

我们需要稍微改变一下 addStock 方法,以便返回生成的 ID:

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();
}

所有其他方法保持不变,除了 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]);
}

总结

上面的代码在部署到 Google App Engine 时非常适合我,但在 Google Web Toolkit Hosted Mode 中触发错误:

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

如果您遇到同样的问题,请告诉我。它在 Google App Engine 中工作的事实似乎表明托管模式存在错误。

关于java - 通过 GWT RPC 传递类对象的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/958879/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com