2013-07-29 35 views
2

我有一个Web应用程序,其中服务器以JSON格式返回任何结果。为了创建JSON,我使用codehaus Jackson ObjectWriter,版本1.9.8。JsonMappingException:(was java.lang.ArrayIndexOutOfBoundsException)

我遇到的问题是,有时在映射中存在错误,并且从那时起所有服务器调用都会导致错误。我一直无法确定是什么原因导致错误,我确实发现了原因。

当发生异常时,服务器返回“(was java.lang.ArrayIndexOutOfBoundsException)(通过引用链:com.onior.modm.restlet.helpers.ServiceResult [”success“])”,这意味着异常抛出'toJSON'被捕获并通过'toRepresentation'映射到JSON,否则它将返回空。

我只是不知道为什么它有时会失败。我将可以在整个上午使用应用程序,而不会出现任何问题,然后我会突然发现这个错误。它发生在不同的电话上,但这些电话会在其他时间成功。从我的角度来看,这似乎很随意,但也许有人可以帮助我看到光明? :)

正被映射到的服务器结果:

public class ServiceResult<T> { 
    private boolean success; 
    private T results = null; 
    private ModmServiceStatus message = null; 

    public ServiceResult() { 
    } 

    public ServiceResult(T results) { 
     this.success = true; 
     this.results = results; 
    } 

    public ServiceResult(boolean success, ModmServiceStatus message) { 
     this.success = success; 
     this.message = message; 
    } 

    public ServiceResult(ServiceError error) { 
     this(false, new ModmServiceStatus(error)); 
    } 

    public static ServiceResult<ModmServiceStatus> serviceException(
     ServiceError error) { 
     return new ServiceResult<ModmServiceStatus>(false, 
      new ModmServiceStatus(error.getCode(), error.getDescription())); 
    } 

    public static ServiceResult<ModmServiceStatus> dbError() { 
     return ServiceResult 
      .serviceException(ServiceError.GENERIC_DATABASE_ERROR); 
    } 

    public static ServiceResult<ModmServiceStatus> invalidJson() { 
     return ServiceResult 
      .serviceException(ServiceError.GENERIC_INVALID_JSON); 
    } 

    public static ServiceResult<ModmServiceStatus> missingEntity() { 
     return ServiceResult    .serviceException(ServiceError.GENERIC_MISSING_OR_INCOMPLETE_ENTITY); 
    } 

    public static ServiceResult<ModmServiceStatus> entityNotFound() { 
     return ServiceResult 
      .serviceException(ServiceError.GENERIC_ENTITY_NOT_FOUND); 
    } 

    public static ServiceResult<ModmServiceStatus> entityDeleted(String entity) { 
     return new ServiceResult<ModmServiceStatus>(true, 
      new ModmServiceStatus(0, entity + " deleted.")); 
    } 
} 

映射:

public class RestUtils { 
    private static final boolean PRETTY_PRINT = true; 

    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 
    public static final ObjectWriter OBJECT_WRITER = (PRETTY_PRINT ? OBJECT_MAPPER 
     .writerWithDefaultPrettyPrinter() : OBJECT_MAPPER.writer()); 

    @SuppressWarnings("unchecked") 
    public static <T> JacksonRepresentation<T> toJSON(T t) throws IOException { 
     JsonRepresentation jsonRepresentation = null; 
     JacksonRepresentation<T> jacksonRepresentation = null; 
     jsonRepresentation = new JsonRepresentation(
      OBJECT_WRITER.writeValueAsString(t)); // Origin of incidental 
                // server error 
     jacksonRepresentation = new JacksonRepresentation<T>(
      jsonRepresentation, (Class<T>) t.getClass()); 
     return jacksonRepresentation; 
    } 

    public static <T> Representation toRepresentation(ServiceResult<T> ss) { 
     Representation representation = null; 
     try { 
     representation = RestUtils.toJSON(ss); 
     } catch (IOException jsonException) { 
      jsonException.printStackTrace(); 
      try { 
       jsonException.printStackTrace(); 
       representation = RestUtils.toJSON(jsonException.getMessage()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     return representation; 
    } 
} 

呼叫:

org.codehaus.jackson.map.JsonMappingException: (was java.lang.ArrayIndexOutOfBoundsException) (through reference chain: com.onior.modm.restlet.helpers.ServiceResult["success"]) 
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218) 
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183) 
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140) 
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158) 
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) 
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610) 
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256) 
    at org.codehaus.jackson.map.ObjectWriter._configAndWriteValue(ObjectWriter.java:456) 
    at org.codehaus.jackson.map.ObjectWriter.writeValueAsString(ObjectWriter.java:393) 
    at com.onior.modm.restlet.helpers.RestUtils.toJSON(RestUtils.java:52) 
    at com.onior.modm.restlet.helpers.RestUtils.toRepresentation(RestUtils.java:71) 
    at com.onior.modm.restlet.resources.GroupCollectionResource.toJsonRead(GroupCollectionResource.java:191) 
    at sun.reflect.GeneratedMethodAccessor143.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:506) 
    at org.restlet.resource.ServerResource.get(ServerResource.java:707) 
    at org.restlet.resource.ServerResource.doHandle(ServerResource.java:589) 
    at org.restlet.resource.ServerResource.doNegotiatedHandle(ServerResource.java:649) 
    at org.restlet.resource.ServerResource.doConditionalHandle(ServerResource.java:348) 
    at org.restlet.resource.ServerResource.handle(ServerResource.java:952) 
    at org.restlet.resource.Finder.handle(Finder.java:246) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Router.doHandle(Router.java:431) 
    at org.restlet.routing.Router.handle(Router.java:648) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Router.doHandle(Router.java:431) 
    at org.restlet.routing.Router.handle(Router.java:648) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.routing.Filter.doHandle(Filter.java:159) 
    at org.restlet.routing.Filter.handle(Filter.java:206) 
    at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211) 
    at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:84) 
    at org.restlet.Application.handle(Application.java:381) 
    at org.restlet.ext.servlet.ServletAdapter.service(ServletAdapter.java:206) 
    at org.restlet.ext.spring.RestletFrameworkServlet.doService(RestletFrameworkServlet.java:124) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.ArrayIndexOutOfBoundsException 
    at org.codehaus.jackson.impl.WriterBasedGenerator.writeRaw(WriterBasedGenerator.java:577) 
    at org.codehaus.jackson.util.DefaultPrettyPrinter$Lf2SpacesIndenter.writeIndentation(DefaultPrettyPrinter.java:279) 
    at org.codehaus.jackson.util.DefaultPrettyPrinter.beforeObjectEntries(DefaultPrettyPrinter.java:98) 
    at org.codehaus.jackson.impl.WriterBasedGenerator._writePPFieldName(WriterBasedGenerator.java:410) 
    at org.codehaus.jackson.impl.WriterBasedGenerator._writeFieldName(WriterBasedGenerator.java:340) 
    at org.codehaus.jackson.impl.WriterBasedGenerator.writeFieldName(WriterBasedGenerator.java:217) 
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:444) 
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) 
    ... 58 more 

RestUtils.toRepresentation(new ServiceResult<List<Group>>(groups)); 

与堆栈跟踪的异常

回答

1

与Jackson 1.9.9拥有完全相同的ArrayIndexOutOfBoundsException

调查后,我们的根本原因是多线程共享的PrettyPrinter。 如果您在为DefaultPrettyPrinter杰克逊代码看,你会看到:

/** 
* Number of open levels of nesting. Used to determine amount of 
* indentation to use. 
*/ 
protected int _nesting = 0; 

_nesting最终被用于访问阵列。处理对象时,此变量会递增和递减。如果多个线程递减它,它可能最终会导致ArrayIndexOutOfBoundsException。一旦消极,它将不会再次增加,因为在达到可增加它的一段代码之前会产生异常。

在你的代码中,我看到你有一个静态对象编写器。您可能最终得到DefaultPrettyPrinter的单个实例。如果你的应用程序可以同时产生JSON对象,给定足够的时间,你会得到异常。

Stéphan

+0

感谢您的分析。我认为ObjectMapper被认为是线程安全的......所以这实际上是Jackson 1.9中的一个bug? –

相关问题