2013-07-29 36 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? –

相關問題