Spring Hateoas Pageable Consumption

I have a Rest-Service using HAteoas, which used to work without browsing. Now I am releasing page Json. I did this using ready-made functions from Spring -Hateoas. But now I am delaying it, and I think it is really poorly documented, if that is the case.

My JSON looks like this:

{ "_embedded": { "vertragResourceList": [ { "identifier": 728, "auszubildender": "Rumm", "beruf": "Landwirt/in", "betrieb": "Mitterbauer Johann", "betriebsNummer": "e12d0949-67ae-4134-9dc2-fb67758b6b16", "zustaendigeStelle": "Irgendwo", "beginn": 529887600000, "status": "RECENT", "fachrichtung": null, "schwerpunkt": "Grünland oder Ackergras", "ende": 623113200000, "_links": { "self": { "href": "http://localhost:8080/bbsng-app-rest/vertrag/728" } } }, { "identifier": 803, "auszubildender": "Gossen", "beruf": "Landwirt/in", "betrieb": "Beer Johann", "betriebsNummer": "d5a20cb9-7273-4b75-85bd-f8e7d6a843c4", "zustaendigeStelle": "Woanders", "beginn": 278118000000, "status": "RECENT", "fachrichtung": null, "schwerpunkt": "Ackerfutterbau", "ende": 339116400000, "_links": { "self": { "href": "http://localhost:8080/bbsng-app-rest/vertrag/803" } } } ] }, "page": { "size": 2, "totalElements": 1000, "totalPages": 500, "number": 5 } } 

====

But now my list is "_embedded", since I can use it in the most convenient way. I would prefer a Spring -Hateoas box exception or similar.

My code before working as it should ( Json was not wrapped in _embedded / vertragResourceList until !!! ).

 @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public VertragsListe findeAlleVertraege(final Integer firstDataSet, final Integer lastDataSet, final VertragDTFilter vertragsFilter, final VertragDTSorting vertragSorting) { final VertragsListe vertragsListe = new VertragsListe(); final String url = LinkUtils.findeVertrag(firstDataSet, lastDataSet, vertragsFilter, vertragSorting); final ResponseEntity<List> entity = template.getForEntity(url, List.class); if (OK.equals(entity.getStatusCode())) { final List<LinkedHashMap> body = entity.getBody(); for (final LinkedHashMap map : body) { vertragsListe.add(getPopulatedVertrag(vertragsListe, map)); } } return vertragsListe; } 

Stacktrace:

 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@e89d 61c; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@e89d 61c; line: 1, column: 1] 

=====

EDIT:

The corresponding Resourceclass looks like this (Serverside and Clientside !!!):

 public class VertragPagedResources extends PagedResources<VertragResource> { @SuppressWarnings("unchecked") public VertragPagedResources(final Collection<VertragResource> content, final PageMetadata metadata) { super(content, metadata, CollectionUtils.EMPTY_COLLECTION); } public VertragPagedResources() { super(); } } 

On Clientside, I have now changed the following:

 @Autowired private RestTemplate template; @Override public VertragPagedResources findeAlleVertraege(final Integer firstDataSet, final Integer lastDataSet, final VertragDTFilter vertragsFilter, final VertragDTSorting vertragSorting) { final String url = LinkUtils.findeVertrag(firstDataSet, lastDataSet, vertragsFilter, vertragSorting); final ResponseEntity<VertragPagedResources> entity = template.getForEntity(url, VertragPagedResources.class); if (OK.equals(entity.getStatusCode())) { return entity.getBody(); } return new VertragPagedResources(); } 

Now I am not getting any exceptions, but the content is empty. The only thing that is correctly filled out is the information from the page (numberOfReturned Datasets, pageSize, etc.). Content is empty List !!! When debugging, and I try the given URL in the browser, then the JSON looks higher.

 <200 OK,PagedResource { content: [], metadata: Metadata { number: 1, total pages: 100, total elements: 1000, size: 10 }, links: [] },{Server=[Apache-Coyote/1.1], X-Application-Context=[application:custom:8080], totalNumber=[1000], Content-Type=[application/json;charset=UTF-8], Transfer-Encoding=[chunked], Date=[Wed, 28 Jan 2015 16:58:16 GMT]}> 

VertragResource (client and server):

 public class VertragResource extends IdentifierResourceSupport { @NotNull private String auszubildender; @NotNull private String beruf; @NotNull private String betrieb; @NotNull private String betriebsNummer; @NotNull private String zustaendigeStelle; @NotNull private Calendar beginn; @NotNull private String status; private String fachrichtung; private String schwerpunkt; private Calendar ende; // GETTER & SETTER .... 

Controller Server Panel:

 @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE) public HttpEntity<VertragPagedResources> showAll( /* PARAMS */ ) { // FILTER ... final VertragFilter filter = new VertragFilter(); // FILL FILTER // SORTING ... final VertragSorting sorting = new VertragSorting(/* BLA */) // COMPUTE ... final VertragResourceAssembler assembler = new VertragResourceAssembler(); final List<Vertrag> alleVertrage = service.findeAlleVertraege(/* BLA */); final List<VertragResource> resources = assembler.toResources(alleVertrage); // final long totalElements = service.zaehleAlleVertraege(filter); final long size = Math.min(displayLength, totalElements); final long totalPages = totalElements / size; final PageMetadata pageMetadata = new PageMetadata(displayLength, displayStart, totalElements, totalPages); final VertragPagedResources pagedResources = new VertragPagedResources(resources, pageMetadata); return new HttpEntity<VertragPagedResources>(pagedResources, headerTotalNumberOfData()); } 

====

ResourceSupport ID:

 public class IdentifierResourceSupport extends ResourceSupport { private Long identifier; public Long getIdentifier() { return identifier; } public void setIdentifier(Long identifier) { this.identifier = identifier; } } 

=====

EDIT 2:

What I did now, I switched Spring-Boot from 1.2.1 to 1.1.10. Now I get an exception when trying the same, it seems that Spring -Boot 1.2.1 hides the exception:

 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "_embedded" (class at.compax.bbsng.client.mvc.client.resource.VertragPagedResources), not marked as ignorable (3 known properties: "links", "content", "page"]) at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@6253 2c56; line: 1, column: 15] (through reference chain: at.compax.bbsng.client.mvc.client.resource.VertragPagedResources["_embedded"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_embedded" (class at.compax.bbsng.client.mvc.client.resource.VertragPagedResources), not marked as ignorable (3 known properties: "links", "content", "page"]) at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@6253 2c56; line: 1, column: 15] (through reference chain: at.compax.bbsng.client.mvc.client.resource.VertragPagedResources["_embedded"]) 
+6
source share
1 answer

Good,

Now I got a solution.

First of all, there is a bug in Spring Boot 1.2.1. as mentioned in EDIT2 question. Spring-Boot 1.1.10 throws an exception because it cannot display content in _embedded. This is why my content is left blank. Spring Download 1.2.1, just leave this emptry without any hint as an exception. Going to 1.1.10 gave me a hint.

So what were the implications for the change:

Controller on Serverside:

 @RequestMapping(method = GET, produces = "application/hal+json") public HttpEntity<VertragPagedResources> showAll( /* PARAMS */ ) { // LIKE CODE IN QUESTION ... return new HttpEntity<VertragPagedResources>(pagedResources); } 

====

RestTemplate Config:

Then you need to configure Resttemplate to handle HAL-Format.

 @Bean public RestTemplate restTemplate() { final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Jackson2HalModule()); final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); converter.setObjectMapper(mapper); return new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter)); } 

The client code remains the same as in the first question, “Edit in question!”

+6
source

Source: https://habr.com/ru/post/981466/


All Articles