Slide 1

Slide 1 text

Spring Framework 5 & Spring Boot 2.0 / olivergierke Oliver Gierke ƀ [email protected] Modern Enterprise Java in 2018

Slide 2

Slide 2 text

https://github.com/olivergierke/spring-five-functional-reactive Sample Code 2

Slide 3

Slide 3 text

Spring Framework 5 3

Slide 4

Slide 4 text

Infrastructure 4

Slide 5

Slide 5 text

Infrastructure • JavaSE 8 baseline • JDK 9 compatibility through automatic modules and JDK 9 base CI builds • JavaEE 7 baseline • Servlet API 3.1 • JPA 2.1 (OpenJPA support dropped) • JMS 2.0 • Bean Validation 1.1 • Support for selected JavaEE 8 APIs • Servlet 4 • Bean Validation 2.0 • JSON Binding API 5

Slide 6

Slide 6 text

JDK 9 Support • Many general JVM improvements • Compact Strings • G1 by default • TLS protocol stack • Jigsaw • Stable automatic module names • We currently recommend to still run in classpath mode 6

Slide 7

Slide 7 text

HTTP/2 Support • Mostly via Servlet 4.0 • HTTP/2 support in Servlet containers • PushBuilder API 7

Slide 8

Slide 8 text

JUnit 5 • Test context framework support • for both JUnit 4 and JUnit 5 • Dependency injection capabilities inspired by Spring • Constructor injection • Parameter injection á la Spring MVC • Meta annotation support inspired by Spring 8 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(…) public class MyTest { … }

Slide 9

Slide 9 text

JUnit 5 • Test context framework support • for both JUnit 4 and JUnit 5 • Dependency injection capabilities inspired by Spring • Constructor injection • Parameter injection á la Spring MVC • Meta annotation support inspired by Spring 8 @SpringJUnitConfig(…) public class MyTest { … }

Slide 10

Slide 10 text

Functional
 container extensions 9

Slide 11

Slide 11 text

Functional container extensions 10 GenericApplicationContext ctx = new GenericApplicationContext();


Slide 12

Slide 12 text

Functional container extensions 10 GenericApplicationContext ctx = new GenericApplicationContext();
 // Default constructor via reflection
 ctx.registerBean(First.class);


Slide 13

Slide 13 text

Functional container extensions 10 GenericApplicationContext ctx = new GenericApplicationContext();
 // Default constructor via reflection
 ctx.registerBean(First.class);
 // Explicit constructor via Supplier
 ctx.registerBean(Second.class,
 () -> new Second(ctx.getBean(First.class)));


Slide 14

Slide 14 text

Functional container extensions 10 GenericApplicationContext ctx = new GenericApplicationContext();
 // Default constructor via reflection
 ctx.registerBean(First.class);
 // Explicit constructor via Supplier
 ctx.registerBean(Second.class,
 () -> new Second(ctx.getBean(First.class)));
 // Explicit constructor plus BeanDefinition customization
 ctx.registerBean(Third.class,
 () -> new Third(ctx.getBean(First.class)),
 bd -> bd.setLazyInit(true));

Slide 15

Slide 15 text

A quick detour Reactive Programming 11

Slide 16

Slide 16 text

Reactive fundamentals 12 Publisher Subscriber Data Subscribe

Slide 17

Slide 17 text

Reactive fundamentals 12 Publisher Subscriber Data Subscribe

Slide 18

Slide 18 text

Reactive fundamentals 12 Publisher Subscriber Data Subscribe Business logic
 using operators ?

Slide 19

Slide 19 text

Reactive programming 101 13 Mono.just("Hello") .map(word -> word.concat(" World!")) .subscribe(System.out::println);
 Flux.just("Hello", "World") .flatMap(word -> Flux.fromArray(word.split(""))) .subscribe(System.out::println);

Slide 20

Slide 20 text

Reactive programming 101 14 someMono .map(word -> word.concat("World")) .… someFlux .flatMap(word -> Flux.fromArray(word.split(""))) .…

Slide 21

Slide 21 text

Reactive programming 101 15 someMono // Created by the infrastructure .map(word -> word.concat("World")) .… // Handled by the infrastructure someFlux // Created by the infrastructure .flatMap(word -> Flux.fromArray(word.split(""))) .… // Handled by the infrastructure

Slide 22

Slide 22 text

Reactive programming 101 16 someMono // Created by the infrastructure .map(word -> word.concat("World")) .… // Handled by the infrastructure someFlux // Created by the infrastructure .flatMap(word -> Flux.fromArray(word.split(""))) .… // Handled by the infrastructure

Slide 23

Slide 23 text

Reactive programming • Subscription based • Push VS. pull model • Backpressure blurs the line • Two-phase execution • First: to build up the pipeline. Second: once the data starts flowing • Similar to programming model of the Java 8 Stream API • Lazy execution • Nothing happens until someone subscribes • Backpressure • Subscriber signals capability to handle the amount of data 17

Slide 24

Slide 24 text

Reactive programming • Optimized for resource usage, scalability and stability • Not necessarily faster • Optimized for „mean time to first result“ • Challenge: debugging and tests • Needs non-blocking across the entire stack • Usage of blocking APIs (e.g. JDBC) severely complicates the picture and limits efficiency 18

Slide 25

Slide 25 text

Spring WebFlux 19

Slide 26

Slide 26 text

Runtime stacks 20 Servlet container Netty, Undertow, Servlet 3.1 Servlet API Spring Web Reactive API Spring MVC Spring WebFlux(.fn) New! New!

Slide 27

Slide 27 text

WebFlux Controller 21 @Controller class ReactiveUserController { private final UserRepository users; // Constructor for Dependency Injection @GetMapping("/users")
 Flux getUsers() {
 return this.repository.findAll();
 }
 }

Slide 28

Slide 28 text

WebFlux Controller 22 @Controller class ReactiveUserController { private final UserRepository users; // Constructor for Dependency Injection @GetMapping("/users")
 Flux getUsers() {
 return this.repository.findAll();
 }
 }

Slide 29

Slide 29 text

WebFlux Controller 23 @Controller class ReactiveUserController { // … continued @PostMapping("/users") Mono createUser(@RequestBody Mono user) { return user.flatMap(this.repository::save); } @GetMapping("/users/{id}/") Mono getUser(@PathVariable Long id) { return this.repository.findById(id); } }

Slide 30

Slide 30 text

WebFlux Controller 24 @Controller class ReactiveUserController { // … continued @PostMapping("/users") Mono createUser(@RequestBody Mono user) { return user.flatMap(this.repository::save); } @GetMapping("/users/{id}/") Mono getUser(@PathVariable Long id) { return this.repository.findById(id); } }

Slide 31

Slide 31 text

Spring WebFlux.fn 25

Slide 32

Slide 32 text

Functional controller 26 @Component class FunctionalUserController { private final UserRepository repository; // Constructor for Dependency Injection Mono getUser(ServerRequest request) { Mono user = Mono.just(request.pathVariable("id")) .flatMap(this.repository::findById); return ServerResponse.ok().body(user, User.class); } }

Slide 33

Slide 33 text

Functional controller 27 @Component class FunctionalUserController { private final UserRepository repository; // Constructor for Dependency Injection Mono getUser(ServerRequest request) { Mono user = Mono.just(request.pathVariable("id")) .flatMap(this.repository::findById); return ServerResponse.ok().body(user, User.class); } }

Slide 34

Slide 34 text

Functional controller 28 @Component class FunctionalUserController { // … continued Mono getUsers(ServerRequest request) { Flux users = this.repository.findAll(); return ServerResponse.ok().body(users, User.class); } }

Slide 35

Slide 35 text

Router Functions 29 @SpringBootApplication class ApplicationConfiguration { @Bean RouterFunction> routes(FunctionalUserController controller) { return RouterFunctions .route(GET("/users"), controller::getUsers) .andRoute(GET("/users/{id}"), controller::getUser); } }

Slide 36

Slide 36 text

Kotlin Extensions 30

Slide 37

Slide 37 text

ApplicationContext extensions 31 // In GenericApplicationContextExtension.kt in spring-context
 
 inline fun GenericApplicationContext.registerBean(
 vararg customizers: BeanDefinitionCustomizer,
 crossinline function: (ApplicationContext) -> T) {
 
 registerBean(T::class.java, Supplier { function.invoke(this) }, *customizers)
 } 
 // Allows …
 
 context.registerBean { Foo() }

Slide 38

Slide 38 text

Functional routing with Kotlin 32 val router = router {
 val users = …
 accept(TEXT_HTML).nest {
 "/" { ok().render("index") }
 "/sse" { ok().render("sse") }
 "/users" {
 ok().render("users", mapOf("users" to users.map { it.toDto() }))
 }
 } ("/api/users" and accept(APPLICATION_JSON)) {
 ok().body(users)
 }
 }

Slide 39

Slide 39 text

Bean definitions – Kotlin style 33 val databaseContext = beans {
 bean()
 bean()
 environment( { !activeProfiles.contains("cloud") } ) {
 bean {
 CommandLineRunner { initializeDatabase(ref()) }
 }
 } }
 
 fun initializeDatabase(userRepository: UserRepository) { // ... }

Slide 40

Slide 40 text

Miscellaneous • Component indexing for faster startup • APT processor included in spring-context-indexer • Creates index in META-INF/spring.components • Nullability annotations in the entire codebase • @Nullable to indicate optionality at injection points • Data binding against immutable objects • Via constructor argument resolution and support for Kotlin / Lombok • WebClient as reactive alternative to RestTemplate 34

Slide 41

Slide 41 text

Spring Boot 2.0 35

Slide 42

Slide 42 text

Core themes • Upgrade to Java 8 and Spring Framework 5 • Includes upgrades to all ecosystem projects based on those versions • Infrastructure upgrades • Jetty 9.4 • Tomcat 8.5 • Hibernate 5.2 • Hikari connection pool (previously Tomcat) • Reactive web test support • OAuth 2.0 support moved to Spring Security • Tweaked defaults 36

Slide 43

Slide 43 text

Core themes • Actuator refactorings • Resources moved to /application/… • All secured by default • Micrometer support • Actuator customization API • To abstract over Spring MVC, Spring WebFlux, JAX-RS and JMX 37

Slide 44

Slide 44 text

Pruning • General deprecations present in 1.5 • CRaSH project, Spring Loaded 38

Slide 45

Slide 45 text

Related talks 10:45 - 11:45 — Going reactive with Spring Data Jens Schauder (Spring Data team member), Raum: Partenkirchen 12:00 - 13:00 — The Beginner’s Guide to Spring Cloud Spencer Gibb (Spring Cloud co-lead), Raum: Partenkirchen 39

Slide 46

Slide 46 text

Thank you! Questions? / olivergierke Oliver Gierke ƀ [email protected]

Slide 47

Slide 47 text

Resources 41

Slide 48

Slide 48 text

Resources Spring Framework 5 – Migration guide https://github.com/spring-projects/spring-framework/wiki/What's-New-in-Spring-Framework-5.x https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-5.x Spring Framework 5 – FAQ https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-5-FAQ 42

Slide 49

Slide 49 text

Resources Blog series on Reactive Programming https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape Reactor – Project homepage https://projectreactor.io/ 43

Slide 50

Slide 50 text

Resources Spring Boot 2.0 release notes https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes Spring Boot 1.5 -> 2.0 migration guide https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide Micrometer documentation http://micrometer.io/docs Documentation of Spring Boot metrics https://docs.spring.io/spring-boot/docs/2.0.x/reference/htmlsingle/#production-ready-metrics Spring Boot 2.0 Actuators (blog post) https://spring.io/blog/2017/08/22/introducing-actuator-endpoints-in-spring-boot-2-0 44