4

I use spring-boot 2.

I my Junit test (@SpringBootTest), i use a org.springframework.test.web.servlet.MockMvc

@Test
@WithMockUser(roles = {"ADMIN"})
public void testGetSearchByFoodIdWithAdmin() throws Exception {
    final ResultActions resultActions = mockMvc.perform(get(RESOURCE_URL + "/search/findByFooId?fooId=123"))
                .andExpect(status().isOk());
}

I have this Converter:

public class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {
    @Override
    public Date convert(final ZonedDateTime source) {
        return source == null ? null : Date.from(source.toInstant());
    }
}

I have this other Converter:

public class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {
    @Override
    public ZonedDateTime convert(final Date source) {
        return source == null ? null : ofInstant(source.toInstant(), systemDefault());
    }
}

I have this Spring configuration:

@Configuration
@EnableMongoAuditing(dateTimeProviderRef = "dateTimeProvider")
public class MongoConfiguration {

    @Autowired
    MongoDbFactory mongoDbFactory;

    @Bean
    public MongoCustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new DateToZonedDateTimeConverter());
        converters.add(new ZonedDateTimeToDateConverter());
        return new MongoCustomConversions(converters);
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        MappingMongoConverter converter = getDefaultMongoConverter();
        //converter.afterPropertiesSet();
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
        return mongoTemplate;
    }

    @Bean
    public MappingMongoConverter getDefaultMongoConverter() throws Exception {
        MappingMongoConverter converter = new MappingMongoConverter(
                new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext());
        converter.setCustomConversions(customConversions());
        return converter;
    }

}

I have this other Spring configuration:

@Component
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new DateToZonedDateTimeConverter());
        registry.addConverter(new ZonedDateTimeToDateConverter());
    }

}

I have this error:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.ZonedDateTime] to type [java.util.Date]

Why my converter is not taken into account for the WebMvc part while for MongoDB it's good?

EDIT:

I use Spring Data Rest

@RepositoryRestResource(collectionResourceRel = "foo", path = "foo")
public interface FooRepository extends MongoRepository<Foo, String> {

    Foo findByFooId(@Param("fooId") String fooId);

}

My Fooclass:

@Document
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class Foo {

    @Id
    private String keyid;

    @NotNull
    private String fooId;

    @CreatedDate
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private ZonedDateTime creationDate;

    @LastModifiedDate
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private ZonedDateTime updateDate;
}

EDIT n°2:

I try it with CustomizedRestMvcConfiguration implements RepositoryRestConfigurer` but not sole my problem:

@Configuration
@EnableWebMvc
public class CustomizedRestMvcConfiguration implements RepositoryRestConfigurer {

    @Bean
    public DateToZonedDateTimeConverter dateToZonedDateTimeConverter() {
        return new DateToZonedDateTimeConverter();
    }

    @Bean
    public ZonedDateTimeToDateConverter zonedDateTimeToDateConverter() {
        return new ZonedDateTimeToDateConverter();
    }

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) {
        conversionService.addConverter(dateToZonedDateTimeConverter());
        conversionService.addConverter(zonedDateTimeToDateConverter());
    }

}
Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
  • 1
    Why `MyWebMvcConfigurer` is annotated with `@Component` and not `@Configuration`? – Boris Oct 19 '18 at 15:36
  • I change `@Component` by `@Configuration` but result not change. – Stéphane GRILLON Oct 19 '18 at 15:45
  • When I create `@RepositoryRestController` with `@GetMapping(value = "/search/findByFooId")` ... I overide WebMVC part, I do not have the problem. Then I concluded that the converter is not taken into account in the web part but well taken into account in the MongoDB part. – Stéphane GRILLON Oct 19 '18 at 15:52
  • Do you have [@EnableWebMvc](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html) anywhere? – Boris Oct 19 '18 at 15:54
  • On my `MyWebMvcConfigurer` only – Stéphane GRILLON Oct 19 '18 at 16:03
  • 1
    What happens if you remove it? If you want to keep Spring Boot MVC features and you want to add additional config, for example, the converters you should not use `@EnableWebMvc` according to this [doc](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration). Can you try it? – Boris Oct 19 '18 at 16:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182156/discussion-between-boris-and-sgrillon). – Boris Oct 19 '18 at 16:53
  • Why don't you make the fields creationDate and updateDate to java.util.Date in your model class. This way you won't have to make a conversion. – yerqueri Oct 22 '18 at 09:25
  • It is not my model, i use this from external model (I do not modify this part of the code) – Stéphane GRILLON Oct 22 '18 at 09:37

2 Answers2

1

MyWebMvcConfigurer extends WebMvcConfigurerAdapter which as of Spring 5.0 has been deprecated. Instead you should implement WebMvcConfigurer interface:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // ...
    }
}

See Type Conversion documentation for more info. Also note the different annotations!

Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
Boris
  • 22,667
  • 16
  • 50
  • 71
0

Yes, sgrillon answer is not working because the problem is not in the Spring conversion it is in the Jackson JSON converter of the MongoDB.

@Document annotation + ZonedDateTime is the problem. The solution is as sgrillion suggested: A "converter" but not a Spring Converter / HandlerMapping. You need to add it to the MongoTemplate.

Check here for reference. There are many out - just google for: MongoDB ZonedDateTime.

ZonedDateTime with MongoDB

Kai
  • 31
  • 3