Closed anadimisra closed 5 years ago
The fact that your JSON is showing links
and not _links
reveals that your configuration is not properly setup.
For starters, if you are using Spring Boot, then there is no need to use @EnableHypermediaSupport
. In fact, by using the annotation directly, it instructs Spring Boot to back off and NOT activate its other hypermedia-supporting configurations. Instead, you have to do it all yourself.
If you remove that annotation from your configuration, what hypermedia do you then see?
Hi! @gregturn
Removing @EnableHypermediaSupport
doesn't result in the removal of null fields from the rendered HAL JSON. Here's the full response for GET
/customers
call
{
"links": [
{
"rel": "self",
"href": "http://localhost:8080/data/api/customers",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
}
],
"content": [
{
"name": "Minty And Sons Pvt. Ltd.",
"pan": "5GB7W15M0T",
"currecny": "INR",
"tds": 0.1,
"invoicePrefix": "INV",
"links": [
{
"rel": "self",
"href": "/customers/1",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "customers",
"href": "/customers",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "contact",
"href": "/customers/1/contact",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "branches",
"href": "/customers/1/branches",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "invoices",
"href": "/customers/1/invoices",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "paid-invoices",
"href": "/customers/1/invoices/paid",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "pending-invoices",
"href": "/customers/1/invoices/pending",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
},
{
"rel": "overdue-invoices",
"href": "/customers/1/invoices/overdue",
"hreflang": null,
"media": null,
"title": null,
"type": null,
"deprecation": null
}
]
}
],
"page": {
"size": 20,
"totalElements": 1,
"totalPages": 1,
"number": 0
}
}
Again not producing HAL.
Which also happens if your controller doesn’t return a ResourceSupport type.
Can you show your controller?
I am returning Resource
wrapped in ResponseEntity
@GetMapping(value = "/customers/{id}", produces = MediaTypes.HAL_JSON_VALUE)
public DeferredResult<ResponseEntity<Resource<Customer>>> getCustomer(@PathVariable Long id,
HttpServletRequest request) {
DeferredResult<ResponseEntity<Resource<Customer>>> response = new DeferredResult<>();
response.onTimeout(() -> response
.setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT).body("Request timed out.")));
response.onError((Throwable t) -> {
response.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occured."));
});
ListenableFuture<Optional<Customer>> future = customerService.findById(id);
future.addCallback(new ListenableFutureCallback<Optional<Customer>>() {
@Override
public void onSuccess(Optional<Customer> customer) {
response.setResult(customer.map(customerResourceAssembler::toResource).map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()));
}
@Override
public void onFailure(Throwable ex) {
LOGGER.error("Cannot get customer details for id {} due to error: {}", id, ex.getMessage(), ex);
response.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Cannot get customer details due to server error."));
}
});
return response;
}
The problem was in my configuration class, I was registering the Hibernate5Module in a wrong way, removed these lines
@Bean
public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new HibernateAwareObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customJackson2HttpMessageConverter());
super.addDefaultHttpMessageConverters(converters);
}
and simply added a bean
@Bean
public Module hibernate5Module() {
return new Hibernate5Module();
}
that fixed the output
{
"_embedded": {
"customers": [
{
"name": "Minty And Sons Pvt. Ltd.",
"pan": "5GB7W15M0T",
"currecny": "INR",
"tds": 0.1,
"invoice_prefix": "INV",
"_links": {
"self": {
"href": "/customers/1"
},
"customers": {
"href": "/customers"
},
"contact": {
"href": "/customers/1/contact"
},
"branches": {
"href": "/customers/1/branches"
},
"invoices": {
"href": "/customers/1/invoices"
},
"paid-invoices": {
"href": "/customers/1/invoices/paid"
},
"pending-invoices": {
"href": "/customers/1/invoices/pending"
},
"overdue-invoices": {
"href": "/customers/1/invoices/overdue"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/data/api/customers"
}
},
"page": {
"size": 20,
"total_elements": 1,
"total_pages": 1,
"number": 0
}
}
I have the problem similar to one asked in this question however, applying the suggested solution
spring.jackson.default-property-inclusion=NON_NULL
does not stop HATEOAS from rendering links with null properties. Here's my controller declarationand the web config class
In the Controller get method that returns a resource I declare mapping as follows
and then I return a Resource
The
CustomerResourceAssembler
extendsSimpleIdentifiableResourceAssembler
as demonstrated in the spring-hateaos example.But in the response body I still see links rendered with null properties
this doesn't look like how a HATEOAS response should be, like in examples I see
links
not_links
in the JSON