Merge pull request #12137 from hkhan/JAVA-8148-update-guide-webflux
Java 8148 update guide webflux
This commit is contained in:
commit
64999b737c
|
@ -11,7 +11,5 @@ public class Employee {
|
|||
|
||||
private String id;
|
||||
private String name;
|
||||
|
||||
// standard getters and setters
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -10,46 +10,32 @@ import java.util.Map;
|
|||
@Repository
|
||||
public class EmployeeRepository {
|
||||
|
||||
static Map<String, Employee> employeeData;
|
||||
|
||||
static Map<String, String> employeeAccessData;
|
||||
private static final Map<String, Employee> EMPLOYEE_DATA;
|
||||
|
||||
static {
|
||||
employeeData = new HashMap<>();
|
||||
employeeData.put("1", new Employee("1", "Employee 1"));
|
||||
employeeData.put("2", new Employee("2", "Employee 2"));
|
||||
employeeData.put("3", new Employee("3", "Employee 3"));
|
||||
employeeData.put("4", new Employee("4", "Employee 4"));
|
||||
employeeData.put("5", new Employee("5", "Employee 5"));
|
||||
employeeData.put("6", new Employee("6", "Employee 6"));
|
||||
employeeData.put("7", new Employee("7", "Employee 7"));
|
||||
employeeData.put("8", new Employee("8", "Employee 8"));
|
||||
employeeData.put("9", new Employee("9", "Employee 9"));
|
||||
employeeData.put("10", new Employee("10", "Employee 10"));
|
||||
|
||||
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");
|
||||
EMPLOYEE_DATA = new HashMap<>();
|
||||
EMPLOYEE_DATA.put("1", new Employee("1", "Employee 1"));
|
||||
EMPLOYEE_DATA.put("2", new Employee("2", "Employee 2"));
|
||||
EMPLOYEE_DATA.put("3", new Employee("3", "Employee 3"));
|
||||
EMPLOYEE_DATA.put("4", new Employee("4", "Employee 4"));
|
||||
EMPLOYEE_DATA.put("5", new Employee("5", "Employee 5"));
|
||||
EMPLOYEE_DATA.put("6", new Employee("6", "Employee 6"));
|
||||
EMPLOYEE_DATA.put("7", new Employee("7", "Employee 7"));
|
||||
EMPLOYEE_DATA.put("8", new Employee("8", "Employee 8"));
|
||||
EMPLOYEE_DATA.put("9", new Employee("9", "Employee 9"));
|
||||
EMPLOYEE_DATA.put("10", new Employee("10", "Employee 10"));
|
||||
}
|
||||
|
||||
public Mono<Employee> findEmployeeById(String id) {
|
||||
return Mono.just(employeeData.get(id));
|
||||
return Mono.just(EMPLOYEE_DATA.get(id));
|
||||
}
|
||||
|
||||
public Flux<Employee> findAllEmployees() {
|
||||
return Flux.fromIterable(employeeData.values());
|
||||
return Flux.fromIterable(EMPLOYEE_DATA.values());
|
||||
}
|
||||
|
||||
public Mono<Employee> updateEmployee(Employee employee) {
|
||||
Employee existingEmployee = employeeData.get(employee.getId());
|
||||
Employee existingEmployee = EMPLOYEE_DATA.get(employee.getId());
|
||||
if (existingEmployee != null) {
|
||||
existingEmployee.setName(employee.getName());
|
||||
}
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
package com.baeldung.reactive.webflux.annotation;
|
||||
|
||||
import com.baeldung.reactive.webflux.EmployeeRepository;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@SpringBootApplication(exclude = MongoReactiveAutoConfiguration.class)
|
||||
public class EmployeeSpringApplication {
|
||||
|
||||
@Bean
|
||||
EmployeeRepository employeeRepository() {
|
||||
return new EmployeeRepository();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(EmployeeSpringApplication.class, args);
|
||||
|
||||
|
|
|
@ -10,23 +10,23 @@ import reactor.core.publisher.Mono;
|
|||
public class EmployeeWebClient {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeWebClient.class);
|
||||
|
||||
|
||||
WebClient client = WebClient.create("http://localhost:8080");
|
||||
|
||||
|
||||
public void consume() {
|
||||
|
||||
Mono<Employee> employeeMono = client.get()
|
||||
.uri("/employees/{id}", "1")
|
||||
.retrieve()
|
||||
.bodyToMono(Employee.class);
|
||||
.uri("/employees/{id}", "1")
|
||||
.retrieve()
|
||||
.bodyToMono(Employee.class);
|
||||
|
||||
employeeMono.subscribe(employee -> LOGGER.info("Employee: {}", employee));
|
||||
|
||||
employeeMono.subscribe(employee -> LOGGER.debug("Employee: {}", employee));
|
||||
|
||||
Flux<Employee> employeeFlux = client.get()
|
||||
.uri("/employees")
|
||||
.retrieve()
|
||||
.bodyToFlux(Employee.class);
|
||||
|
||||
employeeFlux.subscribe(employee -> LOGGER.debug("Employee: {}", employee));
|
||||
.uri("/employees")
|
||||
.retrieve()
|
||||
.bodyToFlux(Employee.class);
|
||||
|
||||
employeeFlux.subscribe(employee -> LOGGER.info("Employee: {}", employee));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,33 +13,31 @@ import org.springframework.security.web.server.SecurityWebFilterChain;
|
|||
|
||||
@EnableWebFluxSecurity
|
||||
public class EmployeeWebSecurityConfig {
|
||||
|
||||
|
||||
@Bean
|
||||
public MapReactiveUserDetailsService userDetailsService() {
|
||||
UserDetails user = User
|
||||
.withUsername("admin")
|
||||
.password(passwordEncoder().encode("password"))
|
||||
.roles("ADMIN")
|
||||
.build();
|
||||
.withUsername("admin")
|
||||
.password(passwordEncoder().encode("password"))
|
||||
.roles("ADMIN")
|
||||
.build();
|
||||
return new MapReactiveUserDetailsService(user);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
http.csrf()
|
||||
.disable()
|
||||
.authorizeExchange()
|
||||
.pathMatchers(HttpMethod.POST, "/employees/update")
|
||||
.hasRole("ADMIN")
|
||||
.pathMatchers("/**")
|
||||
.permitAll()
|
||||
.and()
|
||||
.httpBasic();
|
||||
http
|
||||
.csrf().disable()
|
||||
.authorizeExchange()
|
||||
.pathMatchers(HttpMethod.POST, "/employees/update").hasRole("ADMIN")
|
||||
.pathMatchers("/**").permitAll()
|
||||
.and()
|
||||
.httpBasic();
|
||||
return http.build();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,50 +25,49 @@ public class EmployeeFunctionalConfig {
|
|||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> getAllEmployeesRoute() {
|
||||
return route(GET("/employees"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findAllEmployees(), Employee.class));
|
||||
return route(GET("/employees"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findAllEmployees(), Employee.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> getEmployeeByIdRoute() {
|
||||
return route(GET("/employees/{id}"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
|
||||
return route(GET("/employees/{id}"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> updateEmployeeRoute() {
|
||||
return route(POST("/employees/update"),
|
||||
req -> req.body(toMono(Employee.class))
|
||||
.doOnNext(employeeRepository()::updateEmployee)
|
||||
.then(ok().build()));
|
||||
return route(POST("/employees/update"),
|
||||
req -> req.body(toMono(Employee.class))
|
||||
.doOnNext(employeeRepository()::updateEmployee)
|
||||
.then(ok().build()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> composedRoutes() {
|
||||
return
|
||||
route(GET("/employees"),
|
||||
return
|
||||
route(GET("/employees"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findAllEmployees(), Employee.class))
|
||||
|
||||
.and(route(GET("/employees/{id}"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)))
|
||||
|
||||
.and(route(POST("/employees/update"),
|
||||
req -> req.body(toMono(Employee.class))
|
||||
.doOnNext(employeeRepository()::updateEmployee)
|
||||
.then(ok().build())));
|
||||
|
||||
.and(route(GET("/employees/{id}"),
|
||||
req -> ok().body(
|
||||
employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class)))
|
||||
|
||||
.and(route(POST("/employees/update"),
|
||||
req -> req.body(toMono(Employee.class))
|
||||
.doOnNext(employeeRepository()::updateEmployee)
|
||||
.then(ok().build())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
http.csrf()
|
||||
.disable()
|
||||
.authorizeExchange()
|
||||
.anyExchange()
|
||||
.permitAll();
|
||||
http
|
||||
.csrf().disable()
|
||||
.authorizeExchange()
|
||||
.anyExchange().permitAll();
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,27 @@ package com.baeldung.reactive.webflux.annotation;
|
|||
|
||||
import com.baeldung.reactive.webflux.Employee;
|
||||
import com.baeldung.reactive.webflux.EmployeeRepository;
|
||||
import com.baeldung.reactive.webflux.annotation.EmployeeSpringApplication;
|
||||
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.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes= EmployeeSpringApplication.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = EmployeeSpringApplication.class)
|
||||
public class EmployeeControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
|
@ -35,40 +35,62 @@ public class EmployeeControllerIntegrationTest {
|
|||
public void givenEmployeeId_whenGetEmployeeById_thenCorrectEmployee() {
|
||||
|
||||
Employee employee = new Employee("1", "Employee 1 Name");
|
||||
|
||||
|
||||
given(employeeRepository.findEmployeeById("1")).willReturn(Mono.just(employee));
|
||||
|
||||
testClient.get()
|
||||
.uri("/employees/1")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Employee.class)
|
||||
.isEqualTo(employee);
|
||||
.uri("/employees/1")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(Employee.class).isEqualTo(employee);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetAllEmployees_thenCorrectEmployees() {
|
||||
|
||||
List<Employee> employeeList = new ArrayList<>();
|
||||
|
||||
Employee employee1 = new Employee("1", "Employee 1 Name");
|
||||
Employee employee2 = new Employee("2", "Employee 2 Name");
|
||||
Employee employee3 = new Employee("3", "Employee 3 Name");
|
||||
|
||||
employeeList.add(employee1);
|
||||
employeeList.add(employee2);
|
||||
employeeList.add(employee3);
|
||||
|
||||
List<Employee> employeeList = Arrays.asList(
|
||||
new Employee("1", "Employee 1 Name"),
|
||||
new Employee("2", "Employee 2 Name"),
|
||||
new Employee("3", "Employee 3 Name")
|
||||
);
|
||||
Flux<Employee> employeeFlux = Flux.fromIterable(employeeList);
|
||||
|
||||
given(employeeRepository.findAllEmployees()).willReturn(employeeFlux);
|
||||
|
||||
testClient.get()
|
||||
.uri("/employees")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBodyList(Employee.class)
|
||||
.hasSize(3)
|
||||
.isEqualTo(employeeList);
|
||||
.uri("/employees")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBodyList(Employee.class).isEqualTo(employeeList);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "admin", roles = { "ADMIN" })
|
||||
public void givenValidUser_whenUpdateEmployee_thenEmployeeUpdated() {
|
||||
Employee employee = new Employee("10", "Employee 10 Updated");
|
||||
|
||||
given(employeeRepository.updateEmployee(employee)).willReturn(Mono.just(employee));
|
||||
|
||||
testClient.post()
|
||||
.uri("/employees/update")
|
||||
.body(Mono.just(employee), Employee.class)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(Employee.class).isEqualTo(employee);
|
||||
|
||||
verify(employeeRepository).updateEmployee(employee);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void givenInvalidUser_whenUpdateEmployee_thenForbidden() {
|
||||
Employee employee = new Employee("10", "Employee 10 Updated");
|
||||
|
||||
testClient.post()
|
||||
.uri("/employees/update")
|
||||
.body(Mono.just(employee), Employee.class)
|
||||
.exchange()
|
||||
.expectStatus().isForbidden();
|
||||
|
||||
verifyNoInteractions(employeeRepository);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@ package com.baeldung.reactive.webflux.functional;
|
|||
|
||||
import com.baeldung.reactive.webflux.Employee;
|
||||
import com.baeldung.reactive.webflux.EmployeeRepository;
|
||||
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;
|
||||
|
@ -19,10 +17,10 @@ import java.util.List;
|
|||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = EmployeeSpringFunctionalApplication.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = EmployeeSpringFunctionalApplication.class)
|
||||
public class EmployeeSpringFunctionalIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
|
@ -34,58 +32,54 @@ public class EmployeeSpringFunctionalIntegrationTest {
|
|||
@Test
|
||||
public void givenEmployeeId_whenGetEmployeeById_thenCorrectEmployee() {
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToRouterFunction(config.getEmployeeByIdRoute())
|
||||
.build();
|
||||
.bindToRouterFunction(config.getEmployeeByIdRoute())
|
||||
.build();
|
||||
|
||||
Employee employee = new Employee("1", "Employee 1");
|
||||
|
||||
given(employeeRepository.findEmployeeById("1")).willReturn(Mono.just(employee));
|
||||
|
||||
client.get()
|
||||
.uri("/employees/1")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Employee.class)
|
||||
.isEqualTo(employee);
|
||||
.uri("/employees/1")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(Employee.class).isEqualTo(employee);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetAllEmployees_thenCorrectEmployees() {
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToRouterFunction(config.getAllEmployeesRoute())
|
||||
.build();
|
||||
.bindToRouterFunction(config.getAllEmployeesRoute())
|
||||
.build();
|
||||
|
||||
List<Employee> employees = Arrays.asList(
|
||||
new Employee("1", "Employee 1"),
|
||||
new Employee("2", "Employee 2"));
|
||||
new Employee("1", "Employee 1"),
|
||||
new Employee("2", "Employee 2")
|
||||
);
|
||||
|
||||
Flux<Employee> employeeFlux = Flux.fromIterable(employees);
|
||||
given(employeeRepository.findAllEmployees()).willReturn(employeeFlux);
|
||||
|
||||
client.get()
|
||||
.uri("/employees")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBodyList(Employee.class)
|
||||
.isEqualTo(employees);
|
||||
.uri("/employees")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBodyList(Employee.class).isEqualTo(employees);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUpdateEmployee_thenEmployeeUpdated() {
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToRouterFunction(config.updateEmployeeRoute())
|
||||
.build();
|
||||
.bindToRouterFunction(config.updateEmployeeRoute())
|
||||
.build();
|
||||
|
||||
Employee employee = new Employee("1", "Employee 1 Updated");
|
||||
|
||||
client.post()
|
||||
.uri("/employees/update")
|
||||
.body(Mono.just(employee), Employee.class)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk();
|
||||
.uri("/employees/update")
|
||||
.body(Mono.just(employee), Employee.class)
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
|
||||
verify(employeeRepository).updateEmployee(employee);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue