Skip to content

Commit dc09d5d

Browse files
schauderchristophstrobl
authored andcommitted
Add JSR310 converters to the converters used for projections.
Similar converters where removed because they clashed with the support for nullable wrappers. This adds them back as dedicated converters that does not clash with conversions for nullable wrappers. See bd3992d#diff-96f7084777a2a702d85f5c600e542b10123d6c3332ed3d3f8e329ca7061faab0R55 Original Pull Request: #479 Closes: #2223
1 parent efe93e3 commit dc09d5d

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.beans.factory.BeanClassLoaderAware;
2929
import org.springframework.core.convert.support.DefaultConversionService;
3030
import org.springframework.core.convert.support.GenericConversionService;
31+
import org.springframework.data.convert.Jsr310Converters;
3132
import org.springframework.data.util.NullableWrapperConverters;
3233
import org.springframework.lang.Nullable;
3334
import org.springframework.util.Assert;
@@ -43,6 +44,7 @@
4344
* @author Oliver Gierke
4445
* @author Christoph Strobl
4546
* @author Mark Paluch
47+
* @author Jens Schauder
4648
* @see SpelAwareProxyProjectionFactory
4749
* @since 1.10
4850
*/
@@ -51,6 +53,7 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware
5153
final static GenericConversionService CONVERSION_SERVICE = new DefaultConversionService();
5254

5355
static {
56+
Jsr310Converters.getConvertersToRegister().forEach(CONVERSION_SERVICE::addConverter);
5457
NullableWrapperConverters.registerConvertersIn(CONVERSION_SERVICE);
5558
CONVERSION_SERVICE.removeConvertible(Object.class, Object.class);
5659
}

src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java

+58-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919

2020
import java.beans.PropertyDescriptor;
2121
import java.lang.reflect.Proxy;
22+
import java.time.LocalDateTime;
23+
import java.util.Calendar;
2224
import java.util.Collections;
25+
import java.util.Date;
26+
import java.util.GregorianCalendar;
2327
import java.util.HashMap;
2428
import java.util.List;
2529
import java.util.Map;
@@ -37,6 +41,8 @@
3741
* @author Oliver Gierke
3842
* @author Wim Deblauwe
3943
* @author Mark Paluch
44+
* @author Jens Schauder
45+
* @author Christoph Strobl
4046
*/
4147
class ProxyProjectionFactoryUnitTests {
4248

@@ -276,17 +282,47 @@ void supportsOptionalWithProjectionAsReturnTypeIfPresent() {
276282
});
277283
}
278284

285+
@Test // DATACMNS-1836
286+
void supportsDateToLocalDateTimeConversion() {
287+
288+
Customer customer = new Customer();
289+
customer.firstname = "Dave";
290+
customer.birthdate = new GregorianCalendar(1967, Calendar.JANUARY, 9).getTime();
291+
292+
customer.address = new Address();
293+
customer.address.city = "New York";
294+
customer.address.zipCode = "ZIP";
295+
296+
CustomerWithLocalDateTime excerpt = factory.createProjection(CustomerWithLocalDateTime.class, customer);
297+
298+
assertThat(excerpt.getFirstname()).isEqualTo("Dave");
299+
assertThat(excerpt.getBirthdate()).isEqualTo(LocalDateTime.of(1967, 1, 9, 0, 0));
300+
}
301+
302+
@Test // DATACMNS-1836
303+
void supportsNullableWrapperDateToLocalDateTimeConversion() {
304+
305+
Customer customer = new Customer();
306+
customer.firstname = "Dave";
307+
customer.birthdate = new GregorianCalendar(1967, Calendar.JANUARY, 9).getTime();
308+
309+
customer.address = new Address();
310+
customer.address.city = "New York";
311+
customer.address.zipCode = "ZIP";
312+
313+
CustomerWithOptional excerpt = factory.createProjection(CustomerWithOptional.class, customer);
314+
315+
assertThat(excerpt.getFirstname()).isEqualTo("Dave");
316+
assertThat(excerpt.getBirthdate()).contains(LocalDateTime.of(1967, 1, 9, 0, 0));
317+
}
318+
279319
interface Contact {}
280320

281-
static class Customer implements Contact {
321+
interface CustomerWithLocalDateTime {
282322

283-
Long id;
284-
String firstname, lastname;
285-
Address address;
286-
byte[] picture;
287-
Address[] shippingAddresses;
288-
Map<String, Object> data;
289-
Optional<String> optional;
323+
String getFirstname();
324+
325+
LocalDateTime getBirthdate();
290326
}
291327

292328
static class Address {
@@ -328,6 +364,8 @@ interface CustomerWithOptional {
328364
Optional<byte[]> getPicture();
329365

330366
Optional<String> getOptional();
367+
368+
Optional<LocalDateTime> getBirthdate();
331369
}
332370

333371
interface CustomerWithOptionalHavingProjection {
@@ -336,4 +374,16 @@ interface CustomerWithOptionalHavingProjection {
336374

337375
Optional<AddressExcerpt> getAddress();
338376
}
377+
378+
static class Customer implements Contact {
379+
380+
Long id;
381+
String firstname, lastname;
382+
Date birthdate;
383+
Address address;
384+
byte[] picture;
385+
Address[] shippingAddresses;
386+
Map<String, Object> data;
387+
Optional<String> optional;
388+
}
339389
}

0 commit comments

Comments
 (0)