注意:https://gist.github.com/SrikanthRao/c9fc35e6fe22a74ab40c
提供了重现此问题的所有代码http://localhost:8080/date/bean?date=2014-13-23(使用BeanParam)生成 " {"代码":500,"消息":"处理您的请求时出错。它已被记录(ID 48be9aa43bd49547)。"}"不添加MultiExceptionMapper到泽西。
如果我将MultiExceptionMapper添加到jersey,则上面的url会导致
"日期不是YYYY-MM-DD格式或无效"
http://localhost:8080/date?date=2014-13-23(直接@QueryParam参数)生成 "日期不是YYYY-MM-DD格式或无效"
几个问题:
这是请求时生成的堆栈跟踪(不将MultiExceptionMapper添加到jersey)。当然删除了很长的痕迹。如果您需要完整的堆栈跟踪,请告诉我。
ERROR [2015-05-04 18:48:33,366] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 0f23e4de758653d6
! javax.ws.rs.WebApplicationException: HTTP 400 Bad Request
! at io.dropwizard.jersey.params.AbstractParam.<init>(AbstractParam.java:28) ~[dropwizard-jersey-0.8.1.jar:0.8.1]
! at com.fun.myapp.LocalDateTimeParam.<init>(LocalDateTimeParam.java:20) ~[classes/:na]
! at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_45]
...
...
Causing: org.glassfish.hk2.api.MultiException: A MultiException has 3 exceptions. They are:
! 1. javax.ws.rs.WebApplicationException: HTTP 400 Bad Request
! 2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.fun.myapp.PaginationFilters errors were found
! 3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.fun.myapp.PaginationFilters
!
! at org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88) ~[hk2-locator-2.4.0-b10.jar:na]
! at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:252) ~[hk2-locator-2.4.0-b10.jar:na]
! at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360) ~[hk2-locator-2.4.0-b10.jar:na]
! at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) ~[hk2-locator-2.4.0-b10.jar:na]
....
....
WARN [2015-05-04 18:48:33,401] org.glassfish.jersey.internal.Errors: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 3
javax.ws.rs.WebApplicationException: HTTP 400 Bad Request
at io.dropwizard.jersey.params.AbstractParam.<init>(AbstractParam.java:28)
at com.fun.myapp.LocalDateTimeParam.<init>(LocalDateTimeParam.java:20)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
...
...
MultiException stack 2 of 3
java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.fun.myapp.PaginationFilters errors were found
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:249)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
...
...
MultiException stack 3 of 3
java.lang.IllegalStateException: Unable to perform operation: resolve on com.fun.myapp.PaginationFilters
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:389)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162)
我在dropwizard用户google群组中提出了这个问题 - https://groups.google.com/forum/#!topic/dropwizard-user/yW-RXSSlspY
答案 0 :(得分:4)
问题1
根据dropwizard的核心文档,我看到了两种可能的输入验证实现:
您可以将验证注释添加到表示类的字段并验证它们......
这似乎不适合您的情况。实际上,LocalDateTime没有可用的注释,并且创建一个注释导致解析LocalDateTime两次:用于验证和设置bean字段。
如果你想要更多的控制,你也可以在你的环境中声明JerseyProviders,通过调用JerseyEnvironment#register(Object)来实现javax.ws.rs.ext.ExceptionMapper ...
要回答你的第一个问题,我会说在你的情况下使用异常映射器完全没问题。
问题2 调试两个isValidDate方法显示@BeanParam版本使用ClazzCreator.java而@QueryParam不使用。该类负责创建bean类实例。如果您检查the class的第226行,您将看到它在解析具有多个错误的输入时收集多个异常。这应该允许报告与不同bean字段相关的几个错误,包括一些后续异常。
答案是Jeysey在POJO中支持* Params。但是,在@BeanParam的上下文中封装成MultiException的相关异常。 因此,如果您计划将其他字段添加到PaginationFilters,则应考虑在映射的异常消息中报告多个错误。
答案 1 :(得分:0)
1 /为了验证日期,我更喜欢自己解析“日期”。它简单而干净。这是一些有效的代码:
package com.rizze.stackoverflow;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
@Path("/test")
public class TestRessource {
@GET
@Path("is")
@Produces({"application/json"})
public Response isDateValid(@QueryParam("date") String dateString){
if(dateString == null)
return Response.status(400).entity("date is null").build();
Date thedate =null;
try {
thedate = new SimpleDateFormat("yyyy-mm-dd").parse(dateString);
}
catch (ParseException e) {
return Response.status(400).entity("date malformed").build();
}
System.out.println("time:"+thedate.getTime());
return Response.ok()
.entity("{\"time\":"+ thedate.getTime() +"}")
.header("source", "com.rizze")
.build();
}
}
在此代码中,您将调用
http://localhost:8080/test/is?date=2014-12-12
将返回:
{"time":1389496320000}
看一下要点:https://gist.github.com/jeorfevre/6e46ae8d9232f7f9d7cc
2 /为了捕获异常,一个好的做法是通过Providers捕获服务器级异常(通过向应用程序注册提供程序)。 对于应用程序级异常,请使用response.status(异常状态)自行利用异常.....
请看一下我的fork gist,我添加了一个_ServerError.class,我在应用程序中注册了它:
//register a mapper by rizze
environment.jersey().register(_ServerError.class);
请查看cristal明确的官方文件: official jersey representation doc