Reputation: 5812
I used the Spring Initializr (https://start.spring.io/ ) to create an app with only starters "Jersey (JAX-RS)" and "HATEOAS". Then I added @EnableHypermediaSupport(type = HAL), but I just can't get links rendered correctly in HAL format.
The format I aim for:
{
"name": "Hello",
"count": 42,
"_links": {
"self": {
"href": "http://localhost:8080/api/foo"
}
}
}
What I currently get instead:
{
"name": "Hello",
"count": 42,
"links": [
{
"rel": "self",
"href": "http://localhost:8080/api/foo"
}
]
}
Besides the classes generated by the initializr, I added this configuration
@Configuration
@ApplicationPath("api")
@Component
@EnableHypermediaSupport(type = HAL)
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
registerEndpoints();
}
private void registerEndpoints() {
register(FooResource.class);
}
}
this resource (endpoint):
@Component
@Path("foo")
public class FooResource {
@GET
@Produces(MediaTypes.HAL_JSON_VALUE)
public Resource<Foo> getFoo() {
final Resource<Foo> fooTo = new Resource<>(new Foo("Hello", 42));
fooTo.add(JaxRsLinkBuilder.linkTo(FooResource.class).withRel("self"));
return fooTo;
}
}
and a dummy bean:
public class Foo {
private String name;
private int count;
public Foo() {
}
public Foo(String name, int count) {
this.name = name;
this.count = count;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
I also tried adding
@EnableHypermediaSupport(type = HAL)
next to the @SpringBootApplication on the application class.
When I
GET localhost:8080/api/foo
I get a response with correct content type
application/hal+json;charset=UTF-8
but still the wrong format ("link" property as array instaed of "_links" property as object/map).
Upvotes: 3
Views: 1572
Reputation: 209012
Just to add to the answer from @zerflagL, to register the Jackson2HalModule
, you should use a ContextResolver
, as mentioned here. Also on top of this module, you need to configure the HalHandlerInstantiator
with the ObjectMapper
. If you miss the last part, you will get exceptions about Jackson not being able to instantiate the serializers because of no default constructor.
@Provider
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper = new ObjectMapper();
public JacksonContextResolver() {
mapper.registerModule(new Jackson2HalModule());
mapper.setHandlerInstantiator(new HalHandlerInstantiator(
new AnnotationRelProvider(), null, null));
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
Then just register the context resolver with your Jersey ResourceConfig
register(new JacksonContextResolver());
Upvotes: 4
Reputation: 26828
Spring HATEOAS was developed to work with Spring MVC. Everything related to JSON serialization / deseralization is registered for Spring MVC, MappingJackson2HttpMessageConverter
to be precise.
If you want the same for Jersey you would have to set up Jackson so that org.springframework.hateoas.hal.Jackson2HalModule
gets registered.
Upvotes: 3