2. Introduction
Just a few minutes ago, Phil Webb spoke to us about
changes happening in the industry and how Spring
adapts itself to those changes, by giving you choices.
Now we're going to show some of the new choices
available in Spring Framework 5, Spring Boot 2 and
Spring Data Kay combined together.
I think we have seen enough slides now, it is about
time we do some live coding!
3. start.spring.io
To get started with a new project, start.spring.io is the go-to
place.
[Search usual suspects in the search box]
Did you know that you can actually do the same thing right
from your IDE?
[In the IDE, project creation]
We’re going to build a fully non-blocking, reactive web
application: The app itself is very simple, it will give you a
list of restaurants which we can filter based on some
category.
=> Start with a test
4. Start with a test
[Attempt to create Restaurant, firechat discussion about starting with a test]
In Spring Framework 5 we have introduced the WebTestClient. It feels similar to
using MockMvc but it is an actual client that can be used for live integration tests
against any server.
[Add @Autowired private WebTestClient webClient]
We’re building a web-application so let’s focus on testing the controller!
[Switch to @WebFluxTest]
Here we are going to use it to test our reactive controller directly, i.e. without a
running server (just like with MockMvc).
Let’s get a list of affordable sushi places, because that’s useful…
[Write test with expectStatus OK that leads to 404]
=> Repository, implementation, test is green
5. Repository, test implementation, test is green
We need a Restaurant type and let’s assume that the controller gets data from a
Repository
[Create Restaurant, RestaurantRepository, Inject repository in Controller]
In a reactive application, we need to return a reactive streams publisher that will give
us the data once it’s available, instead of the data itself. We will use the Flux and
Mono implementations of a RS Publisher from the Reactor project.
Let’s create a mock for the repository using @MockBean.
We can improve the test to assert the content of the response
Now we can add a GetMapping to /restaurants.
[Implement @GetMapping]
Project reactor provides us with many operators for a Flux or Mono. Think of it like
Java 8 Stream but with the ability to compose asynchronous logic without worrying
about thread
[Test is green]
6. Spring Data
Spring Data Kay has reactive support for Redis, MongoDB, Couchbase and
Cassandra. When you ask for data from a remote repository, you can’t be certain
that the data will come to you immediately. And with a reactive data repository, we
are not holding any threads waiting for the data to come.
For the demo we are going to use MongoDB. As usual, starters will guide you. And,
as you need to be reactive end to end, you can count on Spring Data to give you
support for that use case.
[Add starter]
The data can be a finite collection of elements or an infinite stream. You can add
operations to declare what needs to be done with the data once it comes, just like
you declare operations over Java 8 streams.
[Add @Document/@Id on domain - Change repo - Use repo in controller]
=> Start the app
7. Start the app
We haven’t actually started the application till now. We’ve been
using a mock repository for so long but let’s connect to an actual
mongodb instance.
We can now invoke our actual endpoint and, let’s say, find fast food
places instead
[http :8080/restaurants category==fast-food maxPrice==15]
I heard “Jack in The Flux” [Whoever is there] is really good and I
wonder if it’s available tonight.
=> WebClient
8. WebClient
Let's create another endpoint that provides the first three restaurants that are
available tonight. We can get the availability data from a remote service that’s
running on port 8081.
[http :8081/restaurants/Domonos/availability]
The service might not always respond as quickly, or there may be time between
individual items, but we will stream the data as it comes without any extra cost, we
will not be blocking or holding threads at any point.
[Invoke again to show the latency http :8081/restaurants/Domonos/availability]
We could use the RestTemplate to contact the service, injecting a
RestTemplateBuilder to get defaults and your customizations, if any. But that’s
not a good choice here.
=> WebClient (2)
9. WebClient (2)
Indeed, RestTemplate is a blocking API. we don't want to make blocking
calls from the server side where we are processing many requests
concurrently. And didn't we want to stream the data? We can't do that with
the RestTemplate. Let's use the new reactive, non-blocking WebClient.
Consistent developer experience with Webclient.Builder
[Add the WebClient with baseUrl(localhost:8081) + template for the call]
Now we have a WebClient, we can create a new endpoint, get all the
restaurants from the repository and for each restaurant we ask the remote
service if there is a table available.
[Create the endpoint, add flatMap to this::getAvailability]
=> flatMap
10. flatMap
Here, think of flatMap as something that performs nested asynchronous
operations, in this case, getting the restaurant availability for the restaurant is an
async operation. At the end, flatMap will produce a single publisher using all the
nested publishers. It’s not really a new concept, Java 8 Stream API has flatMap too.
We're building a pipeline that make non-blocking calls, and the next thing is to
filter the restaurants based on availability and take only the first 3 from the
resulting flux.
Here you see the power of using Reactor in action. We're composing multiple,
asynchronous operations, without blocking, and without dealing with threads.
Simply declare what needs to be done and let it be handled in the most efficient
manner.
[http :8080/restaurants/available —stream]
=> Web Stack
11. Web Stack
We haven’t really talked about our web stack. What we’ve been using so far is
Spring WebFlux that co-exists with Spring MVC. Spring WebFlux runs on Netty
(which is an async runtime), by default. Tomcat/jetty are perfectly capable as well
and you can easily switch to any of them.
When using Tomcat/Jetty with WebFlux we do not use any of the blocking parts of
the Servlet API and stick to the Servlet 3.1 non-blocking API.
There is actually a session on this later today by Tomcat committer Violeta if you
want to know more. [Show slide]
Even though you have the option of making your application fully non-blocking
and asynchronous, we fully expect that you would still like to continue using
Spring MVC while taking advantage of the webClient API.
[Fireside chat about switching to Spring MVC]
=> Spring MVC
12. Spring MVC
[Switch, run the app again] So what just happened here.. We ran the same code on
both Spring MVC and WebFlux. What are the differences?
Underneath WebFlux eliminates all blocking and runs on a different concurrency
model. There are also features that are possible in WebFlux only.
The key point here is that Spring MVC users can also take advantage of certain
reactive features by using reactive clients like the WebClient or Spring Data
reactive repositories. This is a scenario we fully anticipate and support as a first-
class citizen.
This connects back to the theme of choice. We provide choice at every level and in
many cases you can start using reactive features in existing applications. But it
still uses blocking I/O to write the result to the HTTP response.
Oh you are reminding me of Rossen’s session later today that’s going to cover this
topic in more details. [Show slide]
=> [If we have time] Quick look at the restaurant reservation service
13. Quick look at the restaurant reservation
service
One part of adapting to change is to support new programming
languages that are coming up.
Kotlin, a language created by Jetbrains, that runs on the JVM is
gaining popularity because of the ability to write short and concise
code. Spring Framework 5 added dedicated support for Kotlin and
start.spring.io also lets you create a Spring Boot project using
Kotlin.
The restaurant availability service that we have running in the
background is itself a Spring Boot app written in Kotlin. [Walk
through the service a bit and show functional routing etc].
14. Actuator
[Remove web starter, stop the app]
Users really liked the actuator support that was available for a Spring MVC app.
How do we get the same thing with WebFlux?
Actually, that’s quite easy, just add the actuator starter as you would do naturally.
In Spring Boot 2.0, we've added support for running Actuator on top of WebFlux in
addition to the existing support for Spring MVC. Adding that support required us to
create a better abstraction for Actuator endpoints. That abstraction has allowed us
to also add support for Jersey as well.
[Add starter + start the app, show /actuator/health]
Actuators can contain sensitive information, for example, the env endpoint shows
the entire Spring environment. For security purposes, all endpoints other than info
and health are disabled by default so that they don’t get exposed accidentally.
[Expose all endpoints using the management.endpoints.web.expose property]
=> Actuator (2)
15. Actuator (2)
There are various improvements, notably the output format gives more
information now. Let’s get some information about the property we just set
[Hit the env endpoint for the key, explain the origin support]
As usual, the health endpoint gets health information from the supported
indicators based on your environment and any custom indicator you may have
implemented. Some indicators may use a blocking API and we want this to be
as transparent as possible for you so we wrap them and execute them on a
separate scheduler. But we also have now a reactive specific contract as you’ll
most likely have to return a Publisher for your custom health indicators
[Add custom health indicator and refresh the app]
One simple example is to use the WebClient to check that a remote service is
available. In this case, I am checking that our reservation service is up).
=> Banner and conclusion
16. Banner and Conclusion
So that was a short tour of the developer experience with Spring Boot and the reactive
support. Again, you’ll get a chance to explore those in more details this week. There’s
one missing bit though
[Firechat discussion about banner]
[Switch to console, start the app]
Joke driven development is the new gold standard.
Intended to trick you by creating an animated gif of my full screen just for the purpose of
the joke but Phil said if you demo, you implement it.
You can try it out by dropping your favourite animated gif support as of Spring Boot 2.0 M7.
This feature is almost as useful as the origin support.
Maybe it is. Maybe it isn’t. Regardless, the choice is yours. Thank you very much and enjoy
the conference!