Spring Data REST URI vs. entity ID
Asked Answered
N

2

8

Spring Data REST (and Spring HATEOAS in particular) decouples RESTful IDs (viz., URIs) from entity IDs, and I'm having trouble linking them back up when saving new objects. See the interesting discussion around this decoupling at https://github.com/SpringSource/spring-data-rest/issues/13.

Suppose that a client app wants to create a new Ticket resource with an associated TicketCategory resource. I want to post the Ticket against a remote Spring Data REST endpoint. The Ticket doesn't yet have an ID since it's new. The TicketCategory has an ID, but on the client it's a URI per the discussion above. So when I save the Ticket, Spring Data REST passes the Ticket to Spring Data JPA, which doesn't like it: Spring Data JPA thinks that the TicketCategory—having no entity ID—is transient:

org.hibernate.TransientPropertyValueException:
    Not-null property references a transient value -
    transient instance must be saved before current operation:
    com.springinpractice.ch13.helpdesk.model.Ticket.category ->
    com.springinpractice.ch13.helpdesk.model.TicketCategory

UPDATE: The documentation at

https://github.com/SpringSource/spring-data-rest/wiki/JPA-Repository-REST-Exporter

has a section called "Updating relationships" that describes a scheme using HTTP POST to establish relationships between entities. I don't know if that's the only approach currently available, but it seems that this approach would require leaving the association null on the initial post and then updating it with a subsequent post. In the case above that would be undesirable since the category field is required (@NotNull) for tickets.

Nameplate answered 14/10, 2012 at 6:49 Comment(0)
U
12

Have you looked at https://github.com/SpringSource/spring-data-rest/wiki/Embedded-Entity-references-in-complex-object-graphs?

Simply put, the exporter will de-reference Link objects if it finds them in place of a relationship or managed object (another entity that has an exported Repository).

Assuming your linked property is called "category", then you could create a new Ticket like:

POST /tickets
Content-Type: application/json

{
  "description": "Description of the ticket or issue",
  "category": {
    "rel": "category.Category",
    "href": "http://localhost:8080/categories/1"
  }
}
Ureide answered 23/10, 2012 at 13:30 Comment(0)
S
11

Apprently in the newer versions of Spring Data Rest, this should do it:

POST /tickets
Content-Type: application/json

{
  "description": "Description of the ticket or issue",
  "category": "http://localhost:8080/categories/1"
}

Going by Oliver Drotbohm's comment at Spring Data Rest 2.0.0.RELEASE Breaks Code Working Previously With RC1

Subset answered 14/6, 2014 at 20:44 Comment(2)
Could you please post the code for the two Entity classes for Ticket and Category that you use. How exactly do you annotate the relation between them two? ManyToOne? Or OneToMany? On which side of the relation? with Cascade.All ??? Or not? Do you add a @NotNull annotation (Does not work for me)Chloro
I face deserialize error when do like this. It seems an issue Spring DATA issue 1059Superjacent

© 2022 - 2024 — McMap. All rights reserved.