a little deep dive into the functionality of spring-data-rest:
Data-Rest wraps all Entities into PersistentEntityResource
Objects that extend the Resource<T>
interface that spring HATEOAS provides. This particular implementation has a list of embedded objects that will be serialized as the _embedded
field.
So in theory the solution to my problem should be as simple as implementing a ResourceProcessor<Resource<MyType>>
and add my reference object to the embeds.
In practice this aproach has some ugly but solvable issues:
PersistentEntityResource
is not generic, so while you can build a ResourceProcessor for it, that processor will by default catch everything. I am not sure what happens when you start using Projections. So that is not a solution.
PersistentEntityResource
implements Resource<Object>
and as a result can not be cast to Resource<MyType>
and vice versa. If you want to to access the embedded field all casts have to be done with PersistentEntityResource.class.cast()
and Resource.class.cast()
.
Overall my solution is simple, effective and not very pretty. I hope Spring-Hateoas gets full fledged HAL support in the future.
Here my ResourceProcessor as a sample:
@Bean
public ResourceProcessor<Resource<MyType>> typeProcessorToAddReference() {
// DO NOT REPLACE WITH LAMBDA!!!
return new ResourceProcessor<>() {
@Override
public Resource<MyType> process(Resource<MyType> resource) {
try {
// XXX all resources here are PersistentEntityResource instances, but they can't be cast normaly
PersistentEntityResource halResource = PersistentEntityResource.class.cast(resource);
List<EmbeddedWrapper> embedded = Lists.newArrayList(halResource.getEmbeddeds());
ReferenceObject reference = spineClient.findReferenceById(resource.getContent().getReferenceId());
embedded.add(embeddedWrappers.wrap(reference, "reference-relation"));
// XXX all resources here are PersistentEntityResource instances, but they can't be cast normaly
resource = Resource.class.cast(PersistentEntityResource.build(halResource.getContent(), halResource.getPersistentEntity())
.withEmbedded(embedded).withLinks(halResource.getLinks()).build());
} catch (Exception e) {
log.error("Something went wrong", e);
// swallow
}
return resource;
}
};
}