This is Part 1 of the series “Merry Microservices”
We’ll be introducing a simple confidential note OAuth2 resource server with Spring Boot Webflux, and Spring Data R2DBC.
The source can be found on github at https://github.com/sdoxsee/merry-microservices/tree/part1.
Table of Contents
- Generate the project
- Add the domain
- Add the controller
- Add the repository
- Add the schema
- Configure application.yml
- Use docker-compose to start Keycloak
- Playing around with our note service
I’ve spent most of my career doing Java development–especially with the Spring Framework. Java gets a fair bit of hate–some of it is merited while much of it is myth. Personally, I love it. One downside, however, is that it tends to use a lot of memory; traditional blocking architectures and thread pools at scale really bring this to light.
With Spring Webflux, the Spring Framework has been re-architected on Project Reactor and Netty to bring about more asynchronous, event-driven, non-blocking applications (i.e. “Reactive”). Spring Webflux has some advantages over Spring MVC including more efficient resource utilization (i.e. less threads => less memory). Those lead to cheaper cloud costs and more robust services. I like that. I find it hard to justify the resource requirements for the excessive threads in Spring MVC but, since I still love Java, Spring Webflux makes “Java in the cloud” much more palatable. It also can leverage the awesome autoconfiguration features of Spring Boot that can make it super-easy to use. Webflux has some limitations (e.g. lack of non-blocking libraries, etc.) and differences from the very support-rich servlet-based stack but we’ll see that it’s pretty cool!
Generate the project
Let’s go to start.spring.io and generate our note.zip
We won’t be changing the
start.spring.io but I do want to point out that one of our dependencies is currently experimental:
spring-boot-starter-data-r2dbc– allows for the autoconfiguration of our reactive datasource
Add the domain
Below is our very simple, yet verbose,
Note domain class, although, with the power of an IDE, it’s probably really easy to generate the getters/setters! The key thing to recongize here is that it’s not a JPA
@Entity. It’s a plain class with an
org.springframework.data.annotation.@Id on the
Add the controller
Now that we know what kind of domain class we’ll be working with, let’s switch over to our controller level and add our routes using the new functional routing available in Webflux
These are pretty standard CRUD endpoints. It’s convenient to see all our routes defined together at a high level! Our endpoint implementations are implemented in our
Although I don’t recommend delegating directly to your repository in your handler methods (use a service layer!), you can see it’s pretty easy to do so. Since I’ve borrowed the shell of this handler from Matt Raible’s post (with a few modifications), I defer to his explanations for the purpose of brevity.
Add the repository
Next, let’s look at our repository layer. Spring Data R2DBC is not an ORM–as explained on Spring Data R2DBC’s github page…
Spring Data R2DBC aims at being conceptually easy. In order to achieve this it does NOT offer caching, lazy loading, write behind or many other features of ORM frameworks. This makes Spring Data R2DBC a simple, limited, opinionated object mapper.
Despite Spring Data R2DBC not being an ORM (which is arguably a good thing), there’s still a lot of power like you’re used to with Spring Data JPA repositories. We can still inherit basic CRUD methods without forfeiting the ability to add our own custom ones.
Notice: QueryDsl does not yet support R2DBC (so add your votes!)
Add the schema
Now for our schema. In my opinion, Flyway or liquibase are great choices for database revision management. However, for this demo, we’ll simply include
src/main/resources/schema.sql and Spring Boot will automatically apply it on its embedded h2 server. We don’t have Hibernate’s DDL tricks at our disposal here but you might be able to leverage Liquibase (see Kenny Bastani’s delete tweet). Here’s our uber-simple schema…
src/main/resources/application.yml, we’ve got minimal configuration that sets our port and the
issuer-uri for our locally running identity provider, keycloak.
Use docker-compose to start Keycloak
Why the is our issuer using the realm
jhipster? I was too lazy to configure keycloak for something else and took the default realm-config and users from what jhipster provides :) It includes
- two realms (
masterrealm includes 1 user:
jhipsterrealm includes 2 users:
- default identity role for
- default identity role for
- default client id and secret of
web_app/web_appconfigured for authorization_code flow
and, it’s really easy to start up on port 9080 with docker-compose! We’ve included a copy of it in the root directory of our github repo
Go to http://localhost:9080/auth/admin and log in with
Playing around with our note service
Start the Spring Boot application
That’s it! Fire up the app from the
Once your app is up and running, head over to your favourite http tool to start interacting with our note service. We’ll use Postman.
Create a note using Postman
Create a note using a
http://localhost:8081/api/notes with the a JSON body as follows:
Go to your Authorization section, click the “Get New Access Token” button, and fill in the OAuth2 configuration for your identity provider. Our configuration is as follows:
Tip: If you you need to look up the endpoints, use the discovery endpoint as your guide
Request the token, use the token, and then “Send” your request. You should see a 201 response for your newly created note.
Get the note back using Postman
Similar to creating a note, we can change our HTTP Method to
GET at the same endpoint,
http://localhost:8081/api/notes, get an access token as before, and “Send” the request. We should see a 200 response containing the note we created earlier that looks something like this:
So now, we’ve got a fully reactive OAuth2 Resource Server built with Spring Boot Webflux app and R2DBC.
- Serve up our React CRUD application with a great development experience
- Manage all the OAuth2 and OpenID Connect token flows automatically and safely with Spring Security 5.2.x and relay the access tokens to our note service
Let me know what you think in the comments section.
Thanks for reading!
If you’d like help with any of these things, find out how what I do and how you can hire me at Simple Step Solutions