简体   繁体   English

消耗Spring Hateoas Pageable

[英]Consuming Spring Hateoas Pageable

I have a Rest-Service using HAteoas, what worked before without pageing. 我有一个使用HAteoas的Rest-Service,以前没有分页的工作。 Now I am producing pageable Json. 现在我正在制作可分页的Json。 I did it with out-of-the box features from Spring-Hateoas. 我用Spring-Hateoas的开箱即用功能做到了这一点。 But now I am stucking consuming it and I guess it is really not well documented, if it is. 但现在我正在坚持消费它,我想它确实没有很好的记录,如果是的话。

My JSON looks like follows: 我的JSON如下所示:

{
"_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", so how can I consume it in most convenient way. 但现在我的列表是“_embedded”,所以我怎样才能以最方便的方式使用它。 I would prefer out-of-the-box soltions by Spring-Hateoas or similar. 我更喜欢Spring-Hateoas或类似的开箱即用的解决方案。

My code before worked like follows ( Json was not wrapped in _embedded/vertragResourceList before!!! ). 之前的代码如下所示( Json在!!!之前没有包含在_embedded / vertragResourceList中 )。

@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@e89d61c; 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@e89d61c; line: 1, column: 1]

===== =====

EDIT: 编辑:

Corresponding Resourceclass looks like this (Serverside and Clientside!!!): 对应的Resourceclass看起来像这样(Serverside和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 changed now followed: 在Clientside我现在改变了:

@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 don't get any exceptions, but content is empty. 现在我没有任何例外,但内容是空的。 The only thing what is filled correctly are the information from pageable (numberOfReturned Datasets, pageSize and so on). 正确填充的唯一内容是来自可分页的信息(numberOfReturned Datasets,pageSize等)。 The content is empty List!!! 内容为空列表!!! When debugging and I try out the given URL in browser, then JSON looks like above mentioned. 在调试时,我在浏览器中尝试了给定的URL,然后JSON看起来像上面提到的那样。

<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 & Server): VertragResource(客户端和服务器):

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-Side: 控制器服务器端:

@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());
}

==== ====

IdentifierResourceSupport : IdentifierResourceSupport:

public class IdentifierResourceSupport extends ResourceSupport {
    private Long identifier;

    public Long getIdentifier() {
        return identifier;
    }

    public void setIdentifier(Long identifier) {
       this.identifier = identifier;
    }
}

===== =====

EDIT 2: 编辑2:

What I did now, I switched Spring-Boot from 1.2.1 back to 1.1.10. 我现在做了什么,我将Spring-Boot从1.2.1切换回1.1.10。 Now I get an exception when trying the same, it seems that Spring-Boot 1.2.1 hides the exception: 现在我在尝试相同时遇到异常,似乎Spring-Boot 1.2.1隐藏了异常:

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@62532c56; 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@62532c56; line: 1, column: 15] (through reference chain: at.compax.bbsng.client.mvc.client.resource.VertragPagedResources["_embedded"])

Okay, 好的,

I got the solution now. 我现在得到了解决方案。

First of all, there is a BUG in Spring Boot 1.2.1. 首先,Spring Boot 1.2.1中有一个BUG。 like mentioned in the question EDIT2. 就像在EDIT2中提到的那样。 Spring-Boot 1.1.10 throws exception, because it cannot map the content in _embedded. Spring-Boot 1.1.10抛出异常,因为它无法映射_embedded中的内容。 Thats why my content stayed empty. 这就是为什么我的内容保持空白。 Spring Boot 1.2.1 just leave it emptry without any hint as exception. Spring Boot 1.2.1只是让它没有任何提示作为例外。 Downgrading to 1.1.10 gave me the hint. 降级到1.1.10给了我一些暗示。

So what were the consequence to change: 那么改变的后果是什么:

Controller on Serverside: Serverside上的控制器:

@RequestMapping(method = GET, produces = "application/hal+json")
public HttpEntity<VertragPagedResources> showAll( /* PARAMS */  ) { 

    // LIKE CODE IN QUESTION ...

    return new HttpEntity<VertragPagedResources>(pagedResources);
}

==== ====

RestTemplate Config: RestTemplate配置:

Then you need to configure your Resttemplate to handle HAL-Format. 然后,您需要配置Resttemplate以处理HAL格式。

@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 stays same as first Edit in Question! 客户端代码与第一个问题编辑保持一致!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM