Charlie
Charlie

Reputation: 3374

Spring Boot 2.3.x - How to apply a projection in a custom @RestController?

I am trying to apply projection on an entity returned from a custom controller annotated @RestController.

@RequestMapping(method = GET, value = "customer-api/students/viewProfile")
public @ResponseBody
ResponseEntity<?> fetchProfile(PersistentEntityResourceAssembler resourceAssembler) {

    Student student = studentRepo.findByCreatedBy(accessToken.getSubject());

    if (student != null) {
        return new ResponseEntity<>(resourceAssembler.toModel(student), HttpStatus.OK);
    } else {
        return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
    }

}

But I am getting an infinite recursion exception

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: 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"]

This code works fine in Spring Boot 1.5.17 (I can apply projections and even get HAL formatted JSON) but it breaks in Spring 2.3.x.

So what I essentially want is the functionality of a Spring Data REST exported controller like projections and HAL formatted JSON. Is that possible to do in a custom controller?

I found a similar question here but it didnt help me.

Edit 1:

There is no bi-directional relationship on Student entity. Also I am using the PersistentEntityResourceAssembler to assemble the Student entity for response body which will render any @ManyToOne association as links as explained by Oliver Gierke in this answer so I am not sure how recursion is possible

PersistentEntityResourceAssembler - which is usually injected into the controller method. It renders a single entity in a Spring Data REST way, which means that associations pointing to managed types will be rendered as links etc.

Upvotes: 0

Views: 268

Answers (2)

Charlie
Charlie

Reputation: 3374

For anyone having the same issue, I fixed it by upgrading to Spring Boot 2.5.5 and the code above now works

Upvotes: 0

Renis1235
Renis1235

Reputation: 4700

Since you have an infinite recursion problem, it simply means that it is serializing the parent then its child and then the parent of the child and then the child again... Do you see where this is going? :)

You have not posted your entities so I cannot take a relevant example. But I would use @JsonManagedReference -> Parent and @JsonBackReference -> Child.

Try annotating your Relationship Attributes with these two. For the serialization to work, one of the two sides of the relationship should not be serialized, in order to avoid the infinite loop that causes your StackOverflow error.

Upvotes: 2

Related Questions