Spring Boot 2, Webflux, Reactor, H2
Processing Real-Time data is a big challenge then Reactive tools come and help us to make an Asynchronous application without being involved with Low-Level headaches. This is a Reactive RESTful Web Service with Integration (End-To-End) test.
Tech Stack
- Java 8
- Spring Boot 2
- WebFlux
- REST standards
- Swagger UI
- H2
- JUnit 4
- Reactor
Maven Dependencies
It’s the time to create a Maven Project and put the below dependencies on your POM.xml file.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<h2.version>1.4.197</h2.version>
<lombok.version>1.16.20</lombok.version>
<swagger.version>2.8.0</swagger.version>
<reactor.version>3.1.6.RELEASE</reactor.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>runtime</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- unit testing -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>${reactor.version}</version>
<scope>test</scope>
</dependency>
DB config (application.yml)
I used H2 to make this application more independent.
spring:
datasource:
url: jdbc:h2:mem:customerdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
driver-class-name: org.h2.Driver
platform: h2
# enable H2 web console and set url for web console
# http://localhost:8080/console
h2:
console:
enabled: true
path: /console
CustomerController.java
@RestController
@RequestMapping("/customers")
public class CustomerController {
@Autowired
private CustomerService customerService;
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<Customer> save(@RequestBody Customer customer) {
return customerService.save(customer);
}
//...
}
CustomerServiceImpl.java
@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerRepository customerRepository;
@Override
public Mono<Customer> save(Customer customer) {
return Mono.just(customerRepository.save(customer));
}
//...
}
CustomerRepository.java
As you see our repository is not reactive, because Spring does not support reactive interface “ReactiveCrudRepository” for RDBMS, but we made a web and service layer reactive! If you need an entire Reactive application you should use NoSQLs (Redis, MongoDB, Cassandra, …).
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {}
Run Spring Boot
To make WebFlux Enabled we need “@EnableWebFlux” annotation.
@EnableWebFlux
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
It’s time to see what we have done, we can just run a Boot project with mvn spring-boot:run or use any IDE you like. If your Application is running on PORT 8080 just open http://localhost:8080/swagger-ui.html then you will see all Restful Endpoints (/customers).
CustomerIntegrationTest.java
This in an actual End-To-End test, That means we test the entire application like a user but with codes.
@RunWith(SpringRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@SpringBootTest(classes=Application.class,
webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CustomerIntegrationTest {
@Autowired
private WebTestClient webTestClient;
private Customer newCustomer = new Customer();
public void test2_add_customer_done() {
WebClient webClient = WebClient.create("http://localhost:" + port);
Customer customer = webClient.post().uri("/customers")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(newCustomer))
.retrieve()
.bodyToMono(Customer.class)
.block();
id = customer.getId();
assertThat(customer.getName(), is(newCustomer.getName()));
}
@Test
public void test3_find_customer_done() {
webTestClient.get().uri("/customers/{id}", id)
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.name")
.isEqualTo(newCustomer.getName());
}
//...
Github repo
Just git clone spring-boot-reactive-restful-rdbms and run it on your Machine.