带有Traverson客户端和java.time.Instant的Spring HATEOAS

时间:2020-03-11 14:03:59

标签: spring-hateoas

当rest-entity的属性类型为“ java.time.Instant”时,在traverson客户端上使用spring hateoas 1.0.3会引起问题。 我得到的错误是

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant`

我发现在traverson的RestTemplate内部使用的HttpMessageConverter仅注册了Jackson2HalModule。

有没有办法我也可以在traverson中注册jackson-modules-java8模块?

或者有什么办法可以在traverson之外的restTemplate中注册Jackson2HalModule?

2 个答案:

答案 0 :(得分:1)

以下内容在我为春季狂风1.1.2。发布中为我工作

private static RestTemplate getRestTemplate() {
    List<HttpMessageConverter<?>> httpMessageConverters = SpringFactoriesLoader.loadFactories(TraversonDefaults.class,
            Traverson.class.getClassLoader()).get(0).getHttpMessageConverters(Collections.singletonList(MediaTypes.HAL_JSON));
    Optional<HttpMessageConverter<?>> first = httpMessageConverters.stream().filter(i -> i instanceof MappingJackson2HttpMessageConverter)
            .findFirst();

    if (first.isPresent()) {
        MappingJackson2HttpMessageConverter httpMessageConverter = (MappingJackson2HttpMessageConverter) first.get();
        httpMessageConverter.getObjectMapper().registerModule(new JavaTimeModule());
    }

    return new RestTemplateBuilder().messageConverters(httpMessageConverters).build();
}

然后使用它:

Traverson traverson = new Traverson(URI.create("http://localhost:8080"), MediaTypes.HAL_JSON);
    traverson.setRestOperations(getRestTemplate());

答案 1 :(得分:0)

经过一番调查,我找到了适合我的解决方案。 背景是traverson客户端使用包含Jackson2HalModule的注册MappingJackson2HttpMessageConverter。 为了解决这个问题,我还必须注册JavaTimeModule。

我做了以下

RestTemplateBuilder genericBuilder = this.restTemplateBuilder
    .setConnectTimeout(Duration.ofMillis(configuration.getSecurityRestConnectTimeout()))
    .setReadTimeout(Duration.ofMillis(configuration.getSecurityRestReceiveTimeout()));

// my normal restTemplate
RestTemplateBuilder restTemplate = genericBuilder
                .defaultMessageConverters()
                .build();

// HAL specific restTemplate                
RestTemplateBuilder restTemplateHal = genericBuilder
                .messageConverters(getHalConverter(Arrays.asList(MediaTypes.HAL_JSON)))
                .build();

HalConverter的生成是这样的(还注册了JavaTimeModule):

   private static HttpMessageConverter<?> getHalConverter(List<MediaType> halFlavours) {

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jackson2HalModule());
        mapper.registerModule(new JavaTimeModule());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        converter.setObjectMapper(mapper);
        converter.setSupportedMediaTypes(halFlavours);

        return converter;
    }

然后,您可以使用Traverson设置刚刚生成的restTemplateHal

    Traverson traverson = new Traverson(uri, MediaTypes.HAL_JSON);
    traverson.setRestOperations(restTemplateHal);
    MyClass myclass = traverson.follow().toObject(MyClass.class);