Java Client for POSTing complex entities to a Spring Data REST / HATEOAS service
Asked Answered
A

1

8

From what I can tell, there are provided means for converting a complex object to proper HAL format. This is of course leveraged in marshalling the objects in the framework itself. Resource and Link objects, etc.

For the sake of a use-case: Company 1 is an existing Company in my system. I want to add a new Employee that works for Company 1

Below is an example Employee object that you'd receive from a Spring Data REST based service. Spring HATEOAS also provides the means to construct these objects yourself.

{
    "id": null,
    "firstName": "bZWthNFk",
    "lastName": "GtTnrqka",
    "loginId": "zTk5rT",
    "active": true,
    "_links": {
        "company": {
            "href": "http://localhost/companies/1";
        }
    }
}

However, this seems to not work for POSTing the object. As I understand it, that same object would have to be POSTed as:

{
    "id": null,
    "firstName": "bZWthNFk",
    "lastName": "GtTnrqka",
    "loginId": "zTk5rT",
    "active": true,
    "company": "http://localhost/companies/1"
}

As far as I can tell, there are no means provided by either the HATEOAS or Data REST project to produce this object for posting to a valid HAL based service, either via RestTemplate or some other means. In fact, I can't find any means of readily POSTing a complex object without some hand-marshalling. Am I wrong in assuming this?

How is one supposed to build out a valid Java SDK for service-to-service communication that leverages HATEOAS principles without this tooling to actually POST objects reliably?


Long story short, I want to post this object without having to hand serialize the URIs for associations.

public class Employee {
    private Integer id;
    @NotNull
    private Company company;
    private String firstName;
    private String lastName;
}

I've created the following improvement request in reference to this:

https://jira.spring.io/browse/SPR-12678

Adne answered 27/1, 2015 at 22:26 Comment(0)
Z
2

The approach you suggested should actually work, provided you use at least version 2.0 of Spring Data REST.

You should also have an association resource like http://app.com/employee/10/company. You can PUT a new link to that location using the media type text/uri-list or remove the company from Employee with a DELETE.

UDATE

It seems I didn't address your main concern, that was clarified by your update and comments. So let's take your Employee class that has an association with a Customer.

As you can see from the JSON response you posted, the data structure that the REST API works with doesn't contain a Customer object (or Company in that case), only a link. A client would usually work with the data structure defined by the API. So customerwould be link in the first place and there would be no need for serializing an object to a link.

If the client uses a different data structure internally, then some kind of conversion is necessary anyway. But the reason would be the different structure, not HAL or association links.

Zinazinah answered 28/1, 2015 at 10:39 Comment(9)
That makes total sense :-) My follow up is to ask how would you handle this situation given a NotNull constraint on Company?Adne
@BrandonV It seems that you actually should be able to post an object like you suggested, provided you have at least version 2.0 of Spring Data REST.Zinazinah
Yeah, I know that much works, actually, although your suggestion on the association resource was also cool. My concern is related to the tooling that Spring HATEOAS provides for interacting with HAL based services in this way. Doing this by hand, or writing my own one off marshaler to handle a common case seems a bit unintuitive.Adne
So you mean you have an Employee instance and want to send it via RestTemplate e.g., but you would have the Company field serialized automatically? That implies you have two Java applications using exactly the same data structures. Is that correct?Zinazinah
The specific case here is using MockMvc to post (same application), but we can assume your example as well for the time being.Adne
Even if it is not the exact same object, you would ideally want a Java client to be able to post a complex object with relations. Doing any of it by hand seems...Adne
For what it's worth, I've added another small code snippet.Adne
The MockMvc example makes sense and I guess it's annoying. But here's the catch: A client would work with the data structure of the REST API and the REST employee doesn't contain a full fledged company object. When the client wants to establish an association with a company it would do so by using solely a company's link. There's no need for a client to have a company object or even to know a company's data structure. Now where this link comes from is another story. So basically a client would never be in the situation to serialize an object as a link. Does that make sense?Zinazinah
That does make sense, and I realize what is implied, it is just annoying :) What I'm asking is if Spring HATEOAS provides a more intuitive way to actually do as you say. If there is no other comment about actually doing this in the next day or so, I can mark this as the answer.Adne

© 2022 - 2024 — McMap. All rights reserved.