From: Gustavo Martin Morcuende Date: Wed, 6 Jan 2016 23:16:31 +0000 (+0100) Subject: Spring REST: integration tests: client y server (RestTemplate y Controller) X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=809dd8097a915bea0130d1013f3d90bb34ba7737;p=JavaForFun Spring REST: integration tests: client y server (RestTemplate y Controller) --- diff --git a/SpringJava/REST/pom.xml b/SpringJava/REST/pom.xml deleted file mode 100644 index 73e0eb3..0000000 --- a/SpringJava/REST/pom.xml +++ /dev/null @@ -1,325 +0,0 @@ - - 4.0.0 - de.spring.webservices - web-services-spring-rest - war - 1.0-SNAPSHOT - web-services-spring-rest - http://gumartinm.name - Web Services REST Spring Framework - - Gustavo Martin Morcuende - http://www.gumartinm.name - - - scm:git:http://git.gumartinm.name/JavaForFun - http://git.gumartinm.name/JavaForFun - - - - UTF-8 - UTF-8 - 4.2.4.RELEASE - - - - - release - - release - - - true - - - - documentation - - documentation - - - false - - - - - io.springfox - springfox-swagger2 - 2.3.0 - - - io.springfox - springfox-swagger-ui - 2.3.0 - - - - - - ${basedir}/src/doc/main/resources/ - - **/*.* - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.10 - - - add-source - process-sources - - add-source - - - - src/doc/main/java/ - - - - - - - - - - - - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.3 - - - - org.apache.logging.log4j - log4j-core - 2.3 - - - - org.slf4j - jcl-over-slf4j - 1.7.12 - - - - cglib - cglib - 2.2.2 - - - org.springframework - spring-core - ${spring.version} - - - - commons-logging - commons-logging - - - - - org.springframework - spring-webmvc - ${spring.version} - - - - commons-logging - commons-logging - - - - - - - javax.servlet - javax.servlet-api - 4.0.0-b01 - provided - - - - - com.fasterxml.jackson.core - jackson-databind - 2.6.4 - - - - - javax.validation - validation-api - 1.1.0.Final - - - org.hibernate - hibernate-validator - 5.2.2.Final - - - - - - junit - junit - 4.12 - test - - - org.springframework - spring-test - ${spring.version} - test - - - org.mockito - mockito-core - 2.0.11-beta - test - - - - - org.hamcrest - hamcrest-core - 1.3 - test - - - org.hamcrest - hamcrest-library - 1.3 - test - - - com.jayway.jsonpath - json-path - 2.1.0 - test - - - - - ${project.artifactId} - - - ${basedir}/src/main/webapp - - **/*.* - - - - ${basedir}/src/main/resources/ - - **/*.* - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.8 - 1.8 - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - ${project.description} - ${project.version} - ${project.organization.name} - ${project.description} - ${project.version} - ${project.organization.name} - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.18.1 - - - **/*IntegrationTest.java - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.18.1 - - - - integration-test - verify - - - - - - **/*IntegrationTest.java - - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - - - true - src/main/webapp - - WEB-INF/web.xml - - - - - - - - diff --git a/SpringJava/REST/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java b/SpringJava/REST/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java deleted file mode 100644 index 98821a6..0000000 --- a/SpringJava/REST/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.spring.webservices.rest.doc; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.bind.annotation.RequestMapping; - -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger.web.UiConfiguration; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@Configuration -@EnableSwagger2 -public class Swagger2Configuration { - private static final String DOCKET_ID = "web-services-spring-rest"; - - @Bean - public Docket documentation() { - return new Docket(DocumentationType.SWAGGER_2) - .groupName(DOCKET_ID) - .select() - .apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class)) - .paths(PathSelectors.any()) - .build() - .pathMapping("/") - .useDefaultResponseMessages(false) - .apiInfo(metadata()); - } - - @Bean - UiConfiguration uiConfig() { - return UiConfiguration.DEFAULT; - } - - - private static ApiInfo metadata() { - return new ApiInfoBuilder() - .title("gumartinm REST API") - .description("Gustavo Martin Morcuende") - .version("1.0-SNAPSHOT") - .contact("gumartinm.name") - .build(); - } - -} diff --git a/SpringJava/REST/src/doc/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/src/doc/main/resources/spring-configuration/spring-config.xml deleted file mode 100644 index 68a47a4..0000000 --- a/SpringJava/REST/src/doc/main/resources/spring-configuration/spring-config.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/SpringJava/REST/src/main/java/de/spring/webservices/rest/Car.java b/SpringJava/REST/src/main/java/de/spring/webservices/rest/Car.java deleted file mode 100644 index 4310f9d..0000000 --- a/SpringJava/REST/src/main/java/de/spring/webservices/rest/Car.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.spring.webservices.rest; - -public class Car { - - private final Long id; - private final String content; - - // Required by Jackson :/ - public Car() { - this.id = null; - this.content = null; - } - - public Car(Long id, String content) { - this.id = id; - this.content = content; - } - - public Long getId() { - return id; - } - - public String getContent() { - return content; - } -} diff --git a/SpringJava/REST/src/main/java/de/spring/webservices/rest/CarController.java b/SpringJava/REST/src/main/java/de/spring/webservices/rest/CarController.java deleted file mode 100644 index ceafb42..0000000 --- a/SpringJava/REST/src/main/java/de/spring/webservices/rest/CarController.java +++ /dev/null @@ -1,109 +0,0 @@ -package de.spring.webservices.rest; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -//import io.swagger.annotations.ApiOperation; -//import io.swagger.annotations.ApiResponse; -//import io.swagger.annotations.ApiResponses; - -@RestController -@RequestMapping("/api/cars/") -public class CarController { - private static final Logger LOGGER = LoggerFactory.getLogger(CarController.class); - private static final String TEMPLATE = "Car: %s"; - - private final AtomicLong counter = new AtomicLong(); - -// Do I want to release with Swagger dependencies? -// @ApiOperation(value = "getCars", nickname = "getAllCars", response = Car.class) -// @ApiResponses({ -// @ApiResponse(code = 404, message ="Not found"), -// @ApiResponse(code = 400, message ="Invalid input") -// }) - @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET) - @ResponseStatus(HttpStatus.OK) - public List cars() { - final List cars = new ArrayList<>(); - cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 1))); - cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 2))); - cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 3))); - - return cars; - } - -// Do I want to release with Swagger dependencies? -// @ApiOperation(value = "getCar", nickname = "getsOneCar", response = Car.class) -// @ApiResponses({ -// @ApiResponse(code = 404, message ="Not found"), -// @ApiResponse(code = 400, message ="Invalid input") -// }) - @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET) - @ResponseStatus(HttpStatus.OK) - public Car car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader, - @PathVariable("id") long id, - @RequestParam Map params, - @RequestParam(value = "wheel", required = false) String[] wheelParams) { - - if (specialHeader != null) { - LOGGER.info("SPECIAL HEADER: " + specialHeader); - } - - if (params.get("mirror") != null) { - LOGGER.info("MIRROR: " + params.get("mirror")); - } - - if (params.get("window") != null) { - LOGGER.info("WINDOW: " + params.get("window")); - } - - if (wheelParams != null) { - for(String wheel : wheelParams) { - LOGGER.info(wheel); - } - } - - try { - Thread.sleep(10000); //1000 milliseconds is one second. - } catch(InterruptedException ex) { - Thread.currentThread().interrupt(); - } - - - return new Car(counter.incrementAndGet(), String.format(TEMPLATE, id)); - } - -// Do I want to release with Swagger dependencies? -// @ApiOperation(value = "postCat", nickname = "createsNewCar", response = Car.class) -// @ApiResponses({ -// @ApiResponse(code = 404, message ="Not found"), -// @ApiResponse(code = 400, message ="Invalid input") -// }) - @RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, - produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST) - public ResponseEntity create(@RequestBody Car car) { - long count = counter.incrementAndGet(); - HttpHeaders headers = new HttpHeaders(); - headers.add(HttpHeaders.LOCATION, "/api/cars/" + count); - - return new ResponseEntity<>(new Car(count, String.format(TEMPLATE, count)), headers, HttpStatus.CREATED); - } - -} diff --git a/SpringJava/REST/src/main/resources/log4j2.xml b/SpringJava/REST/src/main/resources/log4j2.xml deleted file mode 100644 index ee36b97..0000000 --- a/SpringJava/REST/src/main/resources/log4j2.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/REST/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/REST/src/main/resources/spring-configuration/mvc/rest/rest-config.xml deleted file mode 100644 index 420f9e5..0000000 --- a/SpringJava/REST/src/main/resources/spring-configuration/mvc/rest/rest-config.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/REST/src/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/src/main/resources/spring-configuration/spring-config.xml deleted file mode 100644 index a34ec76..0000000 --- a/SpringJava/REST/src/main/resources/spring-configuration/spring-config.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/SpringJava/REST/src/main/webapp/WEB-INF/web.xml b/SpringJava/REST/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 26089bd..0000000 --- a/SpringJava/REST/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - Spring REST Services: example - - - - org.springframework.web.context.ContextLoaderListener - - - - - spring.profiles.active - ${environment.profile} - contextConfigLocation - - classpath*:spring-configuration/*.xml - - - - - - spring-rest - org.springframework.web.servlet.DispatcherServlet - 1 - true - - contextConfigLocation - classpath*:spring-configuration/mvc/rest/*.xml - - - - - spring-rest - /spring-rest/* - - - diff --git a/SpringJava/REST/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java b/SpringJava/REST/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java deleted file mode 100644 index 090d2c4..0000000 --- a/SpringJava/REST/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.spring.webservices.rest; - -import static org.hamcrest.Matchers.any; -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "classpath*:spring-configuration/mvc/rest/*.xml"}) -public class CarControllerIntegrationTest { - private CarController controller; - private MockMvc mockMvc; - - @Before - public void setup() { - controller = new CarController(); - mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); - } - - @Test - public void testWhenGetAllCarsThenRetrieveJsonValues() throws Exception { - mockMvc.perform(get("/api/cars/") - .accept(MediaType.APPLICATION_JSON_UTF8)) - - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", any(Integer.class))) - .andExpect(jsonPath("$[0].content", is("Car: 1"))) - .andExpect(jsonPath("$[1].content", is("Car: 2"))) - .andExpect(jsonPath("$[1].id", any(Integer.class))) - .andExpect(jsonPath("$[2].content", is("Car: 3"))) - .andExpect(jsonPath("$[2].id", any(Integer.class))) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); - } - - @Test - public void testWhenGetOneCarThenRetrieveJsonValue() throws Exception { - mockMvc.perform(get("/api/cars/{id}", 1L) - .accept(MediaType.APPLICATION_JSON_UTF8)) - - .andExpect(status().isOk()) - .andExpect(jsonPath("id", any(Integer.class))) - .andExpect(jsonPath("content", is("Car: 1"))) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); - } - - @Test - public void testWhenCreateNewCarThenRetrieveJsonValue() throws Exception { - Car car = new Car(2L, "nothing"); - mockMvc.perform(post("/api/cars/") - .contentType(MediaType.APPLICATION_JSON_UTF8) - .content(asJsonString(car)) - .accept(MediaType.APPLICATION_JSON_UTF8)) - - .andExpect(status().isCreated()) - .andExpect(jsonPath("id", any(Integer.class))) - .andExpect(jsonPath("content", is("Car: 1"))) - .andExpect(header().string(HttpHeaders.LOCATION, "/api/cars/1")) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); - } - - private static String asJsonString(final Object obj) throws JsonProcessingException { - final ObjectMapper mapper = new ObjectMapper(); - return mapper.writeValueAsString(obj); - } -} diff --git a/SpringJava/REST/web-services-spring-rest-client/pom.xml b/SpringJava/REST/web-services-spring-rest-client/pom.xml new file mode 100644 index 0000000..276b3db --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + + web-services-spring-rest + de.spring.webservices + 1.0-SNAPSHOT + + web-services-spring-rest-client + web-services-spring-rest-client + http://gumartinm.name + + + de.spring.webservices + web-services-spring-rest-global + 1.0-SNAPSHOT + + + + org.springframework + spring-core + + + org.springframework + spring-webmvc + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + junit + junit + test + + + org.springframework + spring-test + test + + + org.mockito + mockito-core + test + + + + + + ${basedir}/src/main/resources/ + + **/*.* + + + + + \ No newline at end of file diff --git a/SpringJava/REST/web-services-spring-rest-client/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java b/SpringJava/REST/web-services-spring-rest-client/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java new file mode 100644 index 0000000..6e0de24 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java @@ -0,0 +1,52 @@ +package de.spring.webservices.rest.doc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger.web.UiConfiguration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableWebMvc +@EnableSwagger2 +public class Swagger2Configuration { + private static final String DOCKET_ID = "web-services-spring-rest"; + + @Bean + public Docket documentation() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName(DOCKET_ID) + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class)) + .paths(PathSelectors.any()) + .build() + .pathMapping("/") + .useDefaultResponseMessages(false) + .apiInfo(metadata()) + .enable(true); + } + + @Bean + UiConfiguration uiConfig() { + return UiConfiguration.DEFAULT; + } + + + private static ApiInfo metadata() { + return new ApiInfoBuilder() + .title("gumartinm REST API") + .description("Gustavo Martin Morcuende") + .version("1.0-SNAPSHOT") + .contact("gumartinm.name") + .build(); + } + +} diff --git a/SpringJava/REST/web-services-spring-rest-client/src/doc/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/web-services-spring-rest-client/src/doc/main/resources/spring-configuration/spring-config.xml new file mode 100644 index 0000000..68a47a4 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/doc/main/resources/spring-configuration/spring-config.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/business/BusinessService.java b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/business/BusinessService.java new file mode 100644 index 0000000..9f76052 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/business/BusinessService.java @@ -0,0 +1,49 @@ +package de.spring.webservices.rest.business; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.spring.webservices.domain.Car; +import de.spring.webservices.rest.client.CarClientService; + +@Service("businessService") +public class BusinessService { + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class); + + private final CarClientService carClientService; + + @Autowired + public BusinessService(CarClientService carClientService) { + this.carClientService = carClientService; + } + + + public void doSomethingWithCars() { + List cars = carClientService.doGetCars(); + LOGGER.info("Retrieved cars"); + for (Car car : cars) { + LOGGER.info("car: " + car.getId()); + LOGGER.info(car.getContent()); + } + } + + public void doSomethingWithCar(long id) { + Car car = carClientService.doGetCar(id); + LOGGER.info("Retrieved car"); + LOGGER.info("car: " + car.getId()); + LOGGER.info(car.getContent()); + } + + public void createsNewCar() { + Car newCar = new Car(666L, "just_a_test"); + + Car car = carClientService.doNewCar(newCar); + LOGGER.info("New car"); + LOGGER.info("car: " + car.getId()); + LOGGER.info(car.getContent()); + } +} diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/client/CarClientService.java b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/client/CarClientService.java new file mode 100644 index 0000000..2d2e2da --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/client/CarClientService.java @@ -0,0 +1,55 @@ +package de.spring.webservices.rest.client; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import de.spring.webservices.domain.Car; + +@Service("carClientService") +public class CarClientService { + private static final Logger LOGGER = LoggerFactory.getLogger(CarClientService.class); + + private final String apiCarsUrl; + private final String apiCarUrl; + private final RestTemplate restTemplate; + + @Autowired + public CarClientService(@Value("${url.base}${url.cars}") String apiCarsUrl, + @Value("${url.base}${url.car}") String apiCarUrl, RestTemplate restTemplate) { + this.apiCarsUrl = apiCarsUrl; + this.apiCarUrl = apiCarUrl; + this.restTemplate = restTemplate; + } + + + public List doGetCars() { + ResponseEntity responseEntity = restTemplate.getForEntity(apiCarsUrl, Car[].class); + + return Arrays.asList(responseEntity.getBody()); + } + + public Car doGetCar(long id) { + ResponseEntity responseEntity = restTemplate.getForEntity( + apiCarUrl.replace(":id", String.valueOf(id)), Car.class); + + return responseEntity.getBody(); + } + + + public Car doNewCar(Car car) { + ResponseEntity responseEntity = restTemplate.postForEntity(apiCarsUrl, car, Car.class); + URI newCarLocation = responseEntity.getHeaders().getLocation(); + LOGGER.info("new car location: " + newCarLocation.getPath()); + + return responseEntity.getBody(); + } +} diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/main/MainTest.java b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/main/MainTest.java new file mode 100644 index 0000000..721a58b --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/main/MainTest.java @@ -0,0 +1,35 @@ +package de.spring.webservices.rest.main; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import de.spring.webservices.rest.business.BusinessService; + + +/** + * This class is used just like a nice example about how to write and run client + * code which will send data to and from the Web Services. + * + */ +public class MainTest { + public ApplicationContext context; + + /** + * @param args + */ + public static void main(final String[] args) { + final MainTest test = new MainTest(); + + test.context = new ClassPathXmlApplicationContext( + "classpath:spring-configuration/rest-config.xml"); + + final BusinessService example = + (BusinessService) test.context.getBean("businessService"); + + example.doSomethingWithCars(); + + example.doSomethingWithCar(66L); + + example.createsNewCar(); + } +} diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/resources/log4j2.xml b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/log4j2.xml new file mode 100644 index 0000000..ee36b97 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/log4j2.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/resources/rest.properties b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/rest.properties new file mode 100644 index 0000000..00255b0 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/rest.properties @@ -0,0 +1,4 @@ +url.base = http://localhost:8080/web-services-spring-rest-server/spring-rest/ + +url.cars = api/cars/ +url.car = api/cars/:id \ No newline at end of file diff --git a/SpringJava/REST/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml new file mode 100644 index 0000000..1f4fe9c --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/business/BusinessServiceTest.java b/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/business/BusinessServiceTest.java new file mode 100644 index 0000000..3910f0b --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/business/BusinessServiceTest.java @@ -0,0 +1,54 @@ +package de.spring.webservices.rest.business; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import de.spring.webservices.domain.Car; +import de.spring.webservices.rest.client.CarClientService; + +public class BusinessServiceTest { + + private CarClientService carClientService; + private BusinessService businessService; + + @Before + public void createTest() { + carClientService = mock(CarClientService.class); + businessService = new BusinessService(carClientService); + } + + @Test + public void whenDoSomethingWithCarsThenInvokeDoGetCars() { + Car expectedOne = new Car(66L, "test"); + Car expectedTwo = new Car(99L, "example"); + List expected = new ArrayList<>(); + expected.add(expectedOne); + expected.add(expectedTwo); + when(carClientService.doGetCars()).thenReturn(expected); + + businessService.doSomethingWithCars(); + + verify(carClientService, times(1)).doGetCars(); + } + + + @Test + public void whenDoSomethingWithOneCarhenInvokeDoGetCar() { + Long id = 66L; + Car expected = new Car(66L, "test"); + + when(carClientService.doGetCar(id)).thenReturn(expected); + + businessService.doSomethingWithCar(id); + + verify(carClientService, times(1)).doGetCar(id); + } +} diff --git a/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/client/CarClientServiceIntegrationTest.java b/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/client/CarClientServiceIntegrationTest.java new file mode 100644 index 0000000..65d752a --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/client/CarClientServiceIntegrationTest.java @@ -0,0 +1,115 @@ +package de.spring.webservices.rest.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import de.spring.webservices.domain.Car; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath*:spring-configuration/rest-config.xml") +public class CarClientServiceIntegrationTest { + + @Value("${url.base}${url.cars}") + private String apiCarsUrl; + + @Value("${url.base}${url.car}") + private String apiCarUrl; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private CarClientService carClientService; + + private MockRestServiceServer mockServer; + + @Before + public void createTest() { + mockServer = MockRestServiceServer.createServer(restTemplate); + } + + @Test + public void whenGetAllCarsThenRetrieveRequestedCars() throws JsonProcessingException { + Car expectedOne = new Car(66L, "test"); + Car expectedTwo = new Car(99L, "example"); + List expected = new ArrayList<>(); + expected.add(expectedOne); + expected.add(expectedTwo); + + mockServer.expect(requestTo(apiCarsUrl)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(asJsonString(expected), MediaType.APPLICATION_JSON_UTF8)); + + List cars = carClientService.doGetCars(); + + mockServer.verify(); + + assertEquals(2, cars.size()); + assertEquals(expectedOne, cars.get(0)); + assertEquals(expectedTwo, cars.get(1)); + } + + @Test + public void whenGetCarByIdThenRetrieveRequestedCar() throws JsonProcessingException { + Long id = 66L; + Car expected = new Car(66L, "test"); + + mockServer.expect(requestTo(apiCarUrl.replace(":id", String.valueOf(id)))) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(asJsonString(expected), MediaType.APPLICATION_JSON_UTF8)); + + Car car = carClientService.doGetCar(id); + + mockServer.verify(); + + assertNotNull(car); + assertEquals(expected, car); + } + + @Test + public void whenCreateNewCarThenRetrieveCreatedCar() throws JsonProcessingException { + Long expectedId = 66L; + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.LOCATION, "/api/cars/" + String.valueOf(expectedId)); + Car expected = new Car(expectedId, "test"); + + mockServer.expect(requestTo(apiCarsUrl)) + .andExpect(method(HttpMethod.POST)) + .andRespond(withSuccess(asJsonString(expected), MediaType.APPLICATION_JSON_UTF8) + .headers(headers)); + + Car car = carClientService.doNewCar(expected); + + mockServer.verify(); + + assertNotNull(car); + assertEquals(expected, car); + } + + private static String asJsonString(final Object obj) throws JsonProcessingException { + final ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(obj); + } +} diff --git a/SpringJava/REST/web-services-spring-rest-global/pom.xml b/SpringJava/REST/web-services-spring-rest-global/pom.xml new file mode 100644 index 0000000..c726115 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-global/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + + web-services-spring-rest + de.spring.webservices + 1.0-SNAPSHOT + + web-services-spring-rest-global + web-services-spring-rest-global + http://gumartinm.name + diff --git a/SpringJava/REST/web-services-spring-rest-global/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java b/SpringJava/REST/web-services-spring-rest-global/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java new file mode 100644 index 0000000..6e0de24 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-global/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java @@ -0,0 +1,52 @@ +package de.spring.webservices.rest.doc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger.web.UiConfiguration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableWebMvc +@EnableSwagger2 +public class Swagger2Configuration { + private static final String DOCKET_ID = "web-services-spring-rest"; + + @Bean + public Docket documentation() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName(DOCKET_ID) + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class)) + .paths(PathSelectors.any()) + .build() + .pathMapping("/") + .useDefaultResponseMessages(false) + .apiInfo(metadata()) + .enable(true); + } + + @Bean + UiConfiguration uiConfig() { + return UiConfiguration.DEFAULT; + } + + + private static ApiInfo metadata() { + return new ApiInfoBuilder() + .title("gumartinm REST API") + .description("Gustavo Martin Morcuende") + .version("1.0-SNAPSHOT") + .contact("gumartinm.name") + .build(); + } + +} diff --git a/SpringJava/REST/web-services-spring-rest-global/src/doc/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/web-services-spring-rest-global/src/doc/main/resources/spring-configuration/spring-config.xml new file mode 100644 index 0000000..68a47a4 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-global/src/doc/main/resources/spring-configuration/spring-config.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-global/src/main/java/de/spring/webservices/domain/Car.java b/SpringJava/REST/web-services-spring-rest-global/src/main/java/de/spring/webservices/domain/Car.java new file mode 100644 index 0000000..cdfaa07 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-global/src/main/java/de/spring/webservices/domain/Car.java @@ -0,0 +1,58 @@ +package de.spring.webservices.domain; + +public class Car { + + private final Long id; + private final String content; + + // Required by Jackson :/ + public Car() { + this.id = null; + this.content = null; + } + + public Car(Long id, String content) { + this.id = id; + this.content = content; + } + + + public Long getId() { + return id; + } + + public String getContent() { + return content; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((content == null) ? 0 : content.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Car other = (Car) obj; + if (content == null) { + if (other.content != null) + return false; + } else if (!content.equals(other.content)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } +} diff --git a/SpringJava/REST/web-services-spring-rest-server/pom.xml b/SpringJava/REST/web-services-spring-rest-server/pom.xml new file mode 100644 index 0000000..cff3af6 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/pom.xml @@ -0,0 +1,110 @@ + + 4.0.0 + + web-services-spring-rest + de.spring.webservices + 1.0-SNAPSHOT + + web-services-spring-rest-server + war + web-services-spring-rest-server + http://gumartinm.name + + + de.spring.webservices + web-services-spring-rest-global + 1.0-SNAPSHOT + + + + org.springframework + spring-core + + + org.springframework + spring-webmvc + + + + + javax.servlet + javax.servlet-api + provided + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + + + junit + junit + test + + + org.springframework + spring-test + test + + + org.mockito + mockito-core + test + + + + + org.hamcrest + hamcrest-core + test + + + org.hamcrest + hamcrest-library + test + + + com.jayway.jsonpath + json-path + test + + + + ${project.artifactId} + + + ${basedir}/src/main/webapp + + **/*.* + + + + ${basedir}/src/main/resources/ + + **/*.* + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java b/SpringJava/REST/web-services-spring-rest-server/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java new file mode 100644 index 0000000..6e0de24 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/doc/main/java/de/spring/webservices/rest/doc/Swagger2Configuration.java @@ -0,0 +1,52 @@ +package de.spring.webservices.rest.doc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger.web.UiConfiguration; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableWebMvc +@EnableSwagger2 +public class Swagger2Configuration { + private static final String DOCKET_ID = "web-services-spring-rest"; + + @Bean + public Docket documentation() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName(DOCKET_ID) + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class)) + .paths(PathSelectors.any()) + .build() + .pathMapping("/") + .useDefaultResponseMessages(false) + .apiInfo(metadata()) + .enable(true); + } + + @Bean + UiConfiguration uiConfig() { + return UiConfiguration.DEFAULT; + } + + + private static ApiInfo metadata() { + return new ApiInfoBuilder() + .title("gumartinm REST API") + .description("Gustavo Martin Morcuende") + .version("1.0-SNAPSHOT") + .contact("gumartinm.name") + .build(); + } + +} diff --git a/SpringJava/REST/web-services-spring-rest-server/src/doc/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/web-services-spring-rest-server/src/doc/main/resources/spring-configuration/spring-config.xml new file mode 100644 index 0000000..68a47a4 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/doc/main/resources/spring-configuration/spring-config.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/CarController.java b/SpringJava/REST/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/CarController.java new file mode 100644 index 0000000..b5ae241 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/CarController.java @@ -0,0 +1,111 @@ +package de.spring.webservices.rest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import de.spring.webservices.domain.Car; + +//import io.swagger.annotations.ApiOperation; +//import io.swagger.annotations.ApiResponse; +//import io.swagger.annotations.ApiResponses; + +@RestController +@RequestMapping("/api/cars/") +public class CarController { + private static final Logger LOGGER = LoggerFactory.getLogger(CarController.class); + private static final String TEMPLATE = "Car: %s"; + + private final AtomicLong counter = new AtomicLong(); + +// Do I want to release with Swagger dependencies? +// @ApiOperation(value = "getCars", nickname = "getAllCars", response = Car.class) +// @ApiResponses({ +// @ApiResponse(code = 404, message ="Not found"), +// @ApiResponse(code = 400, message ="Invalid input") +// }) + @RequestMapping(produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }, method = RequestMethod.GET) + @ResponseStatus(HttpStatus.OK) + public List cars() { + final List cars = new ArrayList<>(); + cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 1))); + cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 2))); + cars.add(new Car(counter.incrementAndGet(), String.format(TEMPLATE, 3))); + + return cars; + } + +// Do I want to release with Swagger dependencies? +// @ApiOperation(value = "getCar", nickname = "getsOneCar", response = Car.class) +// @ApiResponses({ +// @ApiResponse(code = 404, message ="Not found"), +// @ApiResponse(code = 400, message ="Invalid input") +// }) + @RequestMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET) + @ResponseStatus(HttpStatus.OK) + public Car car(@RequestHeader(value = "MY_HEADER", required = false) String specialHeader, + @PathVariable("id") long id, + @RequestParam Map params, + @RequestParam(value = "wheel", required = false) String[] wheelParams) { + + if (specialHeader != null) { + LOGGER.info("SPECIAL HEADER: " + specialHeader); + } + + if (params.get("mirror") != null) { + LOGGER.info("MIRROR: " + params.get("mirror")); + } + + if (params.get("window") != null) { + LOGGER.info("WINDOW: " + params.get("window")); + } + + if (wheelParams != null) { + for(String wheel : wheelParams) { + LOGGER.info(wheel); + } + } + + try { + Thread.sleep(10000); //1000 milliseconds is one second. + } catch(InterruptedException ex) { + Thread.currentThread().interrupt(); + } + + + return new Car(counter.incrementAndGet(), String.format(TEMPLATE, id)); + } + +// Do I want to release with Swagger dependencies? +// @ApiOperation(value = "postCat", nickname = "createsNewCar", response = Car.class) +// @ApiResponses({ +// @ApiResponse(code = 404, message ="Not found"), +// @ApiResponse(code = 400, message ="Invalid input") +// }) + @RequestMapping(consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, + produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST) + public ResponseEntity create(@RequestBody Car car) { + long count = counter.incrementAndGet(); + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.LOCATION, "/api/cars/" + count); + + return new ResponseEntity<>(new Car(count, String.format(TEMPLATE, count)), headers, HttpStatus.CREATED); + } + +} diff --git a/SpringJava/REST/web-services-spring-rest-server/src/main/resources/log4j2.xml b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/log4j2.xml new file mode 100644 index 0000000..ee36b97 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/log4j2.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml new file mode 100644 index 0000000..420f9e5 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/mvc/rest/rest-config.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/spring-config.xml b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/spring-config.xml new file mode 100644 index 0000000..ff7aa8e --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/main/resources/spring-configuration/spring-config.xml @@ -0,0 +1,13 @@ + + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/main/webapp/WEB-INF/web.xml b/SpringJava/REST/web-services-spring-rest-server/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..26089bd --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + + Spring REST Services: example + + + + org.springframework.web.context.ContextLoaderListener + + + + + spring.profiles.active + ${environment.profile} + contextConfigLocation + + classpath*:spring-configuration/*.xml + + + + + + spring-rest + org.springframework.web.servlet.DispatcherServlet + 1 + true + + contextConfigLocation + classpath*:spring-configuration/mvc/rest/*.xml + + + + + spring-rest + /spring-rest/* + + + diff --git a/SpringJava/REST/web-services-spring-rest-server/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java b/SpringJava/REST/web-services-spring-rest-server/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java new file mode 100644 index 0000000..c551c85 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest-server/src/test/java/de/spring/webservices/rest/CarControllerIntegrationTest.java @@ -0,0 +1,85 @@ +package de.spring.webservices.rest; + +import static org.hamcrest.Matchers.any; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import de.spring.webservices.domain.Car; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "classpath*:spring-configuration/mvc/rest/*.xml"}) +public class CarControllerIntegrationTest { + private CarController controller; + private MockMvc mockMvc; + + @Before + public void setup() { + controller = new CarController(); + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + } + + @Test + public void testWhenGetAllCarsThenRetrieveJsonValues() throws Exception { + mockMvc.perform(get("/api/cars/") + .accept(MediaType.APPLICATION_JSON_UTF8)) + + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", any(Integer.class))) + .andExpect(jsonPath("$[0].content", is("Car: 1"))) + .andExpect(jsonPath("$[1].content", is("Car: 2"))) + .andExpect(jsonPath("$[1].id", any(Integer.class))) + .andExpect(jsonPath("$[2].content", is("Car: 3"))) + .andExpect(jsonPath("$[2].id", any(Integer.class))) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); + } + + @Test + public void testWhenGetOneCarThenRetrieveJsonValue() throws Exception { + mockMvc.perform(get("/api/cars/{id}", 1L) + .accept(MediaType.APPLICATION_JSON_UTF8)) + + .andExpect(status().isOk()) + .andExpect(jsonPath("id", any(Integer.class))) + .andExpect(jsonPath("content", is("Car: 1"))) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); + } + + @Test + public void testWhenCreateNewCarThenRetrieveJsonValue() throws Exception { + Car car = new Car(2L, "nothing"); + mockMvc.perform(post("/api/cars/") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(asJsonString(car)) + .accept(MediaType.APPLICATION_JSON_UTF8)) + + .andExpect(status().isCreated()) + .andExpect(jsonPath("id", any(Integer.class))) + .andExpect(jsonPath("content", is("Car: 1"))) + .andExpect(header().string(HttpHeaders.LOCATION, "/api/cars/1")) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)); + } + + private static String asJsonString(final Object obj) throws JsonProcessingException { + final ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(obj); + } +} diff --git a/SpringJava/REST/web-services-spring-rest/pom.xml b/SpringJava/REST/web-services-spring-rest/pom.xml new file mode 100644 index 0000000..bbad4e9 --- /dev/null +++ b/SpringJava/REST/web-services-spring-rest/pom.xml @@ -0,0 +1,317 @@ + + 4.0.0 + de.spring.webservices + web-services-spring-rest + pom + 1.0-SNAPSHOT + web-services-spring-rest + http://gumartinm.name + Web Services Spring Framework + + Gustavo Martin Morcuende + http://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/SpringWebServicesForFun + http://git.gumartinm.name/SpringWebServicesForFun + + + UTF-8 + UTF-8 + 4.2.4.RELEASE + + + + release + + release + + + true + + + + documentation + + documentation + + + false + + + + + io.springfox + springfox-swagger2 + 2.3.1 + + + io.springfox + springfox-swagger-ui + 2.3.1 + + + + + + ${basedir}/src/doc/main/resources/ + + **/*.* + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add-source + process-sources + + add-source + + + + src/doc/main/java/ + + + + + + + + + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.3 + + + + + org.apache.logging.log4j + log4j-core + 2.3 + + + + + org.slf4j + jcl-over-slf4j + 1.7.12 + + + + + cglib + cglib + 2.2.2 + + + + + + org.springframework + spring-core + ${spring.version} + + + + commons-logging + commons-logging + + + + + org.springframework + spring-webmvc + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + javax.servlet + javax.servlet-api + 4.0.0-b01 + provided + + + + + com.fasterxml.jackson.core + jackson-databind + 2.6.4 + + + + + javax.validation + validation-api + 1.1.0.Final + + + org.hibernate + hibernate-validator + 5.2.2.Final + + + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + ${spring.version} + test + + + org.mockito + mockito-core + 2.0.11-beta + test + + + + + org.hamcrest + hamcrest-core + 1.3 + test + + + org.hamcrest + hamcrest-library + 1.3 + test + + + com.jayway.jsonpath + json-path + 2.1.0 + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.18.1 + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + + + true + src/main/webapp + + WEB-INF/web.xml + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + ${project.description} + ${project.version} + ${project.organization.name} + ${project.description} + ${project.version} + ${project.organization.name} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + + **/*IntegrationTest.java + + + + + + \ No newline at end of file