Prevent Jackson from setting links field null when the client sends "_links" : null (links inherited from spring-hateoas RepresentationModel class)

Viewed 76

I have Spring Boot API that uses spring-hateoas.

I have a domain class that is used for request and response in my controller. The domain class inherits from spring-hateoas class RepresentationModel, therefore it contains a "links" field.

For some reason (that I cannot control) a client is sending "_links": null in the request which is forcing links field to be null, after it had been properly initialized with an empty List. See RepresentationModel.java

Null links field in the request is causing issues in my application:

Caused by: java.lang.IllegalArgumentException: Links must not be null!
  at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.8.jar:5.3.8]
  at org.springframework.hateoas.Links.<init>(Links.java:54) ~[spring-hateoas-1.2.6.jar:1.2.6]
  at org.springframework.hateoas.Links.of(Links.java.79) ~[spring-hateoas-1.2.6.jar:1.2.6]
  at org.springframework.hateoas.RepresentationModel.getLinks(RepresentationModel.java:210) ~[spring-hateoas-1.2.6.jar:1.2.6]
  at sun.reflect.GeneratedMethodAccesor158.invoke(Unknown Source) ~[na:na]
  at sun.reflect.DelegatingMethodAccesorImpl.invoke(DelegatingMethodAccesorImpl.java:43) ~[na:1.8.0_292]
  at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_292]
  at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:689) ~[jackson-databind-2.11.4.jar:2.11.4]
  at com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter.serializeAsField(SimpleBeanPropertyFilter.java:208) ~[jackson-databind-2.11.4.jar:2.11.4]

One thing I tried was configuring Jackson to ignore links field on marshalling (@JsonIgonoreProperties) but this is also affecting my response by removing HATEOAS links from it (this Jackson configuration is application wide)

Looking at RepresentationModel class from spring-hateoas, seems like links field is designed not to be handled directly. It is updated only through the corresponding methods in RepresentationModel after it was initialized.

I was able to reinitialize links field through reflection.

  try {
    Field field = obj.getClass().getSuperClass().getDeclaredField("links");
    field.setAccessible(true);
    field.set(obj, new ArrayList<>());
    field.setAccessible(false);
  } catch (Exception e) {
    e.printStackTrace(e);
  }

Is there a better way to reinitialize HATEOAS links field in a RepresenationModel object which already has null links?

Is there a better approach to prevent the client request from affecting the incoming object this way?

0 Answers
Related