Json 在Jersey中重写MessageBodyReader以包装反序列化过程

Json 在Jersey中重写MessageBodyReader以包装反序列化过程,json,rest,serialization,jersey,jackson,Json,Rest,Serialization,Jersey,Jackson,我有一个使用Grizzly、Jersey和Jackson stack的restful服务。如果我在请求中提供了错误的输入值,例如:一个随机字符串而不是UUID,那么Jackson会抛出一个无效的格式或无法识别的属性异常。出于安全目的,我为大多数通用异常添加了异常映射程序,以隐藏异常详细信息。但对于这种非常特殊的情况,如果用户提供了错误的数据,反序列化失败,我想向用户反馈调用失败的原因 我认为,如果我可以包装从Jersey到Jackson的反序列化调用,那么我可以抛出一个带有适当数据的自定义异常,

我有一个使用Grizzly、Jersey和Jackson stack的restful服务。如果我在请求中提供了错误的输入值,例如:一个随机字符串而不是UUID,那么Jackson会抛出一个无效的格式或无法识别的属性异常。出于安全目的,我为大多数通用异常添加了异常映射程序,以隐藏异常详细信息。但对于这种非常特殊的情况,如果用户提供了错误的数据,反序列化失败,我想向用户反馈调用失败的原因

我认为,如果我可以包装从Jersey到Jackson的反序列化调用,那么我可以抛出一个带有适当数据的自定义异常,并为自定义异常添加一个映射器

因此,我创建了一个新类,该类重写JacksonJaxbJsonProvider,并将包装器代码添加到readFrom

@Provider
@Consumes(MediaType.WILDCARD) // NOTE: required to support "non-standard" JSON variants
@Produces(MediaType.WILDCARD)
public class JacksonJaxbJsonProviderOverride extends JacksonJaxbJsonProvider {
  private static final Logger logger = LoggerFactory.getLogger(JacksonJaxbJsonProviderOverride.class);

  @Override
  public Object readFrom(
      Class<Object> type,
      Type genericType,
      Annotation[] annotations,
      MediaType mediaType,
      MultivaluedMap<String, String> httpHeaders,
      InputStream entityStream)
      throws IOException {
    try {
      return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
    } catch (Exception ex) {
      throw new ObjectDeserializationException(ex.getMessage());
    }
  }
但是对反序列化的调用不会影响覆盖。你有没有想过为什么会这样

    com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.UUID from String value 'foo': not a valid textual representation, problem: UUID has to be represented by the standard 36-char representation
 at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@43277af; line: 1, column: 2] (through reference chain: com.oracle.opc.nimbula.foo.models.api.BackupInput["backupConfigurationId"])
        at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:907) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer.deserialize(FromStringDeserializer.java:136) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1470) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:912) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:810) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$lReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:74) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:94) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourcDispatcherProvider.java:160) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.j) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571) [program-0.3.0-20160226101624.jar:na]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73]
Caused by: java.lang.NumberFormatException: UUID has to be represented by the standard 36-char representation
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._badFormat(UUIDDeserializer.java:75) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._deserialize(UUIDDeserializer.java:40) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._deserialize(UUIDDeserializer.java:11) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer.deserialize(FromStringDeserializer.java:122) ~[program-0.3.0-20160226101624.jar:na]
        ... 38 common frames omitted

看起来不像是完整的stacktrace。你能把整件事都贴出来吗?顺便说一下,错误响应是由ExceptionMappers发送的。Jackson为JsonMappingException和JsonParseException提供了一个。您不能注册这些,也不能注册您的own@peeskillet我添加了完整的堆栈跟踪。ExceptionMappers不起作用,因为我在其他地方使用Jackson进行序列化/反序列化。如果为每个序列化/反序列化添加异常映射器,则可能会向用户泄漏信息。我想告诉Jersey,只有在反序列化过程中,如果它抛出错误,然后将其包装到自定义异常中,我可以为其添加异常映射器。可能有不同的方法来执行此操作。configure(反序列化功能。wrap_EXCEPTIONS,false);也许这会有帮助。。。
    com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.UUID from String value 'foo': not a valid textual representation, problem: UUID has to be represented by the standard 36-char representation
 at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@43277af; line: 1, column: 2] (through reference chain: com.oracle.opc.nimbula.foo.models.api.BackupInput["backupConfigurationId"])
        at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:907) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer.deserialize(FromStringDeserializer.java:136) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1470) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:912) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:810) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$lReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:74) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:94) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourcDispatcherProvider.java:160) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) ~[program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.j) [program-0.3.0-20160226101624.jar:na]
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571) [program-0.3.0-20160226101624.jar:na]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73]
Caused by: java.lang.NumberFormatException: UUID has to be represented by the standard 36-char representation
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._badFormat(UUIDDeserializer.java:75) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._deserialize(UUIDDeserializer.java:40) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.UUIDDeserializer._deserialize(UUIDDeserializer.java:11) ~[program-0.3.0-20160226101624.jar:na]
        at com.fasterxml.jackson.databind.deser.std.FromStringDeserializer.deserialize(FromStringDeserializer.java:122) ~[program-0.3.0-20160226101624.jar:na]
        ... 38 common frames omitted