Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-2901

Upon a serialization error, jackson2 writes garbage (partially serialized entity) to resteasy's Response

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • 3.13.2.Final
    • None
    • Hide

      (originally discovered running 3.13.2.Final through WildFly 21.0.0.Final; reproduced on main branch as well - see additional MR)

      com.fasterxml.jackson.databind.JsonMappingException thrown from this entrypoint, after it has already built at least part of the resulting JSON.

      The file DispatcherResponseJackson2Test reproduces the scenario.

      File DispatcherResponseJsonBTest shows it doesn't happen with JSONB, probably because it doesn't mess with resteasy-owned OutputStream in this case (maybe it does when the partially written Response lenght is above certain buffer-size threshold?).

      Show
      (originally discovered running 3.13.2.Final through WildFly 21.0.0.Final; reproduced on main branch as well - see additional MR) com.fasterxml.jackson.databind.JsonMappingException thrown  from this entrypoint , after it has already built at least part of the resulting JSON. The file DispatcherResponseJackson2Test reproduces the scenario. File DispatcherResponseJsonBTest shows it doesn't happen with JSONB, probably because it doesn't mess with resteasy-owned OutputStream in this case (maybe it does when the partially written Response lenght is above certain buffer-size threshold?).
    • Undefined

      One of the DTOs of our application was throwing a NullPointerException and while debugging it I found out it was during jackson's JSON serialization (called by resteasy to produce a response). However, as I debugged the code, it seems to me it could (and maybe should) be fixed in the resteasy code, since it's the owner of the OutputStream involved.

      I'll try to describe what I understood of what is happening (I'm sorry if this is not the correct way to do it; still trying to figure out how to contribute properly):

      1. The SynchronousDispatcher triggers the writing of the response;
      2. ServerResponseWriter obtains the OutputStream to be used and, after a few wrappings on it, through the AbstractWriterInterceptorContext the ResteasyJackson2Provider middleware is called;
      3. Jackson's serialization starts to take place at this point. In our scenario, the serialization fails deeply into the DTO, due to the NPE mentioned before. The problem is that on the finally close of the generator, jackson will write the JSON it has built so far into the OutputStream owned by resteasy (and could have even written something there before this point, if the response were really huge and thus larger than its internal/local buffer, for instance).
      4. This means that, when the code reaches this handler to write the exception, the response object's OutputStream has stuff written to it. This results in the API response being an invalid JSON, consisting of the partially built success response concatenated with the JSON written by our registered ExceptionHandler. It consist of, e.g.: {"id": 3, "name": "John", "props": [1, 4, 7]} {"errorCode": "ARQ-502", "message": "JSON serialization error"}

      I've drafted a possible fix which worked when retesting this specific scenario, but I'm not sure if it is the correct way (or point) to fix it.

      Also, since the fix I made for this is actually at the SynchronousDispatcher, I think (in case it is an adequate fix) the bug could actually be jackson-independent.

              Unassigned Unassigned
              bsmelo Bruno Melo (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: