【问题标题】:GWT Throwing exception to clientGWT向客户端抛出异常
【发布时间】:2011-01-28 06:47:09
【问题描述】:

有人可以显示在 GWT 中向客户端抛出异常吗?

在我的 serviceasync 接口中,我也在我的服务接口中这样做

void ActivateUserAccount(String ActivationCode,AsyncCallback <Boolean> Callback) throws AlreadyActivatedError;

在我的服务器实现中;

我这样做是为了抛出异常

public Boolean ActivateUserAccount(String ActivationCode) throws AlreadyActivatedError
    {
....
throw new AlreadyActivatedError();
}

我的例外是:

public class AlreadyActivatedError extends Exception implements IsSerializable
{
    public AlreadyActivatedError()
    {
        super();
    }
}

【问题讨论】:

  • 你能澄清你的问题吗?.. 你目前的方法有什么问题?您在服务器端抛出的异常没有到达 gwt 客户端。这是您的问题吗?。

标签: gwt exception-handling throw


【解决方案1】:

只是为了说明一切:您可以将已检查(扩展 Exception)和未检查(扩展 RuntimeException)的异常从服务器抛出到客户端 - 只要异常是 serializable。但是建议抛出已检查的异常,因为它们

表示程序无法直接控制的区域中的无效条件(无效的用户输入、数据库问题、网络中断、缺少文件)。

相比之下,未经检查的异常

表示程序中的缺陷(错误) - 传递给非私有方法的参数通常无效。

Source

作为documentation states,必须满足以下条件才能向客户端发送异常:

  • 它必须扩展Exception(注意RuntimeException 会这样做)。
  • 必须是serializable。简而言之:实现Serializable,有一个无参数的构造函数,并且所有的字段都可以序列化。
  • 在您的*Service 接口中,您需要向可以抛出异常的方法添加throws 声明。请注意,您无需将throws 声明添加到*Async 接口。

设置完成后,您将能够在 AsyncCallback 中的 onFailure 方法中处理异常。

根据the guide on the GWT site 中的示例,一些代码将所有部分显示在一起:

DelistedException.java

public class DelistedException extends Exception implements Serializable {

  private String symbol;

  // Note the no-args constructor
  // It can be protected so that only subclasses could use it
  // (because if they want to be serializable too, they'll need
  // a no-args constructor that calls the superclasses' no-args constructor...)
  protected DelistedException() {
  }

  public DelistedException(String symbol) {
    this.symbol = symbol;
  }

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

StockPriceService.java

@RemoteServiceRelativePath("stockPrices")
public interface StockPriceService extends RemoteService {
  StockPrice[] getPrices(String[] symbols) throws DelistedException;
}

StockPriceServiceAsync.java

public interface StockPriceServiceAsync {
  void getPrices(String[] symbols, AsyncCallback<StockPrice[]> callback);
}

在客户端

AsyncCallback<StockPrice[]> callback = new AsyncCallback<StockPrice[]>() {
  public void onFailure(Throwable caught) {
    if (caught instanceof DelistedException) {
      // Do something with it
    } else {
      // Probably some unchecked exception,
      // show some generic error message
  }

  public void onSuccess(StockPrice[] result) {
    // Success!
  }
};

stockPriceService.getPrices(symbols, callback);

【讨论】:

    【解决方案2】:

    不知道为什么希拉尔的回答被接受了,因为它完全是错误的。

    为了让异常到达客户端的浏览器,您必须抛出一个checked exception,即Serializable,并在服务接口中定义。

    如果您的服务实现抛出RuntimeException,Web 客户端将收到如下一般性 500 错误消息:

       [WARN] Exception while dispatching incoming RPC call
    com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract my.module.shared.Result my.module.client.service.Service.doSomething() throws my.module.shared.exception.MyCheckedException' threw an unexpected exception: my.module.shared.exception.AuthzRuntimeException: some authz message
        at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:389)
        at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:579)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
        at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:324)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
        at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
    Caused by: my.module.shared.exception.AuthzRuntimeException: some authz message
        at my.module.shared.Authz.doSomeCheck(Authz.java:101)
        at my.module.server.ServiceImpl.doSomething(ServiceImpl.java:283)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:561)
        ... 22 more
    [ERROR] 500 - POST /module/userService (127.0.0.1) 57 bytes
       Request headers
          Host: 127.0.0.1:8888
          User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
          Accept-Language: en-US,en;q=0.5
          Accept-Encoding: gzip, deflate
          Referer: http://127.0.0.1:8888/foo.html?gwt.codesvr=127.0.0.1:9997
          Cookie: worknet=7k8g41ulbl674dp865t180tji5
          Connection: keep-alive
          Cache-Control: no-cache
          X-GWT-Permutation: HostedMode
          X-GWT-Module-Base: http://127.0.0.1:8888/module/
          Content-Type: text/x-gwt-rpc; charset=utf-8
          Content-Length: 1076
          Pragma: no-cache
       Response headers
          Content-Type: text/plain
    (RequestCallbackAdapter.java:209) 2013-10-18 13:16:56,966 [WARN ] Fail ""
    com.google.gwt.user.client.rpc.StatusCodeException: 500 The call failed on the server; see server log for details
        at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:209)
        at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:258)
        at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:412)
        at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
        at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
        at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
        at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338)
        at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219)
        at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
        at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
        at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
        at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
        at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242)
        at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
        at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
        at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
        at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
        at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
        at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
        at java.lang.Thread.run(Unknown Source)
    

    【讨论】:

      【解决方案3】:

      GWT 只能处理从RuntimeException 扩展的未序列化的unchecked exceptions(表示从服务器发送到客户端)。我不知道AlreadyActivatedError 是什么。如果不是 RuntimeException 则无法发送到客户端(浏览器)

      【讨论】:

      • Hilal,你说的正好相反。只有在服务器端生成的检查异常才会发送到 gwt 层。对于未经检查的异常,您只会得到 com.google.gwt.user.client.rpc.StatusCodeException 。你应该更正你的答案..
      • @Gursel 从 Eclipse 中的新 Web 项目开始。您可以看到从 RuntimeExcetion 扩展而来的 IllegalArgumentException,这是未经检查的异常
      • 好吧,和我说的有什么关系。我没有说IllegalArgument异常是checkedException。我所说的只是检查的异常从服务器传播到 gwt 层。您可以轻松检查。
      • 所以我们说同样的话,但格式不同。写“可以处理”我的意思是异常应该是可以在客户端处理和捕获的运行时异常
      • Gursel,我也对这个答案被接受感到困惑,因为它完全是错误的。如果您尝试从服务实现中抛出未经检查的 RuntimeException,我会在答案中详细说明 Jetty 日志中显示的内容。
      【解决方案4】:

      也许还要注意,如果你的特定 Exception 没有标准构造函数,也会显示通用的 500 错误消息,因为无法反序列化异常。可悲的是,gwt 编译器和开发模式插件并不总是明确指出这个问题..(这就是我到达这里的方式)

      所以,结合vinnyjames所说的(异常必须是Serializable并且在(RPC)服务的接口中定义的),我发现gwt客户端代码中处理异常并不太复杂。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 2021-03-19
        • 1970-01-01
        相关资源
        最近更新 更多