BAEL-2715: Moved reactor netty samples to an existing module

This commit is contained in:
isaolmez 2019-03-27 21:35:54 +03:00
parent fc8abdc6e3
commit d26f3ac49a
14 changed files with 299 additions and 17 deletions

View File

@ -1,23 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-5-webflux</artifactId>
<version>1.0-SNAPSHOT</version>
<name>spring-5-webflux</name>
<url>http://www.baeldung.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot.version>2.0.2.RELEASE</spring-boot.version>
</properties>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<dependencyManagement>
<dependencies>
@ -58,12 +55,8 @@
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

View File

@ -0,0 +1,36 @@
package com.baeldung.spring.serverconfig;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.netty.NettyServerCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import reactor.netty.http.server.HttpServer;
@Configuration
@Profile("skipAutoConfig")
public class CustomNettyWebServerFactory {
@Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory();
webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer());
return webServerFactory;
}
private static class EventLoopNettyCustomizer implements NettyServerCustomizer {
@Override
public HttpServer apply(HttpServer httpServer) {
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup();
return httpServer
.tcpConfiguration(tcpServer -> tcpServer.bootstrap(
serverBootstrap -> serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class)
));
}
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.spring.serverconfig;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/greet")
public class GreetingController {
private final GreetingService greetingService;
public GreetingController(GreetingService greetingService) {
this.greetingService = greetingService;
}
@GetMapping("/{name}")
private Mono<String> greet(@PathVariable String name) {
return greetingService.greet(name);
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.spring.serverconfig;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class GreetingService {
public Mono<String> greet(String name) {
return Mono.just("Greeting " + name);
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.spring.serverconfig;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.netty.NettyServerCustomizer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
import reactor.netty.http.server.HttpServer;
@Component
public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
@Override
public void customize(NettyReactiveWebServerFactory serverFactory) {
serverFactory.addServerCustomizers(new PortCustomizer(8443));
}
private static class PortCustomizer implements NettyServerCustomizer {
private final int port;
private PortCustomizer(int port) {
this.port = port;
}
@Override
public HttpServer apply(HttpServer httpServer) {
return httpServer.port(port);
}
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.spring.serverconfig;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.netty.SslServerCustomizer;
import org.springframework.boot.web.server.Http2;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
@Override
public void customize(NettyReactiveWebServerFactory serverFactory) {
Ssl ssl = new Ssl();
ssl.setEnabled(true);
ssl.setKeyStore("classpath:sample.jks");
ssl.setKeyAlias("alias");
ssl.setKeyPassword("password");
ssl.setKeyStorePassword("secret");
Http2 http2 = new Http2();
http2.setEnabled(false);
serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null));
serverFactory.setPort(8443);
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.spring.serverconfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServerConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ServerConfigApplication.class, args);
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="Console"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
</Pattern>
</layout>
</appender>
<appender name="AccessLog" class="ch.qos.logback.core.FileAppender">
<file>netty-access.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="Async" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="AccessLog"/>
</appender>
<logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
<appender-ref ref="Console"/>
<appender-ref ref="Async"/>
</logger>
<root level="info">
<appender-ref ref="Console"/>
</root>
</configuration>

Binary file not shown.

View File

@ -9,7 +9,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ResponseStatusControllerTests {
public class ResponseStatusControllerLiveTest {
@Autowired
private WebTestClient testClient;

View File

@ -0,0 +1,41 @@
package com.baeldung.spring.serverconfig;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
@RunWith(SpringRunner.class)
@WebFluxTest
public class GreetingControllerIntegrationTest {
@Autowired
private WebTestClient webClient;
@MockBean
private GreetingService greetingService;
private final String name = "Baeldung";
@Before
public void setUp() {
when(greetingService.greet(name)).thenReturn(Mono.just("Greeting Baeldung"));
}
@Test
public void shouldGreet() {
webClient.get().uri("/greet/{name}", name)
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Greeting Baeldung");
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.spring.serverconfig;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import javax.net.ssl.SSLException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
import reactor.netty.http.client.HttpClient;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
@DirtiesContext
public class GreetingLiveTest {
private static final String BASE_URL = "https://localhost:8443";
private WebTestClient webTestClient;
@Before
public void setup() throws SSLException {
webTestClient = WebTestClient.bindToServer(getConnector())
.baseUrl(BASE_URL)
.build();
}
@Test
public void shouldGreet() {
final String name = "Baeldung";
ResponseSpec response = webTestClient.get()
.uri("/greet/{name}", name)
.exchange();
response.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Greeting Baeldung");
}
private ReactorClientHttpConnector getConnector() throws SSLException {
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext));
return new ReactorClientHttpConnector(httpClient);
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.spring.serverconfig;
import org.springframework.test.context.ActiveProfiles;
@ActiveProfiles("skipAutoConfig")
public class GreetingSkipAutoConfigLiveTest extends GreetingLiveTest {
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
</Pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="Console"/>
</root>
</configuration>