I am trying to use domain model classes generated from schema using avro-maven-plugin 1.8.2 with spring-hateoas 1.0.0.RELEASE (via Spring Boot 2.2.0.RC1). The Spring MVC 5.2.0.RELEASE framework throws org.springframework.http.converter.HttpMessageNotWritableException
during serialization of the EntityModel
created by the @RestController
. The EntityModel
is assembled using a SimpleIdentifiableRepresentationModelAssembler sub-class.
Mapping the Avro objects to POJOs before passing them to the representation model assembler works as expected during serialization, but duplicating the domain model won't scale for this application in the long run. I've read about custom media types and I could probably do something like this for, say, application/hal+avro+json
, but that's a deep rabbit hole to go down for a set of objects that, outside of the representation model, are easily serialized to simple JSON. Especially since REST clients don't actually need the Avro schema embedded in these objects... yet. Internal consumers of the Avro do need it though.
FundController.java:
@Autowired
private final FundRepresentationModelAssembler assembler;
...
@GetMapping(value = "/funds/{id}")
public ResponseEntity<EntityModel<Fund>> findOne(@PathVariable final String id) {
return this.repo.findById(id)
.map(this.assembler::toModel)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
FundRepresentationModelAssembler.java:
@Component
public class FundRepresentationModelAssembler extends SimpleIdentifiableRepresentationModelAssembler<Fund> {
public FundRepresentationModelAssembler() {
super(FundController.class);
}
}
Model pom.xml:
<plugins>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
Model schema:
{"namespace": "org.example.model",
"type": "record",
"name": "Fund",
"fields": [
{"name": "id", "type": "string"},
{"name": "description", "type": "string"}
]
}
The nicely formatted error is:
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON:
Not an array: {"type":"record","name":"Fund","namespace":"org.example.model","fields":[{"name":"id","type":"string"},{"name":"description","type":"string"}]}
nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Not an array: {"type":"record","name":"Fund","namespace":"org.example.model","fields":[{"name":"id","type":"string"},{"name":"description","type":"string"}]}
through reference chain: org.springframework.hateoas.EntityModel["content"]
->org.example.model.Fund["schema"]
->org.apache.avro.Schema$RecordSchema["elementType"]
What I'm hoping exists is a way to pass "serialization hints" down through the HATEOAS framework to Jackson.