diff --git a/README.md b/README.md
index de31ace..216fa75 100644
--- a/README.md
+++ b/README.md
@@ -3,13 +3,14 @@
## Sub-projects
-* Reactive web + security
-* Reactive web socket - `ON HOLD`
+* Reactive web
+* Reactive security
+* Reactive web client
+* Reactive web socket - `[STAND BY]`
* Reactive web socket client
* Reactive MongoDB
-* Reactive R2DBC - `NOT WORKING`
-* Reactive functional - `IN PROGRESS`
-* Reactive web client
+* Reactive R2DBC - `[NOT WORKING]`
+* Reactive functional
---
@@ -31,10 +32,11 @@ mvnw clean package spring-boot:run
## TODOs
-* Let R2DBC work
-* Add filter handler
+* Let R2DBC work - `[IN PROGRESS]`
* Add validation
* Add error handling
+* Add OAuth2 security
+* Test Debug
* Test Fongo
---
@@ -45,16 +47,20 @@ mvnw clean package spring-boot:run
* https://spring.io/blog/2017/03/15/spring-tips-the-spring-web-flux-reactive-client
* https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html `[IN PROGRESS]`
-* https://medium.com/@cheron.antoine/tuto-building-a-reactive-restful-api-with-spring-webflux-java-258fd4dbae41
+* https://medium.com/@cheron.antoine/tuto-building-a-reactive-restful-api-with-spring-webflux-java-258fd4dbae41 `[TODO]`
### Reactive Web
* https://www.baeldung.com/spring-webflux
* https://www.baeldung.com/spring-5-webclient
* https://www.baeldung.com/spring-reactive-sequence-logging
-* https://www.baeldung.com/spring-debugging-reactive-streams
* https://medium.com/@fede.lopez/take-reactive-programming-with-spring-to-the-infinity-and-beyond-965a4c15b26 `[TODO]`
+### Reactive Web Client
+
+* https://www.baeldung.com/spring-5-webclient
+* https://spring.io/blog/2017/03/15/spring-tips-the-spring-web-flux-reactive-client
+
### Reactive Security
* https://www.baeldung.com/spring-security-5-reactive
@@ -67,37 +73,56 @@ mvnw clean package spring-boot:run
* https://www.baeldung.com/spring-data-mongodb-reactive
-#### Fongo `[TODO]`
-
-* https://github.com/fakemongo/fongo
-* https://devops.datenkollektiv.de/testing-the-mongodb-slice-with-spring-and-fongo.html
-* https://github.com/JohnathanMarkSmith/spring-fongo-demo
-
### Reactive R2DBC
* https://spring.io/projects/spring-data-r2dbc
* https://github.com/spring-projects/spring-data-r2dbc
* https://github.com/r2dbc/r2dbc-h2
* https://github.com/r2dbc/r2dbc-postgresql
+* https://github.com/r2dbc/r2dbc-proxy - `[TODO]`
+* https://github.com/r2dbc/r2dbc-client - `[TODO]`
* https://github.com/spring-projects/spring-data-examples/tree/master/r2dbc/example
+* https://docs.spring.io/spring-data/r2dbc/docs/1.0.0.M1/reference/html/
+* https://spring.io/blog/2018/12/12/spring-data-r2dbc-1-0-m1-released - `[IN PROGRESS]`
### Reactive Functional
* https://www.baeldung.com/spring-5-functional-web
* https://spring.io/blog/2016/09/22/new-in-spring-5-functional-web-framework
* http://sinhamohit.com/writing/spring-boot-reactive-tutorial
-* https://ordina-jworks.github.io/spring/2018/09/28/SpringOne-fun-with-the-functional-web-framework.html `[IN-PROGRESS: missing handler filter function]`
-* https://medium.com/@ankesh.kapil/real-time-event-streaming-using-spring-webflux-745e8885c8bd `[TODO]`
+* https://medium.com/@ankesh.kapil/real-time-event-streaming-using-spring-webflux-745e8885c8bd
-### Reactive Web Client
+### Testing
-* https://www.baeldung.com/spring-5-webclient
-* https://spring.io/blog/2017/03/15/spring-tips-the-spring-web-flux-reactive-client
+* https://docs.spring.io/spring-security/site/docs/current/reference/html5/#test-webflux
+* https://www.baeldung.com/spring-tests
+
+### Addons
+
+#### Fongo `[TODO]`
+
+* https://github.com/fakemongo/fongo
+* https://devops.datenkollektiv.de/testing-the-mongodb-slice-with-spring-and-fongo.html
+* https://github.com/JohnathanMarkSmith/spring-fongo-demo
-### Validation `[TODO]`
+#### Filter
+
+* https://ordina-jworks.github.io/spring/2018/09/28/SpringOne-fun-with-the-functional-web-framework.html
+* https://stackoverflow.com/questions/52870517/spring-reactive-get-body-jsonobject-using-serverrequest
+
+#### Validation `[TODO]`
* https://www.baeldung.com/spring-functional-endpoints-validation
-### Error handling `[TODO]`
+#### Error handling `[TODO]`
* https://objectpartners.com/2017/11/16/spring-webflux-functional-endpoints/
+
+#### Debug `[TODO]`
+
+* https://www.baeldung.com/spring-debugging-reactive-streams
+
+#### OAuth2 `[TODO]`
+
+* https://www.baeldung.com/spring-oauth-login-webflux
+* https://docs.spring.io/spring-security/site/docs/current/reference/html/webclient.html
diff --git a/spring-reactive-client/pom.xml b/spring-reactive-client/pom.xml
index db78284..b417e52 100644
--- a/spring-reactive-client/pom.xml
+++ b/spring-reactive-client/pom.xml
@@ -22,6 +22,10 @@
org.springframework.boot
spring-boot-starter-webflux
+
+ org.springframework.data
+ spring-data-commons
+
org.projectlombok
diff --git a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EmployeeWebClient.java b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EmployeeWebClient.java
index b793369..c3bac7e 100644
--- a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EmployeeWebClient.java
+++ b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EmployeeWebClient.java
@@ -5,13 +5,21 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import java.nio.charset.Charset;
import java.util.Random;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
/**
* @author Matteo Baiguini
@@ -22,26 +30,13 @@
@AllArgsConstructor
@Getter(AccessLevel.PROTECTED)
@Component
+@Profile("web-func")
public class EmployeeWebClient {
final String URI_ROOT = "/employees";
WebClient webClient;
- @Scheduled(initialDelay = 5000, fixedRate = 1000)
- public void update() {
-
- String id = "1";
-
- log.info("update employee id {}", id);
-
- getWebClient()
- .put()
- .uri(URI_ROOT)
- .body(BodyInserters.fromObject(Employee.builder().id(id).name("Matteo Baiguini").build()))
- ;
- }
-
@Scheduled(initialDelay = 1000, fixedRate = 3000)
public void getById() {
@@ -70,6 +65,25 @@ public void getAll() {
;
}
+ @Scheduled(initialDelay = 5000, fixedRate = 10000)
+ public void update() {
+
+ final Employee employee = Employee.builder().id("1").name("Matteo Baiguini").build();
+ log.info("scheduled update employee {}...", employee);
+
+ getWebClient()
+ .put()
+ .uri(URI_ROOT)
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .header("Authorization", "Basic " + Base64Utils
+ .encodeToString(("admin:secret").getBytes(UTF_8)))
+ .body(Mono.just(employee), Employee.class)
+ .retrieve()
+ .bodyToMono(Employee.class)
+ .subscribe(this::logInfoEmployee)
+ ;
+ }
+
private String generateRandomId() {
return Integer.toString(new Random().nextInt(10));
diff --git a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EventWebClient.java b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EventWebClient.java
index 14e6661..95157ec 100644
--- a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EventWebClient.java
+++ b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/EventWebClient.java
@@ -7,6 +7,7 @@
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -25,6 +26,7 @@
@AllArgsConstructor
@Getter(AccessLevel.PROTECTED)
@Component
+@Profile("web-func")
public class EventWebClient {
final String URI_ROOT = "/events";
@@ -59,7 +61,9 @@ public void subscribeFlux() {
getWebClient()
.get()
.uri(URI_ROOT)
- .accept(MediaType.TEXT_EVENT_STREAM)
+ // WARNING: adding "accept" header is not working, investigate better about the reason!
+ // .accept(MediaType.TEXT_EVENT_STREAM)
+ // .accept(MediaType.APPLICATION_STREAM_JSON)
.retrieve()
.bodyToFlux(Event.class)
.subscribe(this::logInfoEvent)
diff --git a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/R2dbcWebClient.java b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/R2dbcWebClient.java
new file mode 100644
index 0000000..582634f
--- /dev/null
+++ b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/clients/R2dbcWebClient.java
@@ -0,0 +1,99 @@
+package com.rabbit.samples.springreactiveclient.clients;
+
+import com.rabbit.samples.springreactiveclient.domain.Employee;
+import com.rabbit.samples.springreactiveclient.domain.Event;
+import com.rabbit.samples.springreactiveclient.domain.R2dbcEmployee;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.PostConstruct;
+import java.util.Random;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 05 Mar 2019
+ */
+@Slf4j
+@AllArgsConstructor
+@Getter(AccessLevel.PROTECTED)
+@Component
+@Profile("r2dbc")
+public class R2dbcWebClient {
+
+ final String URI_ROOT = "/employees";
+
+ WebClient webClient;
+
+ @PostConstruct
+ public void postConstruct() {
+
+ insert(1, "Matteo Baiguini");
+ // insert(2, "John Doe");
+ // insert(3, "Jane Doe");
+ //
+ // getById(1);
+ //
+ // getAll();
+ }
+
+ public void insert(final Integer id, final String name) {
+
+ final R2dbcEmployee employee = R2dbcEmployee.builder().id(id).name(name).build();
+ log.info("scheduled insert employee {}", employee);
+
+ getWebClient()
+ .post()
+ .uri(URI_ROOT)
+ .body(Mono.just(employee), R2dbcEmployee.class)
+ .retrieve()
+ .bodyToMono(R2dbcEmployee.class)
+ .subscribe(this::logInfoEmployee)
+ ;
+ }
+
+ public void getById(final Integer id) {
+
+ log.info("scheduled get by id...");
+
+ getWebClient()
+ .get()
+ .uri(URI_ROOT + "/{id}", id)
+ .retrieve()
+ .bodyToMono(R2dbcEmployee.class)
+ .subscribe(this::logInfoEmployee)
+ ;
+ }
+
+ public void getAll() {
+
+ log.info("scheduled get all...");
+
+ getWebClient()
+ .get()
+ .uri(URI_ROOT)
+ .retrieve()
+ .bodyToFlux(R2dbcEmployee.class)
+ .subscribe(this::logInfoEmployee)
+ ;
+ }
+
+ private void logInfoEmployee(final R2dbcEmployee employee) {
+
+ log.info(employee.toString());
+ }
+
+}
diff --git a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/Employee.java b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/Employee.java
index dee04b8..398c514 100644
--- a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/Employee.java
+++ b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/Employee.java
@@ -4,7 +4,9 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
+import lombok.ToString;
import lombok.experimental.FieldDefaults;
@@ -13,27 +15,17 @@
* matteo@solidarchitectures.com
* 19 Feb 2019
*/
+@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
-@FieldDefaults(level = AccessLevel.PRIVATE)
+@EqualsAndHashCode
+@ToString
public class Employee {
String id;
String name;
- @Override
- public String toString() {
-
- return new StringBuilder()
- .append("{\"id\":")
- .append(getId())
- .append(",\"name\":")
- .append(getName())
- .append("}")
- .toString();
- }
-
}
diff --git a/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/R2dbcEmployee.java b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/R2dbcEmployee.java
new file mode 100644
index 0000000..bea81e0
--- /dev/null
+++ b/spring-reactive-client/src/main/java/com/rabbit/samples/springreactiveclient/domain/R2dbcEmployee.java
@@ -0,0 +1,33 @@
+package com.rabbit.samples.springreactiveclient.domain;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import lombok.experimental.FieldDefaults;
+import org.springframework.data.annotation.Id;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@Builder
+@EqualsAndHashCode
+@ToString
+public class R2dbcEmployee {
+
+ @Id
+ Integer id;
+
+ String name;
+
+}
diff --git a/spring-reactive-client/src/main/resources/application.properties b/spring-reactive-client/src/main/resources/application.properties
index 37e935f..3da597d 100644
--- a/spring-reactive-client/src/main/resources/application.properties
+++ b/spring-reactive-client/src/main/resources/application.properties
@@ -1,9 +1,14 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactivewebclient = DEBUG
# Spring
spring.application.name = spring-reactive-client
+# Spring PROFILES
+# available values: web-func | mongo | r2dbc
+spring.profiles.active = r2dbc
+
# Spring WEB
server.port = 8081
diff --git a/spring-reactive-func/pom.xml b/spring-reactive-func/pom.xml
index e89849e..e29a1c0 100644
--- a/spring-reactive-func/pom.xml
+++ b/spring-reactive-func/pom.xml
@@ -22,14 +22,10 @@
org.springframework.boot
spring-boot-starter-webflux
-
-
-
-
-
-
-
-
+
+ org.springframework.boot
+ spring-boot-starter-security
+
org.projectlombok
@@ -49,6 +45,11 @@
reactor-test
test
+
+ org.springframework.security
+ spring-security-test
+ test
+
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/CompactFunctionalConfig.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/CompactFunctionalConfig.java
index 7681e9d..b9fd2df 100644
--- a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/CompactFunctionalConfig.java
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/CompactFunctionalConfig.java
@@ -2,6 +2,9 @@
import com.rabbit.samples.springreactivefunc.domain.Employee;
import com.rabbit.samples.springreactivefunc.domain.Event;
+import com.rabbit.samples.springreactivefunc.filters.EmployeeFilterHandler;
+import com.rabbit.samples.springreactivefunc.filters.EventFilterHandler;
+import com.rabbit.samples.springreactivefunc.filters.GenericFilterHandler;
import com.rabbit.samples.springreactivefunc.repos.EmployeeRepository;
import com.rabbit.samples.springreactivefunc.repos.EventRepository;
import com.rabbit.samples.springreactivefunc.repos.impl.StaticEmployeeRepository;
@@ -15,7 +18,6 @@
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.http.MediaType.APPLICATION_JSON;
-import static org.springframework.web.reactive.function.BodyExtractors.toMono;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
@@ -43,6 +45,24 @@ EventRepository eventRepository() {
return new StaticEventRepository();
}
+ @Bean
+ GenericFilterHandler genericFilterHandler() {
+
+ return new GenericFilterHandler();
+ }
+
+ @Bean
+ EmployeeFilterHandler employeeFilterHandler() {
+
+ return new EmployeeFilterHandler();
+ }
+
+ @Bean
+ EventFilterHandler eventFilterHandler() {
+
+ return new EventFilterHandler();
+ }
+
@Bean
RouterFunction allRoutes() {
@@ -73,7 +93,6 @@ RouterFunction allRoutes() {
)
.PUT(
"",
- accept(APPLICATION_JSON),
serverRequest ->
ok()
.contentType(APPLICATION_JSON)
@@ -81,6 +100,7 @@ RouterFunction allRoutes() {
)
)
.build()
+ .filter(employeeFilterHandler()::requestLogging)
)
// EVENTS
@@ -94,7 +114,9 @@ RouterFunction allRoutes() {
.GET(
"/{id}",
serverRequest ->
- ok().body(eventRepository().findById(Long.valueOf(serverRequest.pathVariable("id"))), Event.class)
+ ok()
+ .contentType(APPLICATION_JSON)
+ .body(eventRepository().findById(Long.valueOf(serverRequest.pathVariable("id"))), Event.class)
)
.GET(
"",
@@ -105,8 +127,11 @@ RouterFunction allRoutes() {
.body(eventRepository().findAll(), Event.class)
)
).build()
+ .filter(eventFilterHandler()::requestLogging)
)
+ .filter(genericFilterHandler()::performanceLogging)
.build();
}
+
}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/ExtendedFunctionalConfig.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/ExtendedFunctionalConfig.java
index b35de35..4805a5a 100644
--- a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/ExtendedFunctionalConfig.java
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/ExtendedFunctionalConfig.java
@@ -60,7 +60,9 @@ RouterFunction getEmployeeByIdRoute() {
.GET(
"/employees/{id}",
serverRequest ->
- ok().body(employeeRepository().findById(serverRequest.pathVariable("id")), Employee.class)
+ ok()
+ .contentType(APPLICATION_JSON)
+ .body(employeeRepository().findById(serverRequest.pathVariable("id")), Employee.class)
)
.build();
}
@@ -88,10 +90,9 @@ RouterFunction updateEmployeeRoute() {
"/employees",
accept(APPLICATION_JSON),
serverRequest ->
- serverRequest
- .body(toMono(Employee.class))
- .doOnNext(employeeRepository()::update)
- .then(ok().build())
+ ok()
+ .contentType(APPLICATION_JSON)
+ .body(serverRequest.bodyToMono(Employee.class).doOnNext(employeeRepository()::update), Employee.class)
)
.build();
}
@@ -103,7 +104,9 @@ RouterFunction getEventByIdRoute() {
.GET(
"/events/{id}",
serverRequest ->
- ok().body(eventRepository().findById(Long.valueOf(serverRequest.pathVariable("id"))), Event.class)
+ ok()
+ .contentType(APPLICATION_JSON)
+ .body(eventRepository().findById(Long.valueOf(serverRequest.pathVariable("id"))), Event.class)
)
.build();
}
@@ -116,8 +119,8 @@ RouterFunction getAllEventsRoute() {
"/events",
serverRequest ->
ok()
- // .contentType(MediaType.TEXT_EVENT_STREAM)
- .contentType(MediaType.APPLICATION_STREAM_JSON)
+ .contentType(MediaType.TEXT_EVENT_STREAM)
+ // .contentType(MediaType.APPLICATION_STREAM_JSON)
.body(eventRepository().findAll(), Event.class)
)
.build();
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/SecurityConfig.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/SecurityConfig.java
index 2d56218..ddf2ceb 100644
--- a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/SecurityConfig.java
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/configs/SecurityConfig.java
@@ -1,16 +1,16 @@
package com.rabbit.samples.springreactivefunc.configs;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
-// import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
-// import org.springframework.security.config.web.server.ServerHttpSecurity;
-// import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
-// import org.springframework.security.core.userdetails.User;
-// import org.springframework.security.core.userdetails.UserDetails;
-// import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-// import org.springframework.security.crypto.password.PasswordEncoder;
-// import org.springframework.security.web.server.SecurityWebFilterChain;
+// import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.server.SecurityWebFilterChain;
/**
@@ -18,46 +18,46 @@
* matteo@solidarchitectures.com
* 25 Feb 2019
*/
-@Configuration
-// @EnableWebFluxSecurity
-// PLEASE NOTE: @Configuration already included in @EnableWebFluxSecurity
+@EnableWebFluxSecurity
+// @EnableReactiveMethodSecurity
+// PLEASE NOTE: @Configuration already included in both @EnableWebFluxSecurity and @EnableReactiveMethodSecurity
public class SecurityConfig {
- // @Bean
- // public PasswordEncoder passwordEncoder() {
- //
- // return new BCryptPasswordEncoder();
- // }
- //
- // @Bean
- // public MapReactiveUserDetailsService mapReactiveUserDetailsService() {
- //
- // UserDetails userDetails = User
- // .withUsername("admin")
- // .password(passwordEncoder().encode("secret"))
- // .roles("ADMIN")
- // .build();
- //
- // return new MapReactiveUserDetailsService(userDetails);
- // }
-
- // @Bean
- // public SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity serverHttpSecurity) {
- //
- // return serverHttpSecurity
- // .csrf().disable()
- //
- // .authorizeExchange()
- //
- // // .pathMatchers(HttpMethod.PUT, "/employees").hasRole("ADMIN")
- // // .pathMatchers("/**").permitAll()
- //
- // .anyExchange().permitAll()
- //
- // .and().httpBasic()
- //
- // .and().build()
- // ;
- // }
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ public MapReactiveUserDetailsService mapReactiveUserDetailsService() {
+
+ UserDetails adminDetails = User
+ .withUsername("admin")
+ .password(passwordEncoder().encode("secret"))
+ .roles("ADMIN")
+ .build();
+
+ return new MapReactiveUserDetailsService(adminDetails);
+ }
+
+ @Bean
+ public SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity serverHttpSecurity) {
+
+ return serverHttpSecurity
+ .csrf().disable()
+
+ .authorizeExchange()
+
+ .pathMatchers(HttpMethod.PUT, "/employees").hasRole("ADMIN")
+ .pathMatchers("/**").permitAll()
+
+ .anyExchange().permitAll()
+
+ .and().httpBasic()
+
+ .and().build()
+ ;
+ }
}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/domain/Employee.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/domain/Employee.java
index 99528ee..5b0b1c4 100644
--- a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/domain/Employee.java
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/domain/Employee.java
@@ -4,7 +4,9 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
+import lombok.ToString;
import lombok.experimental.FieldDefaults;
@@ -13,27 +15,17 @@
* matteo@solidarchitectures.com
* 19 Feb 2019
*/
+@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
-@FieldDefaults(level = AccessLevel.PRIVATE)
+@EqualsAndHashCode
+@ToString
public class Employee {
String id;
String name;
- @Override
- public String toString() {
-
- return new StringBuilder()
- .append("{\"id\":")
- .append(getId())
- .append(",\"name\":")
- .append(getName())
- .append("}")
- .toString();
- }
-
}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EmployeeFilterHandler.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EmployeeFilterHandler.java
new file mode 100644
index 0000000..c9aeedf
--- /dev/null
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EmployeeFilterHandler.java
@@ -0,0 +1,22 @@
+package com.rabbit.samples.springreactivefunc.filters;
+
+import com.rabbit.samples.springreactivefunc.domain.Employee;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.reactive.function.server.ServerRequest;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 04 Mar 2019
+ */
+@Slf4j
+public class EmployeeFilterHandler extends ObjectFilterHandler {
+
+ @Override
+ Object getBodyObject(final ServerRequest serverRequest) {
+
+ return serverRequest.bodyToMono(Employee.class).toProcessor().peek();
+ }
+
+}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EventFilterHandler.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EventFilterHandler.java
new file mode 100644
index 0000000..a012187
--- /dev/null
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/EventFilterHandler.java
@@ -0,0 +1,22 @@
+package com.rabbit.samples.springreactivefunc.filters;
+
+import com.rabbit.samples.springreactivefunc.domain.Event;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.reactive.function.server.ServerRequest;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 04 Mar 2019
+ */
+@Slf4j
+public class EventFilterHandler extends ObjectFilterHandler {
+
+ @Override
+ Object getBodyObject(final ServerRequest serverRequest) {
+
+ return serverRequest.bodyToMono(Event.class).toProcessor().peek();
+ }
+
+}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/GenericFilterHandler.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/GenericFilterHandler.java
new file mode 100644
index 0000000..0c77f75
--- /dev/null
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/GenericFilterHandler.java
@@ -0,0 +1,30 @@
+package com.rabbit.samples.springreactivefunc.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+import java.time.Instant;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 04 Mar 2019
+ */
+@Slf4j
+public class GenericFilterHandler {
+
+ public Mono performanceLogging(ServerRequest serverRequest, HandlerFunction next) {
+
+ Instant start = Instant.now();
+ Mono response = next.handle(serverRequest);
+ Duration duration = Duration.between(start, Instant.now());
+ log.debug("Processing request {} took {} ms ", serverRequest, duration.toMillis());
+ return response;
+ }
+
+}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/ObjectFilterHandler.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/ObjectFilterHandler.java
new file mode 100644
index 0000000..24c3214
--- /dev/null
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/filters/ObjectFilterHandler.java
@@ -0,0 +1,39 @@
+package com.rabbit.samples.springreactivefunc.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 04 Mar 2019
+ */
+@Slf4j
+public abstract class ObjectFilterHandler {
+
+ public Mono requestLogging(final ServerRequest serverRequest, final HandlerFunction next) {
+
+ String uri = serverRequest.uri().toString();
+ String method = serverRequest.methodName();
+ String contentType = serverRequest.headers().contentType().isPresent() ? serverRequest.headers().contentType().get().toString() : "NOT SPECIFIED";
+ String acceptType = serverRequest.headers().accept().toString();
+ String characterSet = serverRequest.headers().acceptCharset().toString();
+ Object bodyData = getBodyObject(serverRequest);
+
+ log.debug("URI: {}", uri);
+ log.debug("Method: {}", method);
+ log.debug("ContentType: {}", contentType);
+ log.debug("Accept: {}", acceptType);
+ log.debug("Charset: {}", characterSet);
+ log.debug("Body: {}", bodyData != null ? bodyData.toString() : "NOT PRESENT");
+
+ return next.handle(serverRequest);
+ }
+
+ abstract Object getBodyObject(final ServerRequest serverRequest);
+
+}
diff --git a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/repos/impl/StaticEmployeeRepository.java b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/repos/impl/StaticEmployeeRepository.java
index bdff8b0..c038752 100644
--- a/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/repos/impl/StaticEmployeeRepository.java
+++ b/spring-reactive-func/src/main/java/com/rabbit/samples/springreactivefunc/repos/impl/StaticEmployeeRepository.java
@@ -6,6 +6,7 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
+import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@@ -18,9 +19,13 @@
@Slf4j
public class StaticEmployeeRepository implements EmployeeRepository {
- static Map employeeData;
+ private static Map employeeData;
- static Map employeeAccessData;
+ @PostConstruct
+ public void postConstruct() {
+
+ initData();
+ }
public Flux findAll() {
@@ -41,23 +46,17 @@ public Mono update(final Employee employee) {
log.debug("update {}", employee);
- Employee existingEmployee = employeeData.get(employee.getId());
+ Employee currentEmployee = employeeData.get(employee.getId());
- if(existingEmployee != null) {
- existingEmployee.setName(employee.getName());
- return Mono.just(existingEmployee);
+ if(currentEmployee != null) {
+ currentEmployee.setName(employee.getName());
+ return Mono.just(currentEmployee);
}
return Mono.empty();
}
- static {
-
- initData();
- initAccessData();
- }
-
- private static void initData() {
+ public void initData() {
employeeData = new HashMap<>();
employeeData.put("1", new Employee("1","Employee 1"));
@@ -72,19 +71,4 @@ private static void initData() {
employeeData.put("10", new Employee("10","Employee 10"));
}
- private static void initAccessData() {
-
- employeeAccessData = new HashMap<>();
- employeeAccessData.put("1", "Employee 1 Access Key");
- employeeAccessData.put("2", "Employee 2 Access Key");
- employeeAccessData.put("3", "Employee 3 Access Key");
- employeeAccessData.put("4", "Employee 4 Access Key");
- employeeAccessData.put("5", "Employee 5 Access Key");
- employeeAccessData.put("6", "Employee 6 Access Key");
- employeeAccessData.put("7", "Employee 7 Access Key");
- employeeAccessData.put("8", "Employee 8 Access Key");
- employeeAccessData.put("9", "Employee 9 Access Key");
- employeeAccessData.put("10", "Employee 10 Access Key");
- }
-
}
diff --git a/spring-reactive-func/src/main/resources/application.properties b/spring-reactive-func/src/main/resources/application.properties
index a8eb189..20e80f3 100644
--- a/spring-reactive-func/src/main/resources/application.properties
+++ b/spring-reactive-func/src/main/resources/application.properties
@@ -1,6 +1,7 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactivefunc = DEBUG
# Spring
spring.application.name = spring-reactive-func
diff --git a/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeFunctionalTest.java b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeAutomaticFunctionalTest.java
similarity index 59%
rename from spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeFunctionalTest.java
rename to spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeAutomaticFunctionalTest.java
index 4e17417..e92ed14 100644
--- a/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeFunctionalTest.java
+++ b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeAutomaticFunctionalTest.java
@@ -1,17 +1,21 @@
package com.rabbit.samples.springreactivefunc;
import com.rabbit.samples.springreactivefunc.domain.Employee;
+import com.rabbit.samples.springreactivefunc.repos.impl.StaticEmployeeRepository;
import lombok.extern.slf4j.Slf4j;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
-import static org.mockito.Mockito.verify;
-
/**
* @author Matteo Baiguini
@@ -24,11 +28,23 @@
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = SpringReactiveFuncApplication.class
)
-public class EmployeeFunctionalTest {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EmployeeAutomaticFunctionalTest {
+
+ @Autowired
+ ApplicationContext applicationContext;
@Autowired
private WebTestClient webTestClient;
+ @Before
+ public void setup() {
+
+ // reset in-memory employees map
+ final StaticEmployeeRepository staticEmployeeRepository = applicationContext.getBean(StaticEmployeeRepository.class);
+ staticEmployeeRepository.initData();
+ }
+
@Test
public void test_getAll() {
@@ -72,24 +88,25 @@ public void test_getById() {
.isEqualTo(employee);
}
- // @Test
- // public void test_update() {
- //
- // // given
- // Employee employee = new Employee("1", "Employee 1 Updated");
- //
- // webTestClient
- // // when
- // .put()
- // .uri("/employees")
- // .body(Mono.just(employee), Employee.class)
- // .exchange()
- //
- // //then
- // .expectStatus()
- // .isOk()
- // .expectBody(Employee.class)
- // .isEqualTo(employee);
- // }
+ @Test
+ @WithMockUser(roles = "ADMIN")
+ public void test_update() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1 Updated");
+
+ webTestClient
+ // when
+ .put()
+ .uri("/employees")
+ .body(Mono.just(employee), Employee.class)
+ .exchange()
+
+ //then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
}
diff --git a/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeManualFunctionalTest.java b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeManualFunctionalTest.java
new file mode 100644
index 0000000..9388021
--- /dev/null
+++ b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeManualFunctionalTest.java
@@ -0,0 +1,123 @@
+package com.rabbit.samples.springreactivefunc;
+
+import com.rabbit.samples.springreactivefunc.domain.Employee;
+import com.rabbit.samples.springreactivefunc.repos.impl.StaticEmployeeRepository;
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import reactor.core.publisher.Mono;
+
+import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
+import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@Slf4j
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
+ classes = SpringReactiveFuncApplication.class
+)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EmployeeManualFunctionalTest {
+
+ @Autowired
+ ApplicationContext applicationContext;
+
+ WebTestClient webTestClient;
+
+ @Before
+ public void setup() {
+
+ // reset in-memory employees map
+ final StaticEmployeeRepository staticEmployeeRepository = applicationContext.getBean(StaticEmployeeRepository.class);
+ staticEmployeeRepository.initData();
+
+ webTestClient = WebTestClient
+ .bindToApplicationContext(applicationContext)
+ // add Spring Security test Support
+ .apply(springSecurity())
+ // .filter(basicAuthentication("user", "secret"))
+ .build();
+ }
+
+ @Test
+ public void test_getAll() {
+
+ // given
+ Employee employee1 = new Employee("1", "Employee 1");
+ Employee employee2 = new Employee("2", "Employee 2");
+ Employee employee3 = new Employee("3", "Employee 3");
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees")
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBodyList(Employee.class)
+ .hasSize(10)
+ .contains(employee1)
+ .contains(employee2)
+ .contains(employee3);
+ }
+
+ @Test
+ public void test_getById() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1");
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees/1")
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
+
+ @Test
+ public void test_update() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1 Updated");
+
+ webTestClient
+ .mutateWith(mockUser().roles("ADMIN"))
+ // when
+ .put()
+ .uri("/employees")
+ .body(Mono.just(employee), Employee.class)
+ .exchange()
+
+ //then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
+
+}
diff --git a/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeUnitTest.java b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeUnitTest.java
index 5664de4..2ef210f 100644
--- a/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeUnitTest.java
+++ b/spring-reactive-func/src/test/java/com/rabbit/samples/springreactivefunc/EmployeeUnitTest.java
@@ -5,11 +5,14 @@
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
+import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Flux;
@@ -34,6 +37,7 @@
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = SpringReactiveFuncApplication.class
)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class EmployeeUnitTest {
@Autowired
@@ -100,6 +104,7 @@ public void test_getById() {
}
@Test
+ @WithMockUser(roles = "ADMIN")
public void test_update() {
// given
@@ -124,5 +129,4 @@ public void test_update() {
verify(employeeRepository).update(employee);
}
-
}
diff --git a/spring-reactive-func/src/test/resources/application.properties b/spring-reactive-func/src/test/resources/application.properties
index 92526c6..93da0cc 100644
--- a/spring-reactive-func/src/test/resources/application.properties
+++ b/spring-reactive-func/src/test/resources/application.properties
@@ -1,7 +1,6 @@
# Logging
-#logging.level.root = ERROR
-logging.level.root = WARN
+logging.level.root = ERROR
# Spring
spring.application.name = spring-reactive-func
diff --git a/spring-reactive-mongo/src/main/resources/application.properties b/spring-reactive-mongo/src/main/resources/application.properties
index 0b22339..5c9d9c9 100644
--- a/spring-reactive-mongo/src/main/resources/application.properties
+++ b/spring-reactive-mongo/src/main/resources/application.properties
@@ -1,6 +1,7 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactivemongo = DEBUG
# Spring
spring.application.name = spring-reactive-mongo
diff --git a/spring-reactive-r2dbc/pom.xml b/spring-reactive-r2dbc/pom.xml
index c9a6394..2670c63 100644
--- a/spring-reactive-r2dbc/pom.xml
+++ b/spring-reactive-r2dbc/pom.xml
@@ -16,11 +16,11 @@
-
- org.springframework.boot
- spring-boot-devtools
- provided
-
+
+
+
+
+
@@ -44,11 +44,11 @@
spring-data-r2dbc
1.0.0.M1
-
- io.r2dbc
- r2dbc-spi
- 1.0.0.M7
-
+
+
+
+
+
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java
index 5cb759d..6508141 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java
@@ -1,42 +1,15 @@
package com.rabbit.samples.springreactiver2dbc;
-import com.rabbit.samples.springreactiver2dbc.clients.EmployeeWebClient;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.experimental.FieldDefaults;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.ConfigurableApplicationContext;
-@Slf4j
-@FieldDefaults(level = AccessLevel.PRIVATE)
-@Getter(AccessLevel.PROTECTED)
@SpringBootApplication
public class SpringReactiveR2dbcApplication {
- public static void main(String[] args) throws InterruptedException {
+ public static void main(String[] args) {
- final ConfigurableApplicationContext context = SpringApplication.run(SpringReactiveR2dbcApplication.class, args);
-
- EmployeeWebClient employeeWebClient = context.getBean(EmployeeWebClient.class);
-
- employeeWebClient.initDb();
-
- Thread.sleep(3000);
-
- employeeWebClient.insert();
- employeeWebClient.insert();
- employeeWebClient.insert();
-
- Thread.sleep(3000);
-
- employeeWebClient.getAll();
-
- Thread.sleep(3000);
-
- employeeWebClient.getById();
+ SpringApplication.run(SpringReactiveR2dbcApplication.class, args);
}
}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/clients/EmployeeWebClient.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/clients/EmployeeWebClient.java
deleted file mode 100644
index 06ccd57..0000000
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/clients/EmployeeWebClient.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.rabbit.samples.springreactiver2dbc.clients;
-
-import com.rabbit.samples.springreactiver2dbc.domain.Employee;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.experimental.FieldDefaults;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.r2dbc.function.DatabaseClient;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.WebClient;
-// import reactor.test.StepVerifier;
-
-import javax.annotation.PostConstruct;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
-
-/**
- * @author Matteo Baiguini
- * matteo@solidarchitectures.com
- * 19 Feb 2019
- */
-@Slf4j
-@FieldDefaults(level = AccessLevel.PRIVATE)
-@Getter(AccessLevel.PROTECTED)
-@Component
-public class EmployeeWebClient {
-
- DatabaseClient databaseClient;
-
- WebClient webClient = WebClient.create("http://localhost:8080");
-
- long counter = 1;
-
- public EmployeeWebClient(final DatabaseClient databaseClient) {
-
- this.databaseClient = databaseClient;
- }
-
- // @PostConstruct
- public void initDb() {
-
- log.info("Init reactive DB");
-
- List statements =
- Arrays.asList(
- "DROP TABLE IF EXISTS employee;",
- "CREATE TABLE employee ( id integer PRIMARY KEY, name VARCHAR(255) NOT NULL );"
- );
-
- statements.forEach(
- it -> getDatabaseClient()
- .execute()
- .sql(it)
- .fetch()
- .rowsUpdated()
- // .as(StepVerifier::create)
- // .verifyComplete()
- .then()
- .block()
- );
-
- // log.info("Drop table employee");
- //
- // getDatabaseClient()
- // .execute()
- // .sql("DROP TABLE IF EXISTS employee;")
- // .fetch()
- // .rowsUpdated()
- // ;
- //
- // log.info("Create table employee");
- //
- // getDatabaseClient()
- // .execute()
- // // .sql("CREATE TABLE employee (id varchar PRIMARY KEY, name varchar);")
- // .sql("CREATE TABLE employee (id integer PRIMARY KEY, name VARCHAR(250) NOT NULL);")
- // .fetch()
- // .rowsUpdated()
- // ;
- }
-
- // @Scheduled(initialDelay = 3000, fixedRate = 10000)
- public void insert() {
-
- log.info("Scheduled insert");
-
- Employee employeeRequest = Employee.builder().id(counter).name("Employee " + counter).build();
- counter++;
-
- getWebClient()
- .post()
- .uri("/employees")
- .body(BodyInserters.fromObject(employeeRequest))
- .retrieve()
- .bodyToMono(Employee.class)
- .subscribe(employeeResponse -> {
- log.info("INSERT: {}", employeeResponse);
- })
- ;
- }
-
- // @Scheduled(initialDelay = 5000, fixedRate = 3000)
- public void getById() {
-
- log.info("Scheduled getById");
-
- getWebClient()
- .get()
- .uri("/employees/{id}", generateRandomId())
- .retrieve()
- .bodyToMono(Employee.class)
- .subscribe(employee -> {
- log.info("GET: {}", employee);
- })
- ;
- }
-
- // @Scheduled(initialDelay = 5000, fixedRate = 10000)
- public void getAll() {
-
- log.info("Scheduled getAll");
-
- getWebClient()
- .get()
- .uri("/employees")
- .retrieve()
- .bodyToFlux(Employee.class)
- .subscribe(employee -> {
- log.info("GET-ALL: {}", employee);
- })
- ;
- }
-
- private String generateRandomId() {
-
- return Integer.toString(new Random().nextInt(10));
- }
-
-}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/R2dbcConfig.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/R2dbcConfig.java
new file mode 100644
index 0000000..33a75ac
--- /dev/null
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/R2dbcConfig.java
@@ -0,0 +1,81 @@
+package com.rabbit.samples.springreactiver2dbc.configs;
+
+import io.r2dbc.postgresql.PostgresqlConnectionConfiguration;
+import io.r2dbc.postgresql.PostgresqlConnectionFactory;
+import io.r2dbc.spi.ConnectionFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
+import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
+import org.testcontainers.containers.PostgreSQLContainer;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 05 Mar 2019
+ */
+@Slf4j
+@Configuration
+@EnableR2dbcRepositories("com.rabbit.samples.springreactiver2dbc.repos")
+@Order(99)
+public class R2dbcConfig extends AbstractR2dbcConfiguration {
+
+ // private PostgreSQLContainer postgres = new PostgreSQLContainer();
+
+ // @PostConstruct
+ // void postConstruct() {
+ //
+ // log.info("start postgres container...");
+ //
+ // postgres.start();
+ // }
+ //
+ // @PreDestroy
+ // void shutdown() {
+ //
+ // log.info("stop postgres container...");
+ //
+ // postgres.stop();
+ // }
+
+ @Override
+ public ConnectionFactory connectionFactory() {
+
+ log.info("create r2dbc connection factory");
+
+ // Docker
+ final String msg = "Postgres DOCKER container started: IP '{}', port '{}', dbName '{}', user '{}', pw '{}'";
+ final String containerIpAddress = "localhost";
+ final Integer firstMappedPort = 5432;
+ final String databaseName = "reactive";
+ final String username = "user";
+ final String password = "secret";
+
+ // TestContainer
+ // final String msg = "Postgres TEST container started: IP '{}', port '{}', dbName '{}', user '{}', pw '{}'";
+ // final String containerIpAddress = postgres.getContainerIpAddress();
+ // final Integer firstMappedPort = postgres.getFirstMappedPort();
+ // final String databaseName = postgres.getDatabaseName();
+ // final String username = postgres.getUsername();
+ // final String password = postgres.getPassword();
+
+ log.info(msg, containerIpAddress, firstMappedPort, databaseName, username, password);
+
+ return new PostgresqlConnectionFactory(
+ PostgresqlConnectionConfiguration
+ .builder()
+ .host(containerIpAddress)
+ .port(firstMappedPort)
+ .database(databaseName)
+ .username(username)
+ .password(password)
+ .build()
+ );
+ }
+
+}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
index e6f3491..7c4384b 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
@@ -1,17 +1,50 @@
package com.rabbit.samples.springreactiver2dbc.configs;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.data.r2dbc.function.DatabaseClient;
import org.springframework.web.reactive.config.EnableWebFlux;
+import javax.annotation.PostConstruct;
+import java.util.Arrays;
+import java.util.List;
+
/**
* @author Matteo Baiguini
* matteo@solidarchitectures.com
* 19 Feb 2019
*/
+@Slf4j
+@AllArgsConstructor
@Configuration
@EnableWebFlux
+@Order(100)
public class WebFluxConfig {
- // no-op
+ DatabaseClient databaseClient;
+
+ @PostConstruct
+ void postConstruct() {
+
+ log.info("create postgres table");
+
+ List statements =
+ Arrays.asList(
+ "DROP TABLE IF EXISTS employee;",
+ "CREATE TABLE employee ( id SERIAL PRIMARY KEY, name VARCHAR(250) );"
+ );
+
+ statements.forEach(
+ state -> databaseClient
+ .execute()
+ .sql(state)
+ .fetch()
+ // .rowsUpdated()
+ .all()
+ );
+ }
+
}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java
index 8047121..d737aa2 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java
@@ -7,6 +7,7 @@
import lombok.Getter;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -34,16 +35,7 @@ public class EmployeeController {
EmployeeRepository employeeRepository;
- @GetMapping
- private Flux getAll() {
-
- log.info("get all employees");
-
- return getEmployeeRepository().findAll();
- }
-
@GetMapping("/{id}")
- // private Mono getById(@PathVariable final String id) {
private Mono getById(@PathVariable final Long id) {
log.info("get employee by id {}", id);
@@ -51,8 +43,16 @@ private Mono getById(@PathVariable final Long id) {
return getEmployeeRepository().findById(id);
}
- @PostMapping
- // private Mono insert(@RequestBody final Employee employee) {
+ // @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ @GetMapping(produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
+ private Flux getAll() {
+
+ log.info("get all employees");
+
+ return getEmployeeRepository().findAll();
+ }
+
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
private Mono insert(@RequestBody final Employee employee) {
log.info("insert employee {}", employee);
@@ -60,8 +60,7 @@ private Mono insert(@RequestBody final Employee employee) {
return save(employee);
}
- @PutMapping
- // private Mono update(@RequestBody final Employee employee) {
+ @PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
private Mono update(@RequestBody final Employee employee) {
log.info("update employee {}", employee);
@@ -78,7 +77,6 @@ private Mono deleteAll() {
}
@DeleteMapping("/{id}")
- // private Mono deleteById(@PathVariable final String id) {
private Mono deleteById(@PathVariable final Long id) {
log.info("delete employee by id {}", id);
@@ -86,7 +84,6 @@ private Mono deleteById(@PathVariable final Long id) {
return getEmployeeRepository().deleteById(id);
}
- // private Mono save(@RequestBody final Employee employee) {
private Mono save(@RequestBody final Employee employee) {
return getEmployeeRepository().save(employee);
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java
index 74e76c6..fe867f7 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java
@@ -4,7 +4,9 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
+import lombok.ToString;
import lombok.experimental.FieldDefaults;
import org.springframework.data.annotation.Id;
@@ -19,24 +21,13 @@
@NoArgsConstructor
@Data
@Builder
+@EqualsAndHashCode
+@ToString
public class Employee {
@Id
- // String id;
- Long id;
+ Integer id;
String name;
- @Override
- public String toString() {
-
- return new StringBuilder()
- .append("{\"id\":")
- .append(getId())
- .append(",\"name\":")
- .append(getName())
- .append("}")
- .toString();
- }
-
}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java
index e91ae8f..4ba9347 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java
+++ b/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java
@@ -1,10 +1,7 @@
package com.rabbit.samples.springreactiver2dbc.repos;
import com.rabbit.samples.springreactiver2dbc.domain.Employee;
-import org.springframework.data.repository.reactive.ReactiveCrudRepository;
-import org.springframework.stereotype.Repository;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
+import org.springframework.data.r2dbc.repository.R2dbcRepository;
/**
@@ -12,23 +9,7 @@
* matteo@solidarchitectures.com
* 19 Feb 2019
*/
-// @Repository
-// public interface EmployeeRepository extends ReactiveCrudRepository {
-public interface EmployeeRepository extends ReactiveCrudRepository {
-// public interface EmployeeRepository {
-
- // Mono count();
- //
- // Flux findAll();
- //
- // Mono findById(final String id);
- //
- // Mono deleteAll();
- //
- // Mono deleteById(final String id);
- //
- // Mono save(final Employee employee);
- //
- // void init();
+public interface EmployeeRepository extends R2dbcRepository {
+ // no-op
}
diff --git a/spring-reactive-r2dbc/src/main/resources/application.properties b/spring-reactive-r2dbc/src/main/resources/application.properties
index 78b9c12..9975170 100644
--- a/spring-reactive-r2dbc/src/main/resources/application.properties
+++ b/spring-reactive-r2dbc/src/main/resources/application.properties
@@ -1,14 +1,14 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactiver2dbc = DEBUG
# Spring
spring.application.name = spring-reactive-r2dbc
# Spring PROFILES
-# Scheduling: scheduling | NULL
# Database: h2 | postgres | spi
-spring.profiles.active = scheduling, postgres
+#spring.profiles.active = postgres
# If 'spi' profile is active, please specify also following properties
#custom.r2dbc.driver = postgresql
#custom.r2dbc.host = localhost
@@ -18,5 +18,5 @@ spring.profiles.active = scheduling, postgres
#custom.r2dbc.database = reactive
# Spring DATA H2
-spring.h2.console.enabled = true
-spring.h2.console.path = /h2
+#spring.h2.console.enabled = true
+#spring.h2.console.path = /h2
diff --git a/spring-reactive-r2dbc_BAK/.mvn/wrapper/MavenWrapperDownloader.java b/spring-reactive-r2dbc_BAK/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..47336fd
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.jar b/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.properties b/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..cd0d451
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-reactive-r2dbc_BAK/mvnw b/spring-reactive-r2dbc_BAK/mvnw
new file mode 100755
index 0000000..5551fde
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/mvnw
@@ -0,0 +1,286 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ wget "$jarUrl" -O "$wrapperJarPath"
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ curl -o "$wrapperJarPath" "$jarUrl"
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-reactive-r2dbc_BAK/mvnw.cmd b/spring-reactive-r2dbc_BAK/mvnw.cmd
new file mode 100644
index 0000000..e5cfb0a
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/mvnw.cmd
@@ -0,0 +1,161 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ echo Found %WRAPPER_JAR%
+) else (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
+ echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/spring-reactive-r2dbc_BAK/pom.xml b/spring-reactive-r2dbc_BAK/pom.xml
new file mode 100644
index 0000000..2670c63
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/pom.xml
@@ -0,0 +1,152 @@
+
+
+ 4.0.0
+
+ com.rabbit.samples
+ spring-reactive-r2dbc
+ 0.0.1
+ spring-reactive-r2dbc
+ Spring Reactive Web sample projects - Reactive R2DBC
+
+
+ 11
+
+ Californium-SR3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ io.projectreactor
+ reactor-core
+
+
+ io.projectreactor.addons
+ reactor-extra
+
+
+
+ org.springframework.data
+ spring-data-r2dbc
+ 1.0.0.M1
+
+
+
+
+
+
+
+
+
+
+
+
+ io.r2dbc
+ r2dbc-postgresql
+ 1.0.0.M7
+
+
+
+
+
+
+
+
+
+ org.testcontainers
+ postgresql
+ 1.9.1
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+
+
+ spring-milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+ spring-snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-libs-snapshot
+ https://repo.spring.io/libs-snapshot
+
+
+
+
+
+ spring-milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+ spring-snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-libs-snapshot
+ https://repo.spring.io/libs-snapshot
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java
new file mode 100644
index 0000000..5cb759d
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/SpringReactiveR2dbcApplication.java
@@ -0,0 +1,42 @@
+package com.rabbit.samples.springreactiver2dbc;
+
+import com.rabbit.samples.springreactiver2dbc.clients.EmployeeWebClient;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+
+
+@Slf4j
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@Getter(AccessLevel.PROTECTED)
+@SpringBootApplication
+public class SpringReactiveR2dbcApplication {
+
+ public static void main(String[] args) throws InterruptedException {
+
+ final ConfigurableApplicationContext context = SpringApplication.run(SpringReactiveR2dbcApplication.class, args);
+
+ EmployeeWebClient employeeWebClient = context.getBean(EmployeeWebClient.class);
+
+ employeeWebClient.initDb();
+
+ Thread.sleep(3000);
+
+ employeeWebClient.insert();
+ employeeWebClient.insert();
+ employeeWebClient.insert();
+
+ Thread.sleep(3000);
+
+ employeeWebClient.getAll();
+
+ Thread.sleep(3000);
+
+ employeeWebClient.getById();
+ }
+
+}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/H2R2dbcConfig.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/H2R2dbcConfig.java
similarity index 100%
rename from spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/H2R2dbcConfig.java
rename to spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/H2R2dbcConfig.java
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/PostgresR2dbcConfig.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/PostgresR2dbcConfig.java
similarity index 100%
rename from spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/PostgresR2dbcConfig.java
rename to spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/PostgresR2dbcConfig.java
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SpiR2dbcConfig.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SpiR2dbcConfig.java
similarity index 100%
rename from spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SpiR2dbcConfig.java
rename to spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SpiR2dbcConfig.java
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SchedulingConfig.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
similarity index 54%
rename from spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SchedulingConfig.java
rename to spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
index 5e46c06..e6f3491 100644
--- a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/SchedulingConfig.java
+++ b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/configs/WebFluxConfig.java
@@ -1,8 +1,7 @@
package com.rabbit.samples.springreactiver2dbc.configs;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
-import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.reactive.config.EnableWebFlux;
/**
@@ -11,9 +10,8 @@
* 19 Feb 2019
*/
@Configuration
-@EnableScheduling
-@Profile("scheduling")
-public class SchedulingConfig {
+@EnableWebFlux
+public class WebFluxConfig {
// no-op
}
diff --git a/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java
new file mode 100644
index 0000000..8047121
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/controllers/EmployeeController.java
@@ -0,0 +1,95 @@
+package com.rabbit.samples.springreactiver2dbc.controllers;
+
+import com.rabbit.samples.springreactiver2dbc.domain.Employee;
+import com.rabbit.samples.springreactiver2dbc.repos.EmployeeRepository;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@Slf4j
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@AllArgsConstructor
+@Getter(AccessLevel.PROTECTED)
+@RestController
+@RequestMapping("/employees")
+public class EmployeeController {
+
+ EmployeeRepository employeeRepository;
+
+ @GetMapping
+ private Flux getAll() {
+
+ log.info("get all employees");
+
+ return getEmployeeRepository().findAll();
+ }
+
+ @GetMapping("/{id}")
+ // private Mono getById(@PathVariable final String id) {
+ private Mono getById(@PathVariable final Long id) {
+
+ log.info("get employee by id {}", id);
+
+ return getEmployeeRepository().findById(id);
+ }
+
+ @PostMapping
+ // private Mono insert(@RequestBody final Employee employee) {
+ private Mono insert(@RequestBody final Employee employee) {
+
+ log.info("insert employee {}", employee);
+
+ return save(employee);
+ }
+
+ @PutMapping
+ // private Mono update(@RequestBody final Employee employee) {
+ private Mono update(@RequestBody final Employee employee) {
+
+ log.info("update employee {}", employee);
+
+ return save(employee);
+ }
+
+ @DeleteMapping
+ private Mono deleteAll() {
+
+ log.info("delete all employees");
+
+ return getEmployeeRepository().deleteAll();
+ }
+
+ @DeleteMapping("/{id}")
+ // private Mono deleteById(@PathVariable final String id) {
+ private Mono deleteById(@PathVariable final Long id) {
+
+ log.info("delete employee by id {}", id);
+
+ return getEmployeeRepository().deleteById(id);
+ }
+
+ // private Mono save(@RequestBody final Employee employee) {
+ private Mono save(@RequestBody final Employee employee) {
+
+ return getEmployeeRepository().save(employee);
+ }
+
+}
diff --git a/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java
new file mode 100644
index 0000000..74e76c6
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/domain/Employee.java
@@ -0,0 +1,42 @@
+package com.rabbit.samples.springreactiver2dbc.domain;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.FieldDefaults;
+import org.springframework.data.annotation.Id;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@Builder
+public class Employee {
+
+ @Id
+ // String id;
+ Long id;
+
+ String name;
+
+ @Override
+ public String toString() {
+
+ return new StringBuilder()
+ .append("{\"id\":")
+ .append(getId())
+ .append(",\"name\":")
+ .append(getName())
+ .append("}")
+ .toString();
+ }
+
+}
diff --git a/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java
new file mode 100644
index 0000000..e91ae8f
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/EmployeeRepository.java
@@ -0,0 +1,34 @@
+package com.rabbit.samples.springreactiver2dbc.repos;
+
+import com.rabbit.samples.springreactiver2dbc.domain.Employee;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+import org.springframework.stereotype.Repository;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+// @Repository
+// public interface EmployeeRepository extends ReactiveCrudRepository {
+public interface EmployeeRepository extends ReactiveCrudRepository {
+// public interface EmployeeRepository {
+
+ // Mono count();
+ //
+ // Flux findAll();
+ //
+ // Mono findById(final String id);
+ //
+ // Mono deleteAll();
+ //
+ // Mono deleteById(final String id);
+ //
+ // Mono save(final Employee employee);
+ //
+ // void init();
+
+}
diff --git a/spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/impl/EmployeeRepositoryImpl.java b/spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/impl/EmployeeRepositoryImpl.java
similarity index 100%
rename from spring-reactive-r2dbc/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/impl/EmployeeRepositoryImpl.java
rename to spring-reactive-r2dbc_BAK/src/main/java/com/rabbit/samples/springreactiver2dbc/repos/impl/EmployeeRepositoryImpl.java
diff --git a/spring-reactive-r2dbc_BAK/src/main/resources/application.properties b/spring-reactive-r2dbc_BAK/src/main/resources/application.properties
new file mode 100644
index 0000000..1e19bed
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/resources/application.properties
@@ -0,0 +1,22 @@
+
+# Logging
+logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactiver2dbc = DEBUG
+
+# Spring
+spring.application.name = spring-reactive-r2dbc
+
+# Spring PROFILES
+# Database: h2 | postgres | spi
+spring.profiles.active = postgres
+# If 'spi' profile is active, please specify also following properties
+#custom.r2dbc.driver = postgresql
+#custom.r2dbc.host = localhost
+#custom.r2dbc.port = 5432
+#custom.r2dbc.user = user
+#custom.r2dbc.password = secret
+#custom.r2dbc.database = reactive
+
+# Spring DATA H2
+spring.h2.console.enabled = true
+spring.h2.console.path = /h2
diff --git a/spring-reactive-r2dbc_BAK/src/main/resources/import_sql.BAK b/spring-reactive-r2dbc_BAK/src/main/resources/import_sql.BAK
new file mode 100644
index 0000000..4b6262e
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/resources/import_sql.BAK
@@ -0,0 +1,3 @@
+-- INSERT INTO POSTS (id, title, description, author) VALUES (1, 'Normal post', 'Normal post description', 'John Doe');
+-- INSERT INTO POSTS (id, title, description, author) VALUES (2, 'Cool post', 'Cool post description', 'Jane Doe');
+-- INSERT INTO POSTS (id, title, description, author) VALUES (3, 'Very cool post', 'Very cool post description', 'Freddy Kruger');
\ No newline at end of file
diff --git a/spring-reactive-r2dbc_BAK/src/main/resources/logback.xml b/spring-reactive-r2dbc_BAK/src/main/resources/logback.xml
new file mode 100644
index 0000000..ee83e82
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-reactive-r2dbc_BAK/src/main/resources/schema_sql.BAK b/spring-reactive-r2dbc_BAK/src/main/resources/schema_sql.BAK
new file mode 100644
index 0000000..cfa0c25
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/main/resources/schema_sql.BAK
@@ -0,0 +1,7 @@
+create table employee
+(
+ id integer not null,
+ name varchar(255) not null,
+ primary key(id)
+);
+-- CREATE TABLE employee (id integer PRIMARY KEY, name VARCHAR(250) NOT NULL);
diff --git a/spring-reactive-r2dbc_BAK/src/test/java/com/rabbit/samples/springreactiver2dbc/ApplicationSmokeTest.java b/spring-reactive-r2dbc_BAK/src/test/java/com/rabbit/samples/springreactiver2dbc/ApplicationSmokeTest.java
new file mode 100644
index 0000000..a44c306
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/test/java/com/rabbit/samples/springreactiver2dbc/ApplicationSmokeTest.java
@@ -0,0 +1,18 @@
+package com.rabbit.samples.springreactiver2dbc;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+// @RunWith(SpringRunner.class)
+// @SpringBootTest
+public class ApplicationSmokeTest {
+
+ // @Test
+ public void contextLoads() {
+
+ // no-op
+ }
+
+}
diff --git a/spring-reactive-r2dbc/src/test/java/com/rabbit/samples/springreactiver2dbc/EmployeeFunctionalTest.java b/spring-reactive-r2dbc_BAK/src/test/java/com/rabbit/samples/springreactiver2dbc/EmployeeFunctionalTest.java
similarity index 100%
rename from spring-reactive-r2dbc/src/test/java/com/rabbit/samples/springreactiver2dbc/EmployeeFunctionalTest.java
rename to spring-reactive-r2dbc_BAK/src/test/java/com/rabbit/samples/springreactiver2dbc/EmployeeFunctionalTest.java
diff --git a/spring-reactive-r2dbc_BAK/src/test/resources/application.properties b/spring-reactive-r2dbc_BAK/src/test/resources/application.properties
new file mode 100644
index 0000000..40a62d8
--- /dev/null
+++ b/spring-reactive-r2dbc_BAK/src/test/resources/application.properties
@@ -0,0 +1,6 @@
+
+# Logging
+logging.level.root = ERROR
+
+# Spring
+spring.application.name = spring-reactive-r2dbc
diff --git a/spring-reactive-web-socket-client/src/main/resources/application.properties b/spring-reactive-web-socket-client/src/main/resources/application.properties
index 0eade16..634fcc9 100644
--- a/spring-reactive-web-socket-client/src/main/resources/application.properties
+++ b/spring-reactive-web-socket-client/src/main/resources/application.properties
@@ -1,6 +1,7 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactivewebsocketclient = DEBUG
# Spring
spring.application.name = spring-reactive-web-socket-client
diff --git a/spring-reactive-web-socket/src/main/resources/application.properties b/spring-reactive-web-socket/src/main/resources/application.properties
index 48e686c..0335628 100644
--- a/spring-reactive-web-socket/src/main/resources/application.properties
+++ b/spring-reactive-web-socket/src/main/resources/application.properties
@@ -1,6 +1,7 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactivewebsocket = DEBUG
# Spring
spring.application.name = spring-reactive-web-socket
diff --git a/spring-reactive-web/pom.xml b/spring-reactive-web/pom.xml
index c1b0cda..850da8c 100644
--- a/spring-reactive-web/pom.xml
+++ b/spring-reactive-web/pom.xml
@@ -45,6 +45,11 @@
reactor-test
test
+
+ org.springframework.security
+ spring-security-test
+ test
+
diff --git a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/WebFluxSecurityConfig.java b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/SecurityConfig.java
similarity index 79%
rename from spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/WebFluxSecurityConfig.java
rename to spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/SecurityConfig.java
index 8d0b620..07fed57 100644
--- a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/WebFluxSecurityConfig.java
+++ b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/configs/SecurityConfig.java
@@ -2,6 +2,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
+// import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
@@ -18,8 +19,9 @@
* 19 Feb 2019
*/
@EnableWebFluxSecurity
-// PLEASE NOTE: @Configuration already included in @EnableWebFluxSecurity
-public class WebFluxSecurityConfig {
+// @EnableReactiveMethodSecurity
+// PLEASE NOTE: @Configuration already included in both @EnableWebFluxSecurity and @EnableReactiveMethodSecurity
+public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
@@ -30,13 +32,13 @@ public PasswordEncoder passwordEncoder() {
@Bean
public MapReactiveUserDetailsService mapReactiveUserDetailsService() {
- UserDetails userDetails = User
+ UserDetails adminDetails = User
.withUsername("admin")
.password(passwordEncoder().encode("secret"))
.roles("ADMIN")
.build();
- return new MapReactiveUserDetailsService(userDetails);
+ return new MapReactiveUserDetailsService(adminDetails);
}
@Bean
diff --git a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/domain/Employee.java b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/domain/Employee.java
index 6275026..06e3d77 100644
--- a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/domain/Employee.java
+++ b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/domain/Employee.java
@@ -6,6 +6,7 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
+import lombok.ToString;
import lombok.experimental.FieldDefaults;
@@ -20,22 +21,11 @@
@Data
@Builder
@EqualsAndHashCode
+@ToString
public class Employee {
String id;
String name;
- @Override
- public String toString() {
-
- return new StringBuilder()
- .append("{\"id\":")
- .append(getId())
- .append(",\"name\":")
- .append(getName())
- .append("}")
- .toString();
- }
-
}
diff --git a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/repos/impl/StaticEmployeeRepository.java b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/repos/impl/StaticEmployeeRepository.java
index 3a10edb..b7955f0 100644
--- a/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/repos/impl/StaticEmployeeRepository.java
+++ b/spring-reactive-web/src/main/java/com/rabbit/samples/springreactiveweb/repos/impl/StaticEmployeeRepository.java
@@ -2,10 +2,12 @@
import com.rabbit.samples.springreactiveweb.domain.Employee;
import com.rabbit.samples.springreactiveweb.repos.EmployeeRepository;
-import org.springframework.stereotype.Repository;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
+import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@@ -15,43 +17,48 @@
* matteo@solidarchitectures.com
* 19 Feb 2019
*/
-@Repository
+@Slf4j
+@Component
public class StaticEmployeeRepository implements EmployeeRepository {
- static Map employeeData;
+ private static Map employeeData;
- static Map employeeAccessData;
+ @PostConstruct
+ public void postConstruct() {
+
+ initData();
+ }
public Flux findAll() {
+ log.debug("find all");
+
return Flux.fromIterable(employeeData.values());
}
public Mono findById(final String id) {
+ log.debug("find by id {}", id);
+
final Employee employee = employeeData.get(id);
return employee != null ? Mono.just(employee) : Mono.empty();
}
public Mono update(final Employee employee) {
- Employee existingEmployee = employeeData.get(employee.getId());
+ log.debug("update {}", employee);
+
+ Employee currentEmployee = employeeData.get(employee.getId());
- if(existingEmployee != null) {
- existingEmployee.setName(employee.getName());
- return Mono.just(existingEmployee);
+ if(currentEmployee != null) {
+ currentEmployee.setName(employee.getName());
+ return Mono.just(currentEmployee);
}
return Mono.empty();
}
- static {
-
- initData();
- initAccessData();
- }
-
- private static void initData() {
+ public void initData() {
employeeData = new HashMap<>();
employeeData.put("1", new Employee("1","Employee 1"));
@@ -66,19 +73,4 @@ private static void initData() {
employeeData.put("10", new Employee("10","Employee 10"));
}
- private static void initAccessData() {
-
- employeeAccessData = new HashMap<>();
- employeeAccessData.put("1", "Employee 1 Access Key");
- employeeAccessData.put("2", "Employee 2 Access Key");
- employeeAccessData.put("3", "Employee 3 Access Key");
- employeeAccessData.put("4", "Employee 4 Access Key");
- employeeAccessData.put("5", "Employee 5 Access Key");
- employeeAccessData.put("6", "Employee 6 Access Key");
- employeeAccessData.put("7", "Employee 7 Access Key");
- employeeAccessData.put("8", "Employee 8 Access Key");
- employeeAccessData.put("9", "Employee 9 Access Key");
- employeeAccessData.put("10", "Employee 10 Access Key");
- }
-
}
diff --git a/spring-reactive-web/src/main/resources/application.properties b/spring-reactive-web/src/main/resources/application.properties
index 4cf72f4..4ef0e6b 100644
--- a/spring-reactive-web/src/main/resources/application.properties
+++ b/spring-reactive-web/src/main/resources/application.properties
@@ -1,6 +1,7 @@
# Logging
logging.level.root = INFO
+#logging.level.com.rabbit.samples.springreactiveweb = DEBUG
# Spring
spring.application.name = spring-reactive-web
diff --git a/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeFunctionalTest.java b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeAutomaticFunctionalTest.java
similarity index 59%
rename from spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeFunctionalTest.java
rename to spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeAutomaticFunctionalTest.java
index 40da82b..6f15b30 100644
--- a/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeFunctionalTest.java
+++ b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeAutomaticFunctionalTest.java
@@ -1,11 +1,17 @@
package com.rabbit.samples.springreactiveweb;
import com.rabbit.samples.springreactiveweb.domain.Employee;
+import com.rabbit.samples.springreactiveweb.repos.impl.StaticEmployeeRepository;
import lombok.extern.slf4j.Slf4j;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
@@ -22,11 +28,23 @@
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = SpringReactiveWebApplication.class
)
-public class EmployeeFunctionalTest {
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EmployeeAutomaticFunctionalTest {
+
+ @Autowired
+ ApplicationContext applicationContext;
@Autowired
private WebTestClient webTestClient;
+ @Before
+ public void setup() {
+
+ // reset in-memory employees map
+ final StaticEmployeeRepository staticEmployeeRepository = applicationContext.getBean(StaticEmployeeRepository.class);
+ staticEmployeeRepository.initData();
+ }
+
@Test
public void test_getAll() {
@@ -70,24 +88,25 @@ public void test_getById() {
.isEqualTo(employee);
}
- // @Test
- // public void test_update() {
- //
- // // given
- // Employee employee = new Employee("1", "Employee 1 Updated");
- //
- // webTestClient
- // // when
- // .put()
- // .uri("/employees")
- // .body(Mono.just(employee), Employee.class)
- // .exchange()
- //
- // //then
- // .expectStatus()
- // .isOk()
- // .expectBody(Employee.class)
- // .isEqualTo(employee);
- // }
+ @Test
+ @WithMockUser(roles = "ADMIN")
+ public void test_update() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1 Updated");
+
+ webTestClient
+ // when
+ .put()
+ .uri("/employees")
+ .body(Mono.just(employee), Employee.class)
+ .exchange()
+
+ //then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
}
diff --git a/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeManualFunctionalTest.java b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeManualFunctionalTest.java
new file mode 100644
index 0000000..2ed7cff
--- /dev/null
+++ b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeManualFunctionalTest.java
@@ -0,0 +1,123 @@
+package com.rabbit.samples.springreactiveweb;
+
+import com.rabbit.samples.springreactiveweb.domain.Employee;
+import com.rabbit.samples.springreactiveweb.repos.impl.StaticEmployeeRepository;
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import reactor.core.publisher.Mono;
+
+import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
+import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@Slf4j
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
+ classes = SpringReactiveWebApplication.class
+)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EmployeeManualFunctionalTest {
+
+ @Autowired
+ ApplicationContext applicationContext;
+
+ WebTestClient webTestClient;
+
+ @Before
+ public void setup() {
+
+ // reset in-memory employees map
+ final StaticEmployeeRepository staticEmployeeRepository = applicationContext.getBean(StaticEmployeeRepository.class);
+ staticEmployeeRepository.initData();
+
+ webTestClient = WebTestClient
+ .bindToApplicationContext(applicationContext)
+ // add Spring Security test Support
+ .apply(springSecurity())
+ // .filter(basicAuthentication("user", "secret"))
+ .build();
+ }
+
+ @Test
+ public void test_getAll() {
+
+ // given
+ Employee employee1 = new Employee("1", "Employee 1");
+ Employee employee2 = new Employee("2", "Employee 2");
+ Employee employee3 = new Employee("3", "Employee 3");
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees")
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBodyList(Employee.class)
+ .hasSize(10)
+ .contains(employee1)
+ .contains(employee2)
+ .contains(employee3);
+ }
+
+ @Test
+ public void test_getById() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1");
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees/1")
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
+
+ @Test
+ public void test_update() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1 Updated");
+
+ webTestClient
+ .mutateWith(mockUser().roles("ADMIN"))
+ // when
+ .put()
+ .uri("/employees")
+ .body(Mono.just(employee), Employee.class)
+ .exchange()
+
+ //then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+ }
+
+}
diff --git a/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeUnitTest.java b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeUnitTest.java
new file mode 100644
index 0000000..5832aac
--- /dev/null
+++ b/spring-reactive-web/src/test/java/com/rabbit/samples/springreactiveweb/EmployeeUnitTest.java
@@ -0,0 +1,132 @@
+package com.rabbit.samples.springreactiveweb;
+
+import com.rabbit.samples.springreactiveweb.domain.Employee;
+import com.rabbit.samples.springreactiveweb.repos.EmployeeRepository;
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.verify;
+
+
+/**
+ * @author Matteo Baiguini
+ * matteo@solidarchitectures.com
+ * 19 Feb 2019
+ */
+@Slf4j
+@FieldDefaults(level = AccessLevel.PRIVATE)
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
+ classes = SpringReactiveWebApplication.class
+)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EmployeeUnitTest {
+
+ @Autowired
+ WebTestClient webTestClient;
+
+ @MockBean
+ EmployeeRepository employeeRepository;
+
+ @Test
+ public void test_getAll() {
+
+ // given
+ Employee employee1 = new Employee("1", "Employee 1");
+ Employee employee2 = new Employee("2", "Employee 2");
+ Employee employee3 = new Employee("3", "Employee 3");
+
+ List employeeList = new ArrayList<>();
+ employeeList.add(employee1);
+ employeeList.add(employee2);
+ employeeList.add(employee3);
+
+ given(employeeRepository.findAll())
+ .willReturn(Flux.fromIterable(employeeList));
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees")
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBodyList(Employee.class)
+ .isEqualTo(employeeList);
+
+ // verify
+ verify(employeeRepository).findAll();
+ }
+
+ @Test
+ public void test_getById() {
+
+ // given
+ final String employeeId = "1";
+ Employee employee = new Employee(employeeId, "Employee 1");
+ given(employeeRepository.findById(employeeId))
+ .willReturn(Mono.just(employee));
+
+ webTestClient
+ // when
+ .get()
+ .uri("/employees/" + employeeId)
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+
+ // verify
+ verify(employeeRepository).findById(employeeId);
+ }
+
+ @Test
+ @WithMockUser(roles = "ADMIN")
+ public void test_update() {
+
+ // given
+ Employee employee = new Employee("1", "Employee 1 Updated");
+ given(employeeRepository.update(employee))
+ .willReturn(Mono.just(employee));
+
+ webTestClient
+ // when
+ .put()
+ .uri("/employees")
+ .body(Mono.just(employee), Employee.class)
+ .exchange()
+
+ // then
+ .expectStatus()
+ .isOk()
+ .expectBody(Employee.class)
+ .isEqualTo(employee);
+
+ // verify
+ verify(employeeRepository).update(employee);
+ }
+
+}