当前位置: 首页 > 面试题库 >

通过GWT RPC传递类对象时出现问题

左劲
2023-03-14
问题内容

我已经使用Eclipse和Google Plugin浏览了Google Web Toolkit StockWatcher教程,并且试图对其进行一些基本更改,以便更好地理解RPC框架。

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

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

Google Web Toolkit托管模式

客户端类似乎无法找到Stock对象的实现,即使该类已导入也是如此。作为参考,这是我的程序包层次结构的屏幕截图:

Eclipse包层次结构

我怀疑我在web.xml中缺少某些内容,但我不知道它是什么。谁能指出我正确的方向?

编辑:忘记提及Stock类是可持久的,因此它需要保留在服务器端。


问题答案:

经过反复尝试,我设法找到了一种方法。这可能不是最好的方法,但它可以工作。希望这篇文章可以节省别人很多时间和精力。

这些说明假定您已完成基本的StockWatcher教程和Google App Engine StockWatcher的修改。

创建股票类的客户端实现

关于GWT,需要牢记以下几点:

  1. 服务器端类可以导入客户端类,但反之亦然(通常)。
  2. 客户端无法导入任何Google App
  3. 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托管模式下会触发错误:

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通过引用传递对象 就像在C#中一样 问题答案: 不,这在Java中是不可能的。 在Java中,方法的所有参数均按值传递。注意非原始型的的变量,它们是对对象的引用,也由值来传递:在这种情况下, 参考 是 由值来传递 。请注意,按值传递引用与按引用传递不同。

  • 问题内容: 我想知道是否有可能使用jQuery AJAX函数将数组传递给php函数。我有以下作为我的JavaScript 当我尝试执行以下操作时 我在PHP中将其作为“数组”接收。如何正确发送对象,以便PHP函数可以使用它? 问题答案: 从第二个ajax中,您可以根据属性名称访问数据,例如: 是在php中以关联数组转换的js对象

  • 如果要在多个Servlet或JSP中传递复杂的对象,使用请求属性是最简单的方法。HttpServletRequest接口定义了setAttribute、getAttribute和removeAttribute方法分别用于保存、获得和删除请求域中的对象。并且还可以通过getAttributeNames方法获得所有保存在请求域中的属性名。在下面的例了将演示在两个Servlet之间传递一个MyClass

  • 问题内容: 我似乎无法获得任何一致的信息。不同的消息来源似乎说了不同的话,而古老的php.net本身( 似乎 )并未明确指出这一点- 尽管我必须承认,我只是快速浏览了一下。 如果我要传递“重”对象,则需要通过引用传递,但我不想继续输入: 如果我能摆脱 那么标准怎么说呢? 问题答案: 对象通过引用传递(和分配)。无需使用操作员地址。 当然,我键入的内容过于简单,但将适合您的目的。该文档指出: 经常提

  • 我试图通过在自定义对象上实现序列化将这个简单的对象从主要活动传递到主要活动。它会导致错误。我提到了类似的堆栈溢出问题。没有任何帮助。 主2活动 错误信息: 07-30 13:58:58.352 26489-26489/? E/AndroidRuntime:致命异常:主进程:gct.venkatesh.com。杂乱无章的,PID:26489 java.lang.RuntimeException:无法

  • 问题内容: 我试图通过意图传递对象的ArrayList,但无法使其工作。这是我所拥有的: 在这里收到意向: 我们已经收到了两个int值,correctAnswer和faultAnswers,我可以使用它们。ArrrayList没有通过。endQuiz()方法中没有错误,但’qs = getIntent()。getParcelableArrayListExtra(“ queries”);’ 抛出错误