Uploaded image for project: 'Spring Data REST'
  1. Spring Data REST
  2. DATAREST-772

inconsistant behaviour of a HTTP PATCH request on a com.mongodb.BasicDBObject member

    Details

    • Type: Bug
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.4.2 (Gosling SR2)
    • Fix Version/s: None
    • Component/s: None
    • Environment:
      Java 1.8.0_73 on Windows 7 Enterprise (64 bits)

      Description

      I've created a simple webservice with Spring Boot 1.3.2 (with dependencies on spring-boot-starter-data-rest and spring-boot-starter-data-mongodb) to read/write MongoDB documents describe by the following class (getters/setters omitted):

      @Document(collection="items")
      public class Item {
          @Id
          private String id;
          private String name;
          private BasicDBObject data;
      }
      

      Persisting a new object in the database works as expected. By POSTing:

      { "name" : "foo",
        "data" : {}
      }
      

      I get the following answer (_links omitted for clarity purposes):

      {
        "name" : "foo",
        "data" : { },
        "_links" : ...
      }
      

      The purpose of the data field is to store data of variable complexity and depth.
      Let's keep it simple for now... PATCHing with:

      { "data" :
        { "a" : 1,
          "b" : 2,
          "c" : 3
        }
      }
      

      Returns:

      {
        "name" : "foo",
        "data" : {
          "a" : 1,
          "b" : 2,
          "c" : 3
        },
        "_links" : ...
      }
      

      Further PATCHing with:

      { "data" : {
        "a" : 0,
        "d" : 4
        }
      }
      

      Returns:

      {
        "name" : "foo",
        "data" : {
          "a" : 0,
          "d" : 4
        },
        "_links" : ...
        }
      }
      

      Question one: is this result correct? I would have expected the following instead:

      {
        "name" : "foo",
        "data" : {
          "a" : 0,
          "b" : 2,
          "c" : 3
          "d" : 4
        },
        "_links" : ...
      }
      

      Now, for the funny part...
      As a foreword, let me just say that I know that PATCH is unsafe and non-idempotent and should be used with caution.

      Let's say I have changed my mind about d, and I want to store a subdocument in it:
      PATCHing with:

      { "data" : {
          "a" : 2,
          "d" : {}
        }
      }
      

      Throws and exception:

      {"cause":{"cause":null,"message":"Can not update object of type java.lang.Integer (by deserializer of type com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer)"},"message":"Could not read payload!; nested exception is java.lang.UnsupportedOperationException: Can not update object of type java.lang.Integer (by deserializer of type com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer)"}
      

      There is a workaround, by simply PATCHing data with a only, then re-sending the PATCH above, I can get what I wan't, ie:

      {
        "name" : "foo",
        "data" : {
          "a" : 2,
          "d" : { }
        },
        "_links" : ...
      }
      

      A bit awkward to me, since the exception above sometimes get thrown when I re-add d as subdocument, even if I PATCHed it away before!

      Let's play a bit more (sorry for the long post, btw). The current data being:

      {
        "name" : "foo",
        "data" : {
          "a" : 0,
          "d" : 4
        },
        "_links" : ...
        }
      }
      

      With a new PATCH that goes:

      { "data" : {
          "d" : {
          "c" : 5
         }
        }
      }
      

      Consistently with what happened before, I should expect the following response:

      {
        "name" : "foo",
        "data" : {
          "d" : {
          "c" : 5
         }
        },
        "_links" : ...
        }
      }
      

      Turns out I get:

      {
        "name" : "foo",
        "data" : {
          {color:red}"a" : 2,{color}
          "d" : {
            "c" : 5
          }
        },
        "_links" : ...
      }
      

      Question two: is this result correct?
      If it the expected behaviour, It seems kind of inconsistant with the result that led me to Question One.

      Now for Question Three...
      The current data being :

      {
        "name" : "foo",
        "data" : {
          "a" : 2,
          "d" : {
            "c" : 5
          }
        },
        "_links" : ...
      }
      

      PATCHing an update for a and d:

      { "data" : {
          "a" : 3,
          "d" : {
            "c" : 4
          }
        }
      }
      

      Here's what I get:

      {
        "name" : "foo",
        "data" : {
          "a" : 2
        },
        "_links" : ...
      }
      

      The payload for d just went down the toilet
      If I re-send the PATCH, it will update d correctly.
      And if I send it again, or even if I change the contents of d once more, d get flushed down again, and so on.

      Question Three: what is happening?

      I have been scratching my head for a few hours and I really don't have a clue about this strange behaviour (and I am confident there's are many more unexpected things that could happen).

      The only thing clear is that right now, send PATCH request should be avoided when dealing with a data schema that is actually schema less, until the result can get somewhat predictable.

      Regards

        Attachments

          Activity

            People

            • Assignee:
              olivergierke Oliver Drotbohm
              Reporter:
              mavonice Marc Tarin
              Last updater:
              Marc Tarin
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: