奇怪的 Java 异常行为
Weird Java Exception Behaviour
我正在使用 Google App Engine with Cloud Endpoints。
我在其中的 Java 异常处理中注意到了一件奇怪的事情。
考虑这个异常堆栈
com.google.api.server.spi.response.ForbiddenException: Unable to find an organization(4)-user(1) match.
at com.fms.advocacy.api.auth.JwtUser.getUserFromRequest(JwtUser.java:172)
at com.fms.advocacy.api.user_profile.UserProfileApi.getCurrentUserProfile(UserProfileApi.java:150)
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.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:130)
at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:363)
at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:113)
at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:71)
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:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.fms.advocacy.filters.AccessRuleFilter.doFilter(AccessRuleFilter.java:67)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.AuthFilter.doFilter(AuthFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.CorsFilter.doFilter(CorsFilter.java:27)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.ErrorHandlerFilter.doFilter(ErrorHandlerFilter.java:38)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
这里异常是getUserFromRequest方法抛出的。
如您所见,它是从过滤器 ErrorHandlerFilter > CorsFilter > AuthFilter > AccessRuleFilter 链接而来的。
在 ErrorHandlerFilter 过滤器中,我写了一段代码,
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Throwable throwable) {
System.out.println("Got " + throwable.getMessage());
}
}
因此理想情况下,客户端不应收到任何内容,消息应打印在我的控制台中。但两者都没有发生。相反,客户端收到了以下响应。
{
"error" : {
"message" : "Unable to find an organization(4)-user(1) match.",
"code" : 403,
"errors" : [ {
"domain" : "global",
"reason" : "forbidden",
"message" : "Unable to find an organization(4)-user(1) match."
} ]
}
}
为什么会这样?
抛出的异常在到达 ErrorHandlerFilter
中的 catch 子句之前被捕获。
我不熟悉 google-app-engine,但我想它是由 com.google.api.server.spi.SystemServiceServlet
完成的,因为异常很好地包装在 json 中并且不会进一步传播。
因此,从 ErrorHandlerFilter.doFilter()
方法的角度来看,一切顺利。当 chain.doFilter(request, response);
returns 时,json 已经写入 response
的输出流。
我正在使用 Google App Engine with Cloud Endpoints。 我在其中的 Java 异常处理中注意到了一件奇怪的事情。
考虑这个异常堆栈
com.google.api.server.spi.response.ForbiddenException: Unable to find an organization(4)-user(1) match.
at com.fms.advocacy.api.auth.JwtUser.getUserFromRequest(JwtUser.java:172)
at com.fms.advocacy.api.user_profile.UserProfileApi.getCurrentUserProfile(UserProfileApi.java:150)
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.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:130)
at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:363)
at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:113)
at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:71)
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:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.fms.advocacy.filters.AccessRuleFilter.doFilter(AccessRuleFilter.java:67)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.AuthFilter.doFilter(AuthFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.CorsFilter.doFilter(CorsFilter.java:27)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.fms.advocacy.filters.ErrorHandlerFilter.doFilter(ErrorHandlerFilter.java:38)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
这里异常是getUserFromRequest方法抛出的。 如您所见,它是从过滤器 ErrorHandlerFilter > CorsFilter > AuthFilter > AccessRuleFilter 链接而来的。
在 ErrorHandlerFilter 过滤器中,我写了一段代码,
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Throwable throwable) {
System.out.println("Got " + throwable.getMessage());
}
}
因此理想情况下,客户端不应收到任何内容,消息应打印在我的控制台中。但两者都没有发生。相反,客户端收到了以下响应。
{
"error" : {
"message" : "Unable to find an organization(4)-user(1) match.",
"code" : 403,
"errors" : [ {
"domain" : "global",
"reason" : "forbidden",
"message" : "Unable to find an organization(4)-user(1) match."
} ]
}
}
为什么会这样?
抛出的异常在到达 ErrorHandlerFilter
中的 catch 子句之前被捕获。
我不熟悉 google-app-engine,但我想它是由 com.google.api.server.spi.SystemServiceServlet
完成的,因为异常很好地包装在 json 中并且不会进一步传播。
因此,从 ErrorHandlerFilter.doFilter()
方法的角度来看,一切顺利。当 chain.doFilter(request, response);
returns 时,json 已经写入 response
的输出流。