spring-projects / spring-data-rest

Simplifies building hypermedia-driven REST web services on top of Spring Data repositories
https://spring.io/projects/spring-data-rest
Apache License 2.0
906 stars 558 forks source link

ConverterNotFoundException unable to register converter OffsetDateTime to Date #2327

Open aeiplatform opened 8 months ago

aeiplatform commented 8 months ago

I am not able to register converter for Data REST, according to instructions Custom conversions.

I have tried other methods, but without success.

Entity is created but cannot be displayed via endpoint/{ID}. Nor other ways to access via ID, but displaying all works.

Am I doing something wrong? Or what's the workaround?

demo.zip

aeiplatform commented 8 months ago

When I create my own controller that inserts data into the repository and return the audited result, everything works as it should. Why is it even necessary to convert the date type to java.util.Date? I would expect Jackson serialization to be used here.

mp911de commented 8 months ago

Seems you're referring to

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.OffsetDateTime] to type [java.util.Date]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) ~[spring-core-6.0.13.jar:6.0.13]
    at org.springframework.data.rest.webmvc.HttpHeadersPreparer.lambda$getLastModifiedInMilliseconds$6(HttpHeadersPreparer.java:127) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
    at org.springframework.data.rest.webmvc.HttpHeadersPreparer.getLastModifiedInMilliseconds(HttpHeadersPreparer.java:127) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at org.springframework.data.rest.webmvc.HttpHeadersPreparer.prepareHeaders(HttpHeadersPreparer.java:87) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at org.springframework.data.rest.webmvc.HttpHeadersPreparer.lambda$prepareHeaders$0(HttpHeadersPreparer.java:64) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
    at org.springframework.data.rest.webmvc.HttpHeadersPreparer.prepareHeaders(HttpHeadersPreparer.java:64) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:475) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(RepositoryEntityController.java:254) ~[spring-data-rest-webmvc-4.1.5.jar:4.1.5]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]

HttpHeadersPreparer's ConversionService isn't configurable yet. We allow customization of a default ConversionService via RepositoryRestMvcConfiguration respective RepositoryRestConfigurer.

@odrotbohm any objections to register JSR310 converters in the RepositoryRestMvcConfiguration and pass on the conversion service to HttpHeadersPreparer?

mp911de commented 8 months ago

One more thing:

The configuration code would be required to look like:

@Component
class MyConfigurer implements RepositoryRestConfigurer {

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) {
        conversionService.addConverter(new OffsetDateTimeConverter());
    }
}

static class OffsetDateTimeConverter implements Converter<OffsetDateTime, Date> {
    @Override
    public Date convert(OffsetDateTime source) {
        return Date.from(source.toInstant());
    }
}
aeiplatform commented 8 months ago

I have tried similar if not the same solution, but the result is the same.

So it's not possible yet, am I getting that right?

odrotbohm commented 7 months ago

I think we have to paddle back a bit here. HttpHeadersPreparer already supports JSR-310 types and adds the necessary converters to the conversion service in its constructor. The original issue seems to be the offset-flavored date-time types being used. They're not actually supported by our auditing infrastructure in the first place and should be actively rejected. I wonder why this is not the case.

Inclined to move this to Data Commons for investigation.

aeiplatform commented 7 months ago

Because, I used a custom DateTime provider for auditing.

@EnableJpaAuditing(dateTimeProviderRef = "offsetDateTimeProvider")
...
@Bean("offsetDateTimeProvider")
DateTimeProvider offsetDateTimeProvider() {
    return () -> Optional.of(OffsetDateTime.now());
}