Spring Boot REST Client
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 5 Feb 2017 19:39:52 +0000 (20:39 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 5 Feb 2017 20:12:57 +0000 (21:12 +0100)
31 files changed:
REST/SpringBoot/pom.xml
REST/SpringBoot/web-services-spring-rest-client/README [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-client/pom.xml
REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/main/MainTest.java [deleted file]
REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/Application.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/business/service/impl/BusinessServiceImpl.java
REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/client/service/impl/CarClientServiceImpl.java
REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-client/src/main/resources/application.yml [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-client/src/main/resources/banner.txt [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-client/src/main/resources/rest.properties [deleted file]
REST/SpringBoot/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml [deleted file]
REST/SpringBoot/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/business/service/BusinessServiceTest.java
REST/SpringBoot/web-services-spring-rest-client/src/test/java/de/spring/webservices/rest/client/service/CarClientServiceIntegrationTest.java
REST/SpringBoot/web-services-spring-rest-client/src/test/resources/application.yml [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/README [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/logback-access.xml [deleted file]
REST/SpringBoot/web-services-spring-rest-server/logback.xml [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/Application.java [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/JacksonConfiguration.java [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/Swagger2Configuration.java [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/ValidatorConfiguration.java [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/WadlConfiguration.java [deleted file]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/Application.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/Swagger2Configuration.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/ValidatorConfiguration.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/WadlConfiguration.java [new file with mode: 0644]
REST/SpringBoot/web-services-spring-rest-server/src/main/resources/application.yml
REST/SpringBoot/web-services-spring-rest-server/src/main/resources/banner.txt
REST/SpringBoot/web-services-spring-rest-server/src/test/java/de/spring/webservices/rest/controller/CarControllerIntegrationTest.java

index 9b7f623..935ba9c 100644 (file)
@@ -21,6 +21,7 @@
         <module>web-services-spring-rest-bom</module>
         <module>web-services-spring-rest-global</module>
         <module>web-services-spring-rest-server</module>
+        <module>web-services-spring-rest-client</module>
     </modules>
 
 </project>
diff --git a/REST/SpringBoot/web-services-spring-rest-client/README b/REST/SpringBoot/web-services-spring-rest-client/README
new file mode 100644 (file)
index 0000000..4f45bc6
--- /dev/null
@@ -0,0 +1 @@
+java -jar target/web-services-spring-rest-client-1.0-SNAPSHOT.jar
index 276b3db..09ab649 100644 (file)
@@ -2,7 +2,7 @@
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
-               <artifactId>web-services-spring-rest</artifactId>
+               <artifactId>web-services-spring-rest-bom</artifactId>
                <groupId>de.spring.webservices</groupId>
                <version>1.0-SNAPSHOT</version>
        </parent>
                        <artifactId>web-services-spring-rest-global</artifactId>
                        <version>1.0-SNAPSHOT</version>
                </dependency>
-       
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-core</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-webmvc</artifactId>
-               </dependency>
-               
-               <!-- Jackson JSON Processor, required by spring-webmvc. See messageConverters in rest-config.xml -->
-               <dependency>
-                       <groupId>com.fasterxml.jackson.core</groupId>
-                       <artifactId>jackson-databind</artifactId>
-               </dependency>
-               
-               <!-- Unitary and integration tests -->
-               <dependency>
-                       <groupId>junit</groupId>
-                       <artifactId>junit</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.springframework</groupId>
-                       <artifactId>spring-test</artifactId>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-core</artifactId>
-                       <scope>test</scope>
-               </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!--
+             Jackson dependency required for serializing and deserializing LocalDateTime,
+             LocalDate, etc, etc objects.
+        -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+        </dependency>
+
+        <!-- Unitary and integration tests -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
        </dependencies>
-       <build>
-               <resources>
-                       <resource>
-                               <directory>${basedir}/src/main/resources/</directory>
-                               <includes>
-                                       <include>**/*.*</include>
-                               </includes>
-                       </resource>
-               </resources>
-       </build>
-</project>
\ No newline at end of file
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+             </plugin>
+        </plugins>
+    </build>
+
+
+</project>
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/main/MainTest.java b/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/main/MainTest.java
deleted file mode 100644 (file)
index 0f066ad..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.spring.webservices.main;
-
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-import de.spring.webservices.rest.business.service.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/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/Application.java b/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/Application.java
new file mode 100644 (file)
index 0000000..a3cc0fc
--- /dev/null
@@ -0,0 +1,29 @@
+package de.spring.webservices.rest;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import de.spring.webservices.rest.business.service.BusinessService;
+
+@SpringBootApplication
+public class Application {
+
+  public static void main(String[] args) {
+    SpringApplication.run(Application.class);
+  }
+
+
+  @Bean
+  CommandLineRunner lookup(BusinessService businessService) {
+    return args -> {
+       businessService.doSomethingWithCars();
+        
+       businessService.doSomethingWithCar(66L);
+        
+       businessService.createsNewCar();
+    };
+  }
+
+}
index b6367e8..ebce1b3 100644 (file)
@@ -2,22 +2,23 @@ package de.spring.webservices.rest.business.service.impl;
 
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 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.business.service.BusinessService;
 import de.spring.webservices.rest.client.service.CarClientService;
 
-@Service("businessService")
+@Named("businessService")
 public class BusinessServiceImpl implements BusinessService {
        private static final Logger LOGGER = LoggerFactory.getLogger(BusinessServiceImpl.class);
 
        private final CarClientService carClientService;
 
-       @Autowired
+    @Inject
        public BusinessServiceImpl(CarClientService carClientService) {
                this.carClientService = carClientService;
        }
index bdb540b..d5638fd 100644 (file)
@@ -4,18 +4,20 @@ import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 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.boot.web.client.RestTemplateBuilder;
 import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
 import de.spring.webservices.domain.Car;
 import de.spring.webservices.rest.client.service.CarClientService;
 
-@Service("carClientService")
+@Named("carClientService")
 public class CarClientServiceImpl implements CarClientService {
        private static final Logger LOGGER = LoggerFactory.getLogger(CarClientServiceImpl.class);
 
@@ -23,12 +25,12 @@ public class CarClientServiceImpl implements CarClientService {
        private final String apiCarUrl;
        private final RestTemplate restTemplate;
        
-    @Autowired
-       public CarClientServiceImpl(@Value("${url.base}${url.cars}") String apiCarsUrl,
-                       @Value("${url.base}${url.car}") String apiCarUrl, RestTemplate restTemplate) {
+    @Inject
+       public CarClientServiceImpl(@Value("${app.url.base}${app.url.cars}") String apiCarsUrl,
+                       @Value("${app.url.base}${app.url.car}") String apiCarUrl, RestTemplateBuilder restTemplateBuilder) {
                this.apiCarsUrl = apiCarsUrl;
                this.apiCarUrl = apiCarUrl;
-               this.restTemplate = restTemplate;
+               this.restTemplate = restTemplateBuilder.build();
        }
 
        
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java b/REST/SpringBoot/web-services-spring-rest-client/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java
new file mode 100644 (file)
index 0000000..4d0062b
--- /dev/null
@@ -0,0 +1,26 @@
+package de.spring.webservices.rest.configuration;
+
+import javax.inject.Inject;
+
+import org.springframework.context.annotation.Configuration;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+@Configuration
+public class JacksonConfiguration {
+
+  @Inject
+  public void configureJackson(ObjectMapper jackson2ObjectMapper) {
+         jackson2ObjectMapper
+               .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+        .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
+        .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
+        .enable(SerializationFeature.INDENT_OUTPUT)
+        .registerModule(new JavaTimeModule());
+  }
+  
+}
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/application.yml b/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/application.yml
new file mode 100644 (file)
index 0000000..1b87497
--- /dev/null
@@ -0,0 +1,28 @@
+# Spring Boot configuration properties
+spring:
+  application:
+    name: web-services-spring-rest-client
+  main:
+    banner-mode: "LOG"
+    # We do not need Tomcat running (this application runs from console)
+    web-environment: false
+  
+# By default Spring Boot uses logback.
+# logging:
+#   level:
+#     org:
+#       springframework: info
+#     ROOT: info
+   
+# Using log4j2 (just for fun) It requires exclusions in spring-boot-starter because by default
+# Spring Boot will pick up the logback dependency :/
+logging:
+  config: classpath:log4j2.xml
+  
+
+# Application properties
+app:
+  url:
+    base: http://localhost:8080/
+    cars: api/cars/
+    car: api/cars/:id
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/banner.txt b/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/banner.txt
new file mode 100644 (file)
index 0000000..85a9cc9
--- /dev/null
@@ -0,0 +1,10 @@
+
+   _____            _              __          __  _        _____                 _               
+  / ____|          (_)             \ \        / / | |      / ____|               (_)              
+ | (___  _ __  _ __ _ _ __   __ _   \ \  /\  / /__| |__   | (___   ___ _ ____   ___  ___ ___  ___ 
+  \___ \| '_ \| '__| | '_ \ / _` |   \ \/  \/ / _ \ '_ \   \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __|
+  ____) | |_) | |  | | | | | (_| |    \  /\  /  __/ |_) |  ____) |  __/ |   \ V /| | (_|  __/\__ \
+ |_____/| .__/|_|  |_|_| |_|\__, |     \/  \/ \___|_.__/  |_____/ \___|_|    \_/ |_|\___\___||___/
+        | |                  __/ |                                                                
+        |_|                 |___/                       
+                ${application.title}                 ${application.formatted-version}                                          
\ No newline at end of file
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/rest.properties b/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/rest.properties
deleted file mode 100644 (file)
index 00255b0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-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/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml b/REST/SpringBoot/web-services-spring-rest-client/src/main/resources/spring-configuration/rest-config.xml
deleted file mode 100644 (file)
index 5f4e873..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:context="http://www.springframework.org/schema/context"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xmlns:p="http://www.springframework.org/schema/p"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-        http://www.springframework.org/schema/beans/spring-beans.xsd
-        http://www.springframework.org/schema/context
-        http://www.springframework.org/schema/context/spring-context.xsd
-        http://www.springframework.org/schema/util
-        http://www.springframework.org/schema/util/spring-util.xsd">
-       
-          
-       <context:annotation-config />
-   
-       <context:component-scan base-package="de.spring.webservices.rest"/>
-       
-       <context:property-placeholder location="classpath:rest.properties" />
-       
-       <bean id="jsonObjectMapperFactory" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" p:indentOutput="true" p:failOnEmptyBeans="false">
-        <property name="featuresToDisable">
-            <array>
-                <util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES"/>
-                <util:constant static-field="com.fasterxml.jackson.databind.MapperFeature.DEFAULT_VIEW_INCLUSION"/>
-            </array>
-        </property>
-    </bean>
-
-    <util:list id="messageConverters">
-        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" p:objectMapper-ref="jsonObjectMapperFactory"/>
-        <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
-    </util:list>
-    
-       <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
-                   <constructor-arg ref="messageConverters" />
-       </bean>
-       
-</beans>
index 53665c4..6ec050b 100644 (file)
@@ -1,9 +1,9 @@
 package de.spring.webservices.rest.business.service;
 
+import static org.mockito.BDDMockito.given;
 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;
@@ -34,7 +34,7 @@ public class BusinessServiceTest {
                List<Car> expected = new ArrayList<>();
                expected.add(expectedOne);
                expected.add(expectedTwo);
-               when(carClientService.doGetCars()).thenReturn(expected);
+               given(carClientService.doGetCars()).willReturn(expected);
                
                businessService.doSomethingWithCars();
                
@@ -46,7 +46,7 @@ public class BusinessServiceTest {
                Long id = 66L;
                Car expected = new Car(66L, "test");
                
-               when(carClientService.doGetCar(id)).thenReturn(expected);
+               given(carClientService.doGetCar(id)).willReturn(expected);
                
                businessService.doSomethingWithCar(id);
                
@@ -58,7 +58,7 @@ public class BusinessServiceTest {
                Car expected = new Car(66L, "test");
                ArgumentCaptor<Car> argCar = ArgumentCaptor.forClass(Car.class);
                
-               when(carClientService.doNewCar(argCar.capture())).thenReturn(expected);
+               given(carClientService.doNewCar(argCar.capture())).willReturn(expected);
                
                businessService.createsNewCar();
                
index b5696be..0e671ee 100644 (file)
@@ -10,50 +10,54 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
 import java.util.ArrayList;
 import java.util.List;
 
-import org.junit.Before;
+import javax.inject.Inject;
+
 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.boot.test.autoconfigure.web.client.RestClientTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.PropertySource;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
-import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit4.SpringRunner;
 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;
+import de.spring.webservices.rest.business.service.BusinessService;
 
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration("classpath*:spring-configuration/rest-config.xml")
+/** WHEN USING @RunWith SPRING SEARCHES FOR YOUR main Aplication AND RUNS IT!!!!! **/
+@RunWith(SpringRunner.class)
+@RestClientTest({ CarClientService.class })
+@PropertySource("classpath:application.yml")
 public class CarClientServiceIntegrationTest {
        
-       @Value("${url.base}${url.cars}")
+       @Value("${app.url.base}${app.url.cars}")
        private String apiCarsUrl;
        
-       @Value("${url.base}${url.car}")
+       @Value("${app.url.base}${app.url.car}")
        private String apiCarUrl;
-       
-    @Autowired
-    private RestTemplate restTemplate;
     
-    @Autowired
+               
+       // WARNING!!!! @RunWith runs searches for the main Application in class path and runs it!!!
+       // Because in my main Application I am injecting the BusinessSerivce I have to mock it in order to make
+       // this test work even when BusinessService is not related to CarclientService :O
+       @MockBean
+       private BusinessService businessService;
+       
+    @Inject
        private CarClientService carClientService;
     
-    @Autowired
-    private Jackson2ObjectMapperFactoryBean jsonObjectMapperFactory;
+    @Inject
+    private ObjectMapper jsonObjectMapperFactory;
 
+    @Inject
     private MockRestServiceServer mockServer;
 
-    @Before
-    public void createTest() {
-        mockServer = MockRestServiceServer.createServer(restTemplate);
-    }
-
        @Test
        public void whenGetAllCarsThenRetrieveRequestedCars() throws JsonProcessingException {
                Car expectedOne = new Car(66L, "test");
@@ -66,7 +70,7 @@ public class CarClientServiceIntegrationTest {
 
                List<Car> cars = carClientService.doGetCars();
 
-               mockServer.verify();
+               //mockServer.verify();
                
                assertEquals(1, cars.size());
                assertEquals(expectedOne, cars.get(0));
@@ -83,7 +87,7 @@ public class CarClientServiceIntegrationTest {
 
                Car car = carClientService.doGetCar(id);
 
-               mockServer.verify();
+               //mockServer.verify();
                
                assertNotNull(car);
                assertEquals(expected, car);
@@ -105,13 +109,13 @@ public class CarClientServiceIntegrationTest {
 
                Car car = carClientService.doNewCar(expected);
 
-               mockServer.verify();
+               //mockServer.verify();
                
                assertNotNull(car);
                assertEquals(expected, car);
        }
        
        private String asJsonString(final Object obj) throws JsonProcessingException {
-               return jsonObjectMapperFactory.getObject().writeValueAsString(obj);
+               return jsonObjectMapperFactory.writeValueAsString(obj);
        }
 }
diff --git a/REST/SpringBoot/web-services-spring-rest-client/src/test/resources/application.yml b/REST/SpringBoot/web-services-spring-rest-client/src/test/resources/application.yml
new file mode 100644 (file)
index 0000000..aff991b
--- /dev/null
@@ -0,0 +1,6 @@
+# Application properties
+app:
+  url:
+    base: http://localhost:8080/
+    cars: api/cars/
+    car: api/cars/:id
\ No newline at end of file
diff --git a/REST/SpringBoot/web-services-spring-rest-server/README b/REST/SpringBoot/web-services-spring-rest-server/README
new file mode 100644 (file)
index 0000000..f364778
--- /dev/null
@@ -0,0 +1 @@
+java -jar target/web-services-spring-rest-server-1.0-SNAPSHOT.jar
diff --git a/REST/SpringBoot/web-services-spring-rest-server/logback-access.xml b/REST/SpringBoot/web-services-spring-rest-server/logback-access.xml
deleted file mode 100644 (file)
index fe219ad..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<configuration>
-    <appender name="CONSOLE_ACCESS" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder>
-            <pattern>%h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}" %D "%header{X-Parent-Id}" "%header{X-Trace-Id}"</pattern>
-            <charset>utf8</charset>
-        </encoder>
-        <withJansi>true</withJansi>
-    </appender>
-
-    <appender-ref ref="CONSOLE_ACCESS" />
-</configuration>
diff --git a/REST/SpringBoot/web-services-spring-rest-server/logback.xml b/REST/SpringBoot/web-services-spring-rest-server/logback.xml
deleted file mode 100644 (file)
index a7c8649..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<configuration scan="true">
-    <property name="FILE_LOG_PATTERN" value="%date{ISO8601,GMT} %level ${PID:- } [%t] %logger : %replace(%msg \{%mdc\} %throwable){'\n','\\\\n'}%n%nopex"/>
-
-    <!--
-        To have color support in IntelliJ, please install 'Grep Console' plugin and set Enable ANSI coloring
-    -->
-    <property name="CONSOLE_LOG_PATTERN" value="%date{ISO8601,GMT} %highlight(${LOG_LEVEL_PATTERN:-%5p}) %magenta(${PID:- }) [%15.15t] %cyan(%-40.40logger{39}) : %m \{%mdc\}%n"/>
-
-
-
-    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder>
-            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
-            <charset>utf8</charset>
-        </encoder>
-        <withJansi>true</withJansi>
-    </appender>
-
-    
-    
-    <!-- Here you should define your loggers -->
-
-    <Logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
-        <appender-ref ref="CONSOLE" />
-    </Logger>
-
-    <!--
-        Logging Hibernate QUERY PARAMETERS requires TRACE level.
-     -->
-    <Logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" additivity="false">
-        <appender-ref ref="CONSOLE" />
-    </Logger>
-
-
-    <root level="INFO">
-        <appender-ref ref="CONSOLE" />
-    </root>
-</configuration>
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/Application.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/Application.java
deleted file mode 100644 (file)
index f19933a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.spring.webservices;
-
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-
-@SpringBootApplication
-public class Application {
-
-  public static void main(String[] args) {
-    SpringApplication.run(Application.class);
-  }
-
-
-  @Bean
-  CommandLineRunner lookup() {
-    return args -> {
-
-    };
-  }
-
-}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/JacksonConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/JacksonConfiguration.java
deleted file mode 100644 (file)
index 2a54a3b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.spring.webservices.configuration;
-
-import javax.inject.Inject;
-
-import org.springframework.context.annotation.Configuration;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
-@Configuration
-public class JacksonConfiguration {
-
-  @Inject
-  public void configureJackson(ObjectMapper jackson2ObjectMapper) {
-         jackson2ObjectMapper
-               .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
-        .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
-        .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
-        .enable(SerializationFeature.INDENT_OUTPUT)
-        .registerModule(new JavaTimeModule());
-  }
-  
-}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/Swagger2Configuration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/Swagger2Configuration.java
deleted file mode 100644 (file)
index c4ea5bf..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-package de.spring.webservices.configuration;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static springfox.documentation.builders.RequestHandlerSelectors.basePackage;
-import static springfox.documentation.builders.RequestHandlerSelectors.withMethodAnnotation;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.ResponseMessageBuilder;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.service.Contact;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger.web.UiConfiguration;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-/**
- * Go to URL: http://localhost:8080/swagger-ui.html#/
- *
- */
-@Configuration
-@EnableSwagger2
-public class Swagger2Configuration {
-       
-       @Bean
-       public Docket documentation() {
-               return new Docket(DocumentationType.SWAGGER_2)
-                               .select()
-                                       .apis(withMethodAnnotation(RequestMapping.class))
-                                       .apis(basePackage("de.spring.webservices.rest.controller"))
-                                       .paths(PathSelectors.any())
-                                       .build()
-                                       .globalResponseMessage(RequestMethod.GET,
-                                                       newArrayList(new ResponseMessageBuilder()
-                                                                       .code(500).message("Global server custom error message").build()))
-                       .useDefaultResponseMessages(false)
-                       .apiInfo(metadata())
-                       .enable(true);
-       }
-
-       @Bean
-       UiConfiguration uiConfig() {
-               return new UiConfiguration(null);
-       }
-       
-       private static ApiInfo metadata() {
-               return new ApiInfoBuilder()
-                               .title("gumartinm REST API")
-                               .description("Gustavo Martin Morcuende")
-                               .version("1.0-SNAPSHOT")
-                       .contact(doContact())
-                       .build();
-       }
-
-       private static Contact doContact() {
-               return new Contact("Gustavo Martin", "https://gumartinm.name", "");
-       }
-}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/ValidatorConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/ValidatorConfiguration.java
deleted file mode 100644 (file)
index ff41038..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.spring.webservices.configuration;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
-
-@Configuration
-public class ValidatorConfiguration {
-
-         @Bean
-         public LocalValidatorFactoryBean localValidatorFactoryBean() {
-           return new LocalValidatorFactoryBean();
-         }
-
-}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/WadlConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/configuration/WadlConfiguration.java
deleted file mode 100644 (file)
index d128661..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.spring.webservices.configuration;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
-import org.springframework.oxm.jaxb.Jaxb2Marshaller;
-
-@Configuration
-public class WadlConfiguration {
-       
-       @Bean
-       public Jaxb2Marshaller marshaller() {
-               Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
-           marshaller.setPackagesToScan("org.jvnet.ws.wadl");
-           return marshaller;    
-       }
-
-       @Bean
-       public MarshallingHttpMessageConverter marshallingHttpMessageConverter(Jaxb2Marshaller marshaller) {
-               return new MarshallingHttpMessageConverter(marshaller);
-       }
-}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/Application.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/Application.java
new file mode 100644 (file)
index 0000000..c1dbfc3
--- /dev/null
@@ -0,0 +1,23 @@
+package de.spring.webservices.rest;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class Application {
+
+  public static void main(String[] args) {
+    SpringApplication.run(Application.class);
+  }
+
+
+  @Bean
+  CommandLineRunner lookup() {
+    return args -> {
+
+    };
+  }
+
+}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/JacksonConfiguration.java
new file mode 100644 (file)
index 0000000..4d0062b
--- /dev/null
@@ -0,0 +1,26 @@
+package de.spring.webservices.rest.configuration;
+
+import javax.inject.Inject;
+
+import org.springframework.context.annotation.Configuration;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+@Configuration
+public class JacksonConfiguration {
+
+  @Inject
+  public void configureJackson(ObjectMapper jackson2ObjectMapper) {
+         jackson2ObjectMapper
+               .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+        .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
+        .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
+        .enable(SerializationFeature.INDENT_OUTPUT)
+        .registerModule(new JavaTimeModule());
+  }
+  
+}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/Swagger2Configuration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/Swagger2Configuration.java
new file mode 100644 (file)
index 0000000..07c916b
--- /dev/null
@@ -0,0 +1,63 @@
+package de.spring.webservices.rest.configuration;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static springfox.documentation.builders.RequestHandlerSelectors.basePackage;
+import static springfox.documentation.builders.RequestHandlerSelectors.withMethodAnnotation;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.ResponseMessageBuilder;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger.web.UiConfiguration;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Go to URL: http://localhost:8080/swagger-ui.html#/
+ *
+ */
+@Configuration
+@EnableSwagger2
+public class Swagger2Configuration {
+       
+       @Bean
+       public Docket documentation() {
+               return new Docket(DocumentationType.SWAGGER_2)
+                               .select()
+                                       .apis(withMethodAnnotation(RequestMapping.class))
+                                       .apis(basePackage("de.spring.webservices.rest.controller"))
+                                       .paths(PathSelectors.any())
+                                       .build()
+                                       .globalResponseMessage(RequestMethod.GET,
+                                                       newArrayList(new ResponseMessageBuilder()
+                                                                       .code(500).message("Global server custom error message").build()))
+                       .useDefaultResponseMessages(false)
+                       .apiInfo(metadata())
+                       .enable(true);
+       }
+
+       @Bean
+       UiConfiguration uiConfig() {
+               return new UiConfiguration(null);
+       }
+       
+       private static ApiInfo metadata() {
+               return new ApiInfoBuilder()
+                               .title("gumartinm REST API")
+                               .description("Gustavo Martin Morcuende")
+                               .version("1.0-SNAPSHOT")
+                       .contact(doContact())
+                       .build();
+       }
+
+       private static Contact doContact() {
+               return new Contact("Gustavo Martin", "https://gumartinm.name", "");
+       }
+}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/ValidatorConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/ValidatorConfiguration.java
new file mode 100644 (file)
index 0000000..50adf4f
--- /dev/null
@@ -0,0 +1,15 @@
+package de.spring.webservices.rest.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+
+@Configuration
+public class ValidatorConfiguration {
+
+         @Bean
+         public LocalValidatorFactoryBean localValidatorFactoryBean() {
+           return new LocalValidatorFactoryBean();
+         }
+
+}
diff --git a/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/WadlConfiguration.java b/REST/SpringBoot/web-services-spring-rest-server/src/main/java/de/spring/webservices/rest/configuration/WadlConfiguration.java
new file mode 100644 (file)
index 0000000..bc46687
--- /dev/null
@@ -0,0 +1,22 @@
+package de.spring.webservices.rest.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+@Configuration
+public class WadlConfiguration {
+       
+       @Bean
+       public Jaxb2Marshaller marshaller() {
+               Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+           marshaller.setPackagesToScan("org.jvnet.ws.wadl");
+           return marshaller;    
+       }
+
+       @Bean
+       public MarshallingHttpMessageConverter marshallingHttpMessageConverter(Jaxb2Marshaller marshaller) {
+               return new MarshallingHttpMessageConverter(marshaller);
+       }
+}
index 7a01bea..c3ce227 100644 (file)
@@ -1,3 +1,4 @@
+# Spring Boot configuration properties
 spring:
   application:
     name: web-services-spring-rest-server
@@ -9,5 +10,14 @@ server:
   
 springfox.documentation.swagger.v2.path: /schema
 
+# By default Spring Boot uses logback.
+# logging:
+#   level:
+#     org:
+#       springframework: info
+#     ROOT: info
+   
+# Using log4j2 (just for fun) It requires exclusions in spring-boot-starter because by default
+# Spring Boot will pick up the logback dependency :/
 logging:
   config: classpath:log4j2.xml
index 2782065..85a9cc9 100644 (file)
@@ -1,3 +1,4 @@
+
    _____            _              __          __  _        _____                 _               
   / ____|          (_)             \ \        / / | |      / ____|               (_)              
  | (___  _ __  _ __ _ _ __   __ _   \ \  /\  / /__| |__   | (___   ___ _ ____   ___  ___ ___  ___ 
index db04517..f97cafa 100644 (file)
@@ -32,11 +32,13 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import de.spring.webservices.domain.Car;
 
 
+/** WHEN USING @RunWith SPRING SEARCHES FOR YOUR main Aplication AND RUNS IT!!!!! **/
 @RunWith(SpringRunner.class)
 @WebMvcTest(CarController.class)
 public class CarControllerIntegrationTest {
        
-       // For injecting and mocking services which could be  used in the Controller under test.
+       // For injecting and mocking services which could be used in the Controller under test just use @MockBean and
+       // then you can work with it using the traditional given willReturn statements from Mockito.
        //@MockBean
        //private CarService carService;