Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inconsistant behaviour of a HTTP PATCH request on a com.mongodb.BasicDBObject member [DATAREST-772] #1147

Open
spring-projects-issues opened this issue Feb 22, 2016 · 1 comment
Assignees
Labels
type: bug

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Feb 22, 2016

Marc Tarin opened DATAREST-772 and commented

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" : {
    "a" : 2,
    "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


Affects: 2.4.2 (Gosling SR2)

@spring-projects-issues
Copy link
Author

spring-projects-issues commented Feb 22, 2016

Marc Tarin commented

Edited formatting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug
Projects
None yet
Development

No branches or pull requests

2 participants