diff --git a/spring-boot/src/main/java/org/baeldung/config/WebConfig.java b/spring-boot/src/main/java/org/baeldung/config/WebConfig.java new file mode 100644 index 0000000000..4ef407823e --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/config/WebConfig.java @@ -0,0 +1,17 @@ +package org.baeldung.config; + +import org.baeldung.web.resolver.HeaderVersionArgumentResolver; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.List; + +@Configuration +public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addArgumentResolvers(final List argumentResolvers) { + argumentResolvers.add(new HeaderVersionArgumentResolver()); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java index b6f88e7cd5..c8649e0d3e 100644 --- a/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java +++ b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java @@ -1,11 +1,16 @@ package org.baeldung.controller; import org.baeldung.domain.GenericEntity; +import org.baeldung.domain.Modes; +import org.baeldung.web.resolver.Version; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -35,4 +40,21 @@ public class GenericEntityController { public GenericEntity findById(@PathVariable Long id) { return entityList.stream().filter(entity -> entity.getId().equals(id)).findFirst().get(); } + + @RequestMapping("/entity/findbydate/{date}") + public GenericEntity findByDate(@PathVariable("date") LocalDateTime date) { + return entityList.stream().findFirst().get(); + } + + @RequestMapping("/entity/findbymode/{mode}") + public GenericEntity findByEnum(@PathVariable("mode") Modes mode) { + return entityList.stream().findFirst().get(); + } + + @RequestMapping("/entity/findbyversion") + public ResponseEntity findByVersion(@Version String version) { + return version != null + ? new ResponseEntity(entityList.stream().findFirst().get(), HttpStatus.OK) + : new ResponseEntity(HttpStatus.NOT_FOUND); + } } diff --git a/spring-boot/src/main/java/org/baeldung/converter/StringToEnumConverterFactory.java b/spring-boot/src/main/java/org/baeldung/converter/StringToEnumConverterFactory.java new file mode 100644 index 0000000000..17c6fd06de --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/converter/StringToEnumConverterFactory.java @@ -0,0 +1,27 @@ +package org.baeldung.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.ConverterFactory; +import org.springframework.stereotype.Component; + +@Component +public class StringToEnumConverterFactory implements ConverterFactory { + + private static class StringToEnumConverter implements Converter { + + private Class enumType; + + public StringToEnumConverter(Class enumType) { + this.enumType = enumType; + } + + public T convert(String source) { + return (T) Enum.valueOf(this.enumType, source.trim()); + } + } + + @Override + public Converter getConverter(final Class targetType) { + return new StringToEnumConverter(targetType); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/converter/StringToLocalDateTimeConverter.java b/spring-boot/src/main/java/org/baeldung/converter/StringToLocalDateTimeConverter.java new file mode 100644 index 0000000000..85c86faae1 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/converter/StringToLocalDateTimeConverter.java @@ -0,0 +1,21 @@ +package org.baeldung.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +@Component +public class StringToLocalDateTimeConverter implements Converter { + + @Override + public LocalDateTime convert(final String source) { + try { + return LocalDateTime.parse(source, DateTimeFormatter.ISO_LOCAL_DATE_TIME); + } catch (DateTimeParseException e) { + throw new IllegalArgumentException("Couldn't parse value"); + } + } +} diff --git a/spring-boot/src/main/java/org/baeldung/domain/Modes.java b/spring-boot/src/main/java/org/baeldung/domain/Modes.java new file mode 100644 index 0000000000..41b1fa0d4e --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/domain/Modes.java @@ -0,0 +1,6 @@ +package org.baeldung.domain; + +public enum Modes { + + Alpha, Beta; +} diff --git a/spring-boot/src/main/java/org/baeldung/web/resolver/HeaderVersionArgumentResolver.java b/spring-boot/src/main/java/org/baeldung/web/resolver/HeaderVersionArgumentResolver.java new file mode 100644 index 0000000000..89a77f38d1 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/web/resolver/HeaderVersionArgumentResolver.java @@ -0,0 +1,26 @@ +package org.baeldung.web.resolver; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.servlet.http.HttpServletRequest; + +@Component +public class HeaderVersionArgumentResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(final MethodParameter methodParameter) { + return methodParameter.getParameterAnnotation(Version.class) != null; + } + + @Override + public Object resolveArgument(final MethodParameter methodParameter, final ModelAndViewContainer modelAndViewContainer, final NativeWebRequest nativeWebRequest, final WebDataBinderFactory webDataBinderFactory) throws Exception { + HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest(); + + return request.getHeader("Version"); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/web/resolver/Version.java b/spring-boot/src/main/java/org/baeldung/web/resolver/Version.java new file mode 100644 index 0000000000..2a9e6e60b3 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/web/resolver/Version.java @@ -0,0 +1,11 @@ +package org.baeldung.web.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface Version { +} diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java index 3c5444942c..94623d3cdd 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java @@ -1,7 +1,9 @@ package org.baeldung; -import org.baeldung.domain.GenericEntity; -import org.baeldung.repository.GenericEntityRepository; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,11 +20,6 @@ import org.springframework.web.context.WebApplicationContext; import java.nio.charset.Charset; -import static org.hamcrest.Matchers.hasSize; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration @@ -42,4 +39,34 @@ public class SpringBootApplicationIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.get("/entity/all")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(contentType)).andExpect(jsonPath("$", hasSize(4))); } + + @Test + public void givenRequestHasBeenMade_whenMeetsFindByDateOfGivenConditions_thenCorrect() throws Exception { + MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); + + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbydate/{date}", "2011-12-03T10:15:30")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(contentType)) + .andExpect(jsonPath("$.id", equalTo(1))); + } + + @Test + public void givenRequestHasBeenMade_whenMeetsFindByModeOfGivenConditions_thenCorrect() throws Exception { + MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); + + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbymode/{mode}", "Alpha")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(contentType)) + .andExpect(jsonPath("$.id", equalTo(1))); + } + + @Test + public void givenRequestHasBeenMade_whenMeetsFindByVersionOfGivenConditions_thenCorrect() throws Exception { + MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); + + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbyversion").header("Version", "1.0.0")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(contentType)) + .andExpect(jsonPath("$.id", equalTo(1))); + } }