diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 44b3e28291..825af8fb9e 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -69,6 +69,7 @@ spring-boot-vue spring-boot-xml spring-boot-actuator + spring-boot-data-2 diff --git a/spring-boot-modules/spring-boot-data-2/pom.xml b/spring-boot-modules/spring-boot-data-2/pom.xml new file mode 100644 index 0000000000..199a204500 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/pom.xml @@ -0,0 +1,21 @@ + + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + 4.0.0 + + spring-boot-data-2 + + + org.springframework.boot + spring-boot-starter-web + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java new file mode 100644 index 0000000000..6f57a534a8 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.boot.jackson.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackages = "com.baeldung.boot.jackson.controller") +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java new file mode 100644 index 0000000000..d1875d03d9 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java @@ -0,0 +1,13 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class CoffeeConstants { + + public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm"; + public static final LocalDateTime FIXED_DATE = LocalDateTime.now(); + public static LocalDateTimeSerializer LOCAL_DATETIME_SERIALIZER = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)); +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java new file mode 100644 index 0000000000..edb2b478fc --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java @@ -0,0 +1,18 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeCustomizerConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL) + .serializers(LOCAL_DATETIME_SERIALIZER); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java new file mode 100644 index 0000000000..eff2b5c252 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeHttpConverterConfiguration { + + @Bean + public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { + Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() + .serializers(LOCAL_DATETIME_SERIALIZER) + .serializationInclusion(JsonInclude.Include.NON_NULL); + return new MappingJackson2HttpMessageConverter(builder.build()); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java new file mode 100644 index 0000000000..8057fff3db --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeJacksonBuilderConfig { + + @Bean + @Primary + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return new Jackson2ObjectMapperBuilder() + .serializers(LOCAL_DATETIME_SERIALIZER) + .serializationInclusion(JsonInclude.Include.NON_NULL); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java new file mode 100644 index 0000000000..f1ce6458ae --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeObjectMapperConfig { + + @Bean + @Primary + public ObjectMapper objectMapper() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(LOCAL_DATETIME_SERIALIZER); + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL) + .registerModule(module); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java new file mode 100644 index 0000000000..fc157f8156 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +@PropertySource("classpath:coffee.properties") +public class CoffeeRegisterModuleConfig { + + @Bean + public Module javaTimeModule() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(LOCAL_DATETIME_SERIALIZER); + return module; + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java new file mode 100644 index 0000000000..23749b18a2 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.controller; + +import com.baeldung.boot.jackson.model.Coffee; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE; + +@RestController +public class CoffeeController { + + @GetMapping("/coffee") + public Coffee getCoffee( + @RequestParam(required = false) String brand, + @RequestParam(required = false) String name) { + return new Coffee().setBrand(brand) + .setDate(FIXED_DATE) + .setName(name); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java new file mode 100644 index 0000000000..4df6b4bd6d --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java @@ -0,0 +1,39 @@ +package com.baeldung.boot.jackson.model; + +import java.time.LocalDateTime; + +public class Coffee { + + private String name; + + private String brand; + + private LocalDateTime date; + + public String getName() { + return name; + } + + public Coffee setName(String name) { + this.name = name; + return this; + } + + public String getBrand() { + return brand; + } + + public Coffee setBrand(String brand) { + this.brand = brand; + return this; + } + + public LocalDateTime getDate() { + return date; + } + + public Coffee setDate(LocalDateTime date) { + this.date = date; + return this; + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties b/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties new file mode 100644 index 0000000000..269845cbf1 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties @@ -0,0 +1 @@ +spring.jackson.default-property-inclusion=non_null \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java new file mode 100644 index 0000000000..f1bc35a8ce --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java @@ -0,0 +1,33 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeConstants; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; + +import java.time.format.DateTimeFormatter; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE; +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class AbstractCoffeeIntegrationTest { + + @Autowired + protected TestRestTemplate restTemplate; + + @Test + public void whenGetCoffee_thenSerializedWithDateAndNonNull() { + String formattedDate = DateTimeFormatter.ofPattern(CoffeeConstants.DATETIME_FORMAT) + .format(FIXED_DATE); + + String brand = "Lavazza"; + String url = "/coffee?brand=" + brand; + + String response = restTemplate.getForObject(url, String.class); + + assertThat(response).isEqualTo( + "{\"brand\":\"" + brand + "\",\"date\":\"" + formattedDate + "\"}"); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java new file mode 100644 index 0000000000..d690de1b9c --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeCustomizerConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeCustomizerConfig.class) +public class CoffeeCustomizerIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java new file mode 100644 index 0000000000..62b1d42152 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeHttpConverterConfiguration; +import org.springframework.context.annotation.Import; + +@Import(CoffeeHttpConverterConfiguration.class) +public class CoffeeHttpConverterIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java new file mode 100644 index 0000000000..52a55394c0 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeJacksonBuilderConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeJacksonBuilderConfig.class) +public class CoffeeJacksonBuilderIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java new file mode 100644 index 0000000000..34743ceba5 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeObjectMapperConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeObjectMapperConfig.class) +public class CoffeeObjectMapperIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java new file mode 100644 index 0000000000..69bbd5be2a --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeRegisterModuleConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeRegisterModuleConfig.class) +public class CoffeeRegisterModuleIntegrationTest extends AbstractCoffeeIntegrationTest { +}