如何在GWT的SERVER端添加异常处理程序?

时间:2019-01-06 01:00:21

标签: java gwt exception-handling

我想包装来自GWT服务器的所有传出异常(仅服务器,客户端无内容):

public class AuthServiceImpl extends RemoteServiceServlet implements AuthService {
    public String loginAttemt(String username, String password) {
        AwesomeUser user = AwesomeUserDao.forUsername(username);
        if(BCrpyt.checkpw(user.getPasshash(), password)) {
            String code = magicallyGenerateErrorCode();
            logger.error("Invalid login attempt - error code"  + code);
            throw new AwesomeException("password", "Invalid username or password", code);
        }
    }
}

@RemoteServiceRelativePath("auth")
public interface AuthService extends RemoteService {
    String loginAttempt(String username, String password) throws AwesomeException;
}

public interface AuthServiceAsync {
    void loginAttempt(String username, String password, AsyncCallback<String> callback) throws AwesomeException;
}

现在,这可行。在我的客户端上,我只是做这样的事情(getField(String)是我出于不相关的原因而进行的一些自定义,但是可以理解这一点)

public void onFailure(Throwable caught) {
    if(caught instanceof AwesomeException) {
        AwesomeException a = (AwesomeException)caught;
        getField(a.getfield()).setErrorText(a.getText());
        getField("error-code").setText(a.getCode());
    }
}

是的,这按预期工作。但是请想象一下usernull-你们中的一些人可能已经读过“哦,伙计,如果用户名不存在,他可能在那里有一个NPE”,您是绝对正确的。可以肯定的是,我确实在为这类事情编写代码。但是,我不会抓住所有这些情况。我想在某处添加一个异常处理程序,该异常处理程序捕获所有这些异常并将它们包装在AwesomeException中-特别是这样,我可以将相关的错误代码传递给用户,以便他们可以与发生问题的支持人员联系。我不想依靠程序员总是记住每个可能的null和非法参数以及所有其他运行时异常。我当然不希望他们沾沾自喜,但我确实要确保用户始终具有错误代码以与支持人员联系。

(错误代码实际上是一个请求ID-每个请求都有一个ID,并且所有日志消息在打印时都使用该ID-因此,如果它们报告错误代码,我们可以很容易地看到带有该请求的所有日志消息和解决错误。)

我尝试跟踪回调,但是最终在RPC类中迷路了。但是,我当然不是第一个尝试拦截服务器发出的GWT异常的人,对吗?

2 个答案:

答案 0 :(得分:1)

这可以通过扩展RemoteServiceServlet并在processCall(RPCRequest rpcRequest)doUnexpectedFailure(Throwable e)中进行异常处理来完成。

例如:

  

仅针对不属于异常的异常或错误调用此方法   服务方法的签名,或来自   SecurityException,SerializationException或其他内部失败   RPC框架。

意味着任何NPE等都可以在此处映射到自定义例外。

  protected void doUnexpectedFailure(Throwable e) {
    try {
      getThreadLocalResponse().reset();
    } catch (IllegalStateException ex) {
      /*
       * If we can't reset the request, the only way to signal that something
       * has gone wrong is to throw an exception from here. It should be the
       * case that we call the user's implementation code before emitting data
       * into the response, so the only time that gets tripped is if the object
       * serialization code blows up.
       */
      throw new RuntimeException("Unable to report failure", e);
    }
    ServletContext servletContext = getServletContext();

    String code = magicallyGenerateErrorCode();
    AwesomeException awesomeException = new AwesomeException("error", "Unexpected Error. Pls contact support", code);

    RPCServletUtils.writeResponseForUnexpectedFailure(servletContext,
        getThreadLocalResponse(), awesomeException);
  }

答案 1 :(得分:1)

您可以创建自己的servlet并将其委托给RemoteServiceServlet,而不是扩展RemoteServiceServlet的服务,例如:

public class GwtServiceServlet extends HttpServlet {
    public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException {
        Object delegate = ...;

        RemoteServiceServlet remoteServiceServlet = new RemoteServiceServlet(delegate);
        remoteServiceServlet.init(getServletConfig());
        remoteServiceServlet.doPost(request, response);
    }
}

delegate是服务接口的实现。由于您正在控制服务实现的创建,因此现在可以将其包装在代理中以转换异常或进行日志记录。