Search code examples
javaspring-bootjacksonspring-hateoashateoas

Spring Hateoas error from EntityModel : Content is not a Map


I am upgrading spring-hateoas from 0.20.0.RELEASE to 1.3.7

I replaced ResourceSupport with RepresentationModel and Resource with RepresentationModel.

While deserialising the JSON of the DTO I am getting an exception, which is working fine in the old version.

DTO with old Hateoas version

public class Employee extends ResourceSupport implements Serializable {
    @JsonProperty("id")
    private Long id;
    @JsonProperty("name")
    private String name;
}
public class EmployeeResource extends Resource<Employee> {
    EmployeeResource(){
        super(new Employee());
    }
}

DTO with new Hateoas version

public class Employee extends RepresentationModel<Employee> implements Serializable {
    @JsonProperty("id")
    private Long id;
    @JsonProperty("name")
    private String name;
}
public class EmployeeResource extends EntityModel<Employee> {
    EmployeeResource(){
        super(new Employee());
    }
}

JSON file to be deserialised employee.json

{
  "employees": [
    {
      "id": 1,
      "name": "Test",
      "links": [
        {
          "rel": "self",
          "href": "api/employees/1"
        }
      ]
    }
  ]
}

Test case of deserialisation

@Test
public void test() throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    InputStream inputStream = EmpTest.class.getClassLoader().getResourceAsStream("employee.json");
    JsonNode node = mapper.readTree(IOUtils.toByteArray(inputStream));
    TypeFactory typeFactory = mapper.getTypeFactory();
    CollectionType listType = typeFactory.constructCollectionType(ArrayList.class, EmployeeResource.class);
    List resultList = mapper.convertValue(node.findValue("employees"), listType);
    System.out.println(resultList);
}

Exception

java.lang.IllegalArgumentException: Content is not a Map! (through reference chain: java.util.ArrayList[0]->com.test.EmployeeResource["id"])
    at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3589)
    at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3530)
    at com.test.EmpTest.test(EmpTest.java:60)
Caused by: java.lang.IllegalStateException: Content is not a Map!
    at org.springframework.util.Assert.state(Assert.java:70)
    at org.springframework.hateoas.EntityModel.getOrInitAsMap(EntityModel.java:158)
    at org.springframework.hateoas.EntityModel.setPropertiesAsMap(EntityModel.java:149)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.fasterxml.jackson.databind.introspect.AnnotatedMethod.callOnWith(AnnotatedMethod.java:130)
    at com.fasterxml.jackson.databind.deser.SettableAnyProperty.set(SettableAnyProperty.java:172)
    ... 33 more

Solution

  • Removing new Employee() from super() constructor of EntityModel resolved the issue, but not sure the reason.

    public class EmployeeResource extends Resource<Employee> {
        EmployeeResource(){
            super();
        }
    }