1
votes

We are trying to create a Java client for an API created with Spring Data.

Some endpoints return hal+json responses containing _embedded and _links attributes.

Our main problem at the moment is trying to wrap our heads around the following structure:

{
    "_embedded": {
        "plans": [
            {
               ...
            }
        ]
    },
   ...
}

When you hit the plans endpoint you get a paginated response the content of which is within the _embedded object. So the logic is that you call plans and you get back a response containing an _embedded object that contains a plans attribute that holds an array of plan objects.

The content of the _embedded object can vary as well, and trying a solution using generics, like the example following, ended up returning us a List of LinkedHashMap Objects instead of the expected type.

class PaginatedResponse<T> {
    @JsonProperty("_embedded")
    Embedded<T> embedded;

    ....
}

class Embedded<T> {
    @JsonAlias({"plans", "projects"})
    List<T> content; // This instead of type T ends up deserialising as a List of LinkedHashMap objects

    ....
}

I am not sure if the above issue is relevant to this Jackson bug report dating from 2015.

The only solution we have so far is to either create a paginated response for each type of content, with explicitly defined types, or to include a List<type_here> for each type of object we expect to receive and make sure that we only read from the populated list and not the null ones.

So our main question to this quite spread out issue is, how one is supposed to navigate such an API without the use of Spring?

We do not consider using Spring in any form as an acceptable solution. At the same time, and I may be quite wrong here, but it looks like in the java world Spring is the only framework actively supporting/promoting HAL/HATEOAS?

I'm sorry if there are wrongly expressed concepts, assumptions and terminology in this question but we are trying to wrap our heads around the philosophy of such an implementation and how to deal with it from a Java point of view.

1

1 Answers

0
votes

You can try consuming HATEOS API using super type tokens. A kind of generic way to handle all kind of hateos response.

For example

Below generic class to handle response

public class Resource<T>  {
 
 protected Resource() {
  this.content = null;
 }
 
 public Resource(T content, Link... links) {
  this(content, Arrays.asList(links));
 }
}

Below code to read the response for various objects

ObjectMapper objectMapper = new ObjectMapper();
Resource<ObjectA> objectA = objectMapper.readValue(response, new TypeReference<Resource<ObjectA>>() {});

Resource<ObjectB> objectB = objectMapper.readValue(response, new TypeReference<Resource<ObjectB>>() {});

You can refer below

http://www.java-allandsundry.com/2012/12/json-deserialization-with-jackson-and.html

http://www.java-allandsundry.com/2014/01/consuming-spring-hateoas-rest-service.html