diff --git a/src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java b/src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java index 758e5dd05..25bbb5604 100644 --- a/src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java +++ b/src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java @@ -28,6 +28,7 @@ import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.data.convert.Jsr310Converters; import org.springframework.data.util.NullableWrapperConverters; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -43,6 +44,7 @@ import org.springframework.util.ConcurrentReferenceHashMap; * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch + * @author Jens Schauder * @see SpelAwareProxyProjectionFactory * @since 1.10 */ @@ -51,6 +53,7 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware final static GenericConversionService CONVERSION_SERVICE = new DefaultConversionService(); static { + Jsr310Converters.getConvertersToRegister().forEach(CONVERSION_SERVICE::addConverter); NullableWrapperConverters.registerConvertersIn(CONVERSION_SERVICE); CONVERSION_SERVICE.removeConvertible(Object.class, Object.class); } diff --git a/src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java b/src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java index c836037ca..bc10a3441 100755 --- a/src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java @@ -19,7 +19,11 @@ import static org.assertj.core.api.Assertions.*; import java.beans.PropertyDescriptor; import java.lang.reflect.Proxy; +import java.time.LocalDateTime; +import java.util.Calendar; import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,6 +41,8 @@ import org.springframework.test.util.ReflectionTestUtils; * @author Oliver Gierke * @author Wim Deblauwe * @author Mark Paluch + * @author Jens Schauder + * @author Christoph Strobl */ class ProxyProjectionFactoryUnitTests { @@ -276,17 +282,47 @@ class ProxyProjectionFactoryUnitTests { }); } + @Test // DATACMNS-1836 + void supportsDateToLocalDateTimeConversion() { + + Customer customer = new Customer(); + customer.firstname = "Dave"; + customer.birthdate = new GregorianCalendar(1967, Calendar.JANUARY, 9).getTime(); + + customer.address = new Address(); + customer.address.city = "New York"; + customer.address.zipCode = "ZIP"; + + CustomerWithLocalDateTime excerpt = factory.createProjection(CustomerWithLocalDateTime.class, customer); + + assertThat(excerpt.getFirstname()).isEqualTo("Dave"); + assertThat(excerpt.getBirthdate()).isEqualTo(LocalDateTime.of(1967, 1, 9, 0, 0)); + } + + @Test // DATACMNS-1836 + void supportsNullableWrapperDateToLocalDateTimeConversion() { + + Customer customer = new Customer(); + customer.firstname = "Dave"; + customer.birthdate = new GregorianCalendar(1967, Calendar.JANUARY, 9).getTime(); + + customer.address = new Address(); + customer.address.city = "New York"; + customer.address.zipCode = "ZIP"; + + CustomerWithOptional excerpt = factory.createProjection(CustomerWithOptional.class, customer); + + assertThat(excerpt.getFirstname()).isEqualTo("Dave"); + assertThat(excerpt.getBirthdate()).contains(LocalDateTime.of(1967, 1, 9, 0, 0)); + } + interface Contact {} - static class Customer implements Contact { + interface CustomerWithLocalDateTime { - Long id; - String firstname, lastname; - Address address; - byte[] picture; - Address[] shippingAddresses; - Map data; - Optional optional; + String getFirstname(); + + LocalDateTime getBirthdate(); } static class Address { @@ -328,6 +364,8 @@ class ProxyProjectionFactoryUnitTests { Optional getPicture(); Optional getOptional(); + + Optional getBirthdate(); } interface CustomerWithOptionalHavingProjection { @@ -336,4 +374,16 @@ class ProxyProjectionFactoryUnitTests { Optional getAddress(); } + + static class Customer implements Contact { + + Long id; + String firstname, lastname; + Date birthdate; + Address address; + byte[] picture; + Address[] shippingAddresses; + Map data; + Optional optional; + } }