我想包装来自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());
}
}
是的,这按预期工作。但是请想象一下user
是null
-你们中的一些人可能已经读过“哦,伙计,如果用户名不存在,他可能在那里有一个NPE”,您是绝对正确的。可以肯定的是,我确实在为这类事情编写代码。但是,我不会抓住所有这些情况。我想在某处添加一个异常处理程序,该异常处理程序捕获所有这些异常并将它们包装在AwesomeException
中-特别是这样,我可以将相关的错误代码传递给用户,以便他们可以与发生问题的支持人员联系。我不想依靠程序员总是记住每个可能的null和非法参数以及所有其他运行时异常。我当然不希望他们沾沾自喜,但我确实要确保用户始终具有错误代码以与支持人员联系。
(错误代码实际上是一个请求ID-每个请求都有一个ID,并且所有日志消息在打印时都使用该ID-因此,如果它们报告错误代码,我们可以很容易地看到带有该请求的所有日志消息和解决错误。)
我尝试跟踪回调,但是最终在RPC类中迷路了。但是,我当然不是第一个尝试拦截服务器发出的GWT异常的人,对吗?
答案 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
是服务接口的实现。由于您正在控制服务实现的创建,因此现在可以将其包装在代理中以转换异常或进行日志记录。