spring-projects / spring-data-rest

Simplifies building hypermedia-driven REST web services on top of Spring Data repositories
https://spring.io/projects/spring-data-rest
Apache License 2.0
921 stars 562 forks source link

Infinite recursion when requesting application/vnc.api+json data [DATAREST-767] #1141

Open spring-projects-issues opened 8 years ago

spring-projects-issues commented 8 years ago

Gabriel Bauman opened DATAREST-767 and commented

I have a test Spring Boot application with a single entity Contact and CrudRepository at /contact. There are no entity relationships.

When there are no entities in the database, the request:

curl 'http://localhost:8080/contacts' -H 'Accept: application/vnd.api+json'

Returns:

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/contacts"
  }, {
    "rel" : "profile",
    "href" : "http://localhost:8080/profile/contacts"
  } ],
  "content" : [ {
    "collectionValue" : true,
    "rel" : null,
    "relTargetType" : "sdr.Contact",
    "value" : [ ]
  } ]
}

But, when I add a record to the database, the same curl request is infinitely recursive:

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/contacts"
  }, {
    "rel" : "profile",
    "href" : "http://localhost:8080/profile/contacts"
  } ],
  "content" : [ {
    "id" : 1,
    "firstName" : "Test",
    "lastName" : "Person",
    "embeddeds" : {
      "content" : [ ]
    },
    "propertyAccessor" : {
      "bean" : {
        "id" : 1,
        "firstName" : "Test",
        "lastName" : "Person"
      }
    },
    "persistentEntity" : {
      "idProperty" : {
        "name" : "id",
        "rawType" : "java.lang.Long",
        "field" : {
          "name" : "id",
          "type" : "java.lang.Long",
          "modifiers" : 2,
          "annotations" : [ ],
          "declaredAnnotations" : [ ],
          "synthetic" : false,
          "declaringClass" : "sdr.Contact",
          "enumConstant" : false,
          "genericType" : "java.lang.Long",
          "annotatedType" : {
            "type" : "java.lang.Long",
            "annotations" : [ ],
            "declaredAnnotations" : [ ]
          },
          "accessible" : true
        },
        "association" : false,
        "owner" : {
          "idProperty" : {
            "name" : "id",
            "rawType" : "java.lang.Long",
            "field" : {
              "name" : "id",
              "type" : "java.lang.Long",
              "modifiers" : 2,
              "annotations" : [ ],
              "declaredAnnotations" : [ ],
              "synthetic" : false,
              "declaringClass" : "sdr.Contact",
              "enumConstant" : false,
              "genericType" : "java.lang.Long",
              "annotatedType" : {
                "type" : "java.lang.Long",
                "annotations" : [ ],
                "declaredAnnotations" : [ ]
              },
              "accessible" : true
            },
            "association" : false,
            "owner" : {
              "idProperty" : {
                "name" : "id",
                "rawType" : "java.lang.Long",
                "field" : {
                  "name" : "id",
                  "type" : "java.lang.Long",
                  "modifiers" : 2,
                  "annotations" : [ ],
                  "declaredAnnotations" : [ ],
                  "synthetic" : false,
                  "declaringClass" : "sdr.Contact",
                  "enumConstant" : false,
                  "genericType" : "java.lang.Long",
                  "annotatedType" : {
                    "type" : "java.lang.Long",
                    "annotations" : [ ],
                    "declaredAnnotations" : [ ]
                  },
                  "accessible" : true
                },
                "association" : false,
                "owner" : {
... CONTINUED RECURSION ...

The server stack trace looks like this:

DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: org.springframework.data.jpa.mapping.JpaPersistentEntityImpl["idProperty"]->org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl["owner"]->org.springframework.data.jpa.mapping.JpaPersistentEntityImpl["idProperty"]->org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl["owner"]->... recursion

Affects: 2.4.2 (Gosling SR2), 2.4.4 (Gosling SR4)

Reference URL: http://stackoverflow.com/questions/35349908/why-does-requesting-jsonapi-metadata-from-a-spring-data-rest-repository-return-a

Attachments:

2 votes, 5 watchers

spring-projects-issues commented 8 years ago

Gabriel Bauman commented

Demo project, instructions to reproduce in README.md

spring-projects-issues commented 8 years ago

Gabriel Bauman commented

Hmm, it appears that there are a number of related bugs. See DATAREST-733 and DATAREST-734

spring-projects-issues commented 8 years ago

Gabriel Bauman commented

Added stack trace showing recursion

spring-projects-issues commented 7 years ago

Jens Janssen commented

Have the same problem with "x-spring-data-verbose+json" and "x-spring-data-compact+json".

Invinite loop of:

"association" : false, "owner" : { "idProperty" : { "name" : "id", "rawType" : "java.lang.Integer", "field" : { "name" : "id", "type" : "java.lang.Integer", "modifiers" : 2, "annotations" : [ { }, { } ], "declaredAnnotations" : [ { }, { } ], "synthetic" : false, "declaringClass" : "Access", "enumConstant" : false, "genericType" : "java.lang.Integer", "annotatedType" : { "type" : "java.lang.Integer", "annotations" : [ ], "declaredAnnotations" : [ ] }, "accessible" : true }, "association" : false, "owner" : { ....

spring-projects-issues commented 7 years ago

Thomas Kallenberg commented

Ran into the same problem. Does somebody knows a workaround?

ramonflores commented 3 years ago

Same problem with spring-data-rest & @RepositoryRestResource.