diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java index 796e3146fc..6115989cb3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java @@ -108,6 +108,7 @@ public class JacksonAutoConfiguration { } + @Deprecated @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ Jackson2ObjectMapperBuilder.class, DateTime.class, DateTimeSerializer.class, JacksonJodaDateFormat.class }) @@ -117,6 +118,8 @@ public class JacksonAutoConfiguration { @Bean SimpleModule jodaDateTimeSerializationModule(JacksonProperties jacksonProperties) { + logger.warn("Auto-configuration of Jackson's Joda-Time integration is deprecated in favor of using " + + "java.time (JSR-310)."); SimpleModule module = new SimpleModule(); JacksonJodaDateFormat jacksonJodaFormat = getJacksonJodaDateFormat(jacksonProperties); if (jacksonJodaFormat != null) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java index 7135fe8034..c19f9c3efb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java @@ -31,6 +31,7 @@ import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; /** * Configuration properties to configure Jackson. @@ -117,6 +118,10 @@ public class JacksonProperties { this.dateFormat = dateFormat; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "dateFormat", + reason = "Auto-configuration for Jackson's Joda-Time integration is " + + "deprecated in favor of its Java 8 Time integration") public String getJodaDateTimeFormat() { return this.jodaDateTimeFormat; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java index 39a82c225b..fa1df0bfc2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/format/WebConversionService.java @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web.format; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.joda.time.format.DateTimeFormatterBuilder; import org.springframework.format.datetime.DateFormatter; @@ -49,9 +51,12 @@ public class WebConversionService extends DefaultFormattingConversionService { private static final boolean JSR_354_PRESENT = ClassUtils.isPresent("javax.money.MonetaryAmount", WebConversionService.class.getClassLoader()); + @Deprecated private static final boolean JODA_TIME_PRESENT = ClassUtils.isPresent("org.joda.time.LocalDate", WebConversionService.class.getClassLoader()); + private static final Log logger = LogFactory.getLog(WebConversionService.class); + private final String dateFormat; /** @@ -93,7 +98,9 @@ public class WebConversionService extends DefaultFormattingConversionService { dateTime.registerFormatters(this); } + @Deprecated private void registerJodaTime() { + logger.warn("Auto-configuration of Joda-Time formatters is deprecated in favor of using java.time (JSR-310)."); JodaTimeFormatterRegistrar jodaTime = new JodaTimeFormatterRegistrar(); if (this.dateFormat != null) { jodaTime.setDateFormatter(new DateTimeFormatterBuilder().appendPattern(this.dateFormat).toFormatter()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java index d4cc600b44..772f36879e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.gson; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -26,7 +28,6 @@ import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.LongSerializationPolicy; -import org.joda.time.DateTime; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -198,9 +199,8 @@ class GsonAutoConfigurationTests { void customDateFormat() { this.contextRunner.withPropertyValues("spring.gson.date-format:H").run((context) -> { Gson gson = context.getBean(Gson.class); - DateTime dateTime = new DateTime(1988, 6, 25, 20, 30); - Date date = dateTime.toDate(); - assertThat(gson.toJson(date)).isEqualTo("\"20\""); + ZonedDateTime dateTime = ZonedDateTime.of(1988, 6, 25, 20, 30, 0, 0, ZoneId.systemDefault()); + assertThat(gson.toJson(Date.from(dateTime.toInstant()))).isEqualTo("\"20\""); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java index 6a76c8bc2a..35cccbcfc5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java @@ -80,6 +80,7 @@ class JacksonAutoConfigurationTests { .withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class)); @Test + @Deprecated void registersJodaModuleAutomatically() { this.contextRunner.run((context) -> { ObjectMapper objectMapper = context.getBean(ObjectMapper.class); @@ -116,6 +117,7 @@ class JacksonAutoConfigurationTests { } @Test + @Deprecated void customJodaDateTimeFormat() throws Exception { this.contextRunner.withPropertyValues("spring.jackson.date-format:yyyyMMddHHmmss", "spring.jackson.joda-date-time-format:yyyy-MM-dd HH:mm:ss").run((context) -> { @@ -336,6 +338,7 @@ class JacksonAutoConfigurationTests { } @Test + @Deprecated void customLocaleWithJodaTime() throws JsonProcessingException { this.contextRunner.withPropertyValues("spring.jackson.locale:de_DE", "spring.jackson.date-format:zzzz", "spring.jackson.serialization.write-dates-with-zone-id:true").run((context) -> { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java index 338a16569f..7b4724122d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/format/WebConversionServiceTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.web.format; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; import org.joda.time.DateTime; @@ -33,14 +35,24 @@ import static org.assertj.core.api.Assertions.assertThat; class WebConversionServiceTests { @Test - void customDateFormat() { + void customDateFormatWithJavaUtilDate() { + customDateFormat(Date.from(ZonedDateTime.of(2018, 1, 1, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant())); + } + + @Test + @Deprecated + void customDateFormatWithJodaTime() { + customDateFormat(LocalDate.fromDateFields(new DateTime(2018, 1, 1, 20, 30).toDate())); + } + + @Test + void customDateFormatWithJavaTime() { + customDateFormat(java.time.LocalDate.of(2018, 1, 1)); + } + + private void customDateFormat(Object input) { WebConversionService conversionService = new WebConversionService("dd*MM*yyyy"); - Date date = new DateTime(2018, 1, 1, 20, 30).toDate(); - assertThat(conversionService.convert(date, String.class)).isEqualTo("01*01*2018"); - LocalDate jodaDate = LocalDate.fromDateFields(date); - assertThat(conversionService.convert(jodaDate, String.class)).isEqualTo("01*01*2018"); - java.time.LocalDate localDate = java.time.LocalDate.of(2018, 1, 1); - assertThat(conversionService.convert(localDate, String.class)).isEqualTo("01*01*2018"); + assertThat(conversionService.convert(input, String.class)).isEqualTo("01*01*2018"); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index fa017ddea8..463fb25de0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.web.reactive; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Collections; import java.util.Date; import java.util.List; @@ -26,7 +28,6 @@ import java.util.concurrent.TimeUnit; import javax.validation.ValidatorFactory; import org.assertj.core.api.Assertions; -import org.joda.time.DateTime; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -187,7 +188,7 @@ class WebFluxAutoConfigurationTests { void noDateFormat() { this.contextRunner.run((context) -> { FormattingConversionService conversionService = context.getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + Date date = Date.from(ZonedDateTime.of(1988, 6, 25, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant()); // formatting conversion service should use simple toString() assertThat(conversionService.convert(date, String.class)).isEqualTo(date.toString()); }); @@ -197,7 +198,7 @@ class WebFluxAutoConfigurationTests { void overrideDateFormat() { this.contextRunner.withPropertyValues("spring.webflux.date-format:dd*MM*yyyy").run((context) -> { FormattingConversionService conversionService = context.getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + Date date = Date.from(ZonedDateTime.of(1988, 6, 25, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant()); assertThat(conversionService.convert(date, String.class)).isEqualTo("25*06*1988"); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java index e3f4d29d21..c1fe7bea2e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.web.servlet; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Collections; import java.util.Date; import java.util.LinkedHashMap; @@ -30,7 +32,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.ValidatorFactory; -import org.joda.time.DateTime; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -321,7 +322,7 @@ class WebMvcAutoConfigurationTests { void noDateFormat() { this.contextRunner.run((context) -> { FormattingConversionService conversionService = context.getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + Date date = Date.from(ZonedDateTime.of(1988, 6, 25, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant()); // formatting conversion service should use simple toString() assertThat(conversionService.convert(date, String.class)).isEqualTo(date.toString()); }); @@ -331,7 +332,7 @@ class WebMvcAutoConfigurationTests { void overrideDateFormat() { this.contextRunner.withPropertyValues("spring.mvc.date-format:dd*MM*yyyy").run((context) -> { FormattingConversionService conversionService = context.getBean(FormattingConversionService.class); - Date date = new DateTime(1988, 6, 25, 20, 30).toDate(); + Date date = Date.from(ZonedDateTime.of(1988, 6, 25, 20, 30, 0, 0, ZoneId.systemDefault()).toInstant()); assertThat(conversionService.convert(date, String.class)).isEqualTo("25*06*1988"); }); }