消耗Spring Hateoas Pageable [英] Consuming Spring Hateoas Pageable

查看:396
本文介绍了消耗Spring Hateoas Pageable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用HAteoas的Rest-Service,以前没有分页的功能。现在我正在制作可分页的Json。我用Spring-Hateoas的开箱即用功能做到了这一点。但现在我正在坚持使用它,我想它确实没有很好的记录,如果是。

I have a Rest-Service using HAteoas, what worked before without pageing. Now I am producing pageable Json. I did it with out-of-the box features from Spring-Hateoas. But now I am stucking consuming it and I guess it is really not well documented, if it is.

我的JSON如下所示:

My JSON looks like follows:

{
"_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
}
}

====

但现在我的清单是_embedded,所以我怎样才能以最方便的方式消费它。我更喜欢Spring-Hateoas或类似的开箱即用解决方案。

But now my list is "_embedded", so how can I consume it in most convenient way. I would prefer out-of-the-box soltions by Spring-Hateoas or similar.

我之前的代码如下( Json没有包含在_embedded /中vertragResourceList before !!! )。

My code before worked like follows (Json was not wrapped in _embedded/vertragResourceList before!!!).

@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:

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]

=====

编辑:

对应的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我现在更改了:

On Clientside I changed now followed:

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

现在我没有任何例外,但内容为空。正确填充的唯一内容是来自可分页的信息(numberOfReturned Datasets,pageSize等)。 内容为空List !!!
调试时,我在浏览器中尝试给定的URL,然后JSON如上所述。

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). The content is empty List!!! When debugging and I try out the given URL in browser, then JSON looks like above mentioned.

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

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 ....

控制器服务器端:

@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:

public class IdentifierResourceSupport extends ResourceSupport {
    private Long identifier;

    public Long getIdentifier() {
        return identifier;
    }

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

=====

编辑2:

我现在做了什么,我将Spring-Boot从1.2.1切换回1.1.10。现在我在尝试相同时遇到异常,似乎Spring-Boot 1.2.1隐藏了异常:

What I did now, I switched Spring-Boot from 1.2.1 back 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@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"])


推荐答案

好的,

我现在得到了解决方案。

I got the solution now.

首先,Spring Boot 1.2.1中有一个BUG。就像在EDIT2中提到的那样。 Spring-Boot 1.1.10抛出异常,因为它无法映射_embedded中的内容。这就是为什么我的内容保持空白。 Spring Boot 1.2.1只是让它没有任何提示作为例外。降级到1.1.10给了我一些提示。

First of all, there is a BUG in Spring Boot 1.2.1. like mentioned in the question EDIT2. Spring-Boot 1.1.10 throws exception, because it cannot map the content in _embedded. Thats why my content stayed empty. Spring Boot 1.2.1 just leave it emptry without any hint as exception. Downgrading to 1.1.10 gave me the hint.

那么改变的后果是什么:

So what were the consequence to change:

Serverside上的控制器:

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

    // LIKE CODE IN QUESTION ...

    return new HttpEntity<VertragPagedResources>(pagedResources);
}

====

RestTemplate配置:

然后您需要配置Resttemplate以处理HAL格式。

Then you need to configure your 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 stays same as first Edit in Question!

这篇关于消耗Spring Hateoas Pageable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆