 Hello Java developers. My name is Matt Ravel. Today I'd like to show you how you can use spring session in Redis to make it so your session is distributed between nodes and so if one fails the other one will pick it up and guess what? People then get logged out, session is intact and it allows you to scale to the moon. Let's get it up. So this screencast is based on a blog post that we published back in December of 2020 and you'll notice it's been updated as recent as March 8th. So I'm actually recording this on March 9th but you might not see it till April or maybe you're even watching it in 2023. If you click on that last updated it'll take you down to the bottom where you can see the PRs that we merged to upgrade it to the latest releases and mostly it's a J-Hipster 770 thing but it also uses HA proxy the latest version as well as Redis the latest version. So if you go back up to the top there's a github icon here you can click on to go to the github repo and in here this is a completed example so if you just want to clone this and run it there's all kinds of instructions here in the readme but what I'm going to do is just use this demo dot adoc file and so adoc stands for ASCII doc and if I click on the raw version here you'll see it renders quite nicely with my ASCII doctor plugin and I'm going to put this on the left and then I'll open up a terminal on the right and you might be asking why is this important? Well it's important because spring security by default if you're using its OAuth 2 login feature which I think should be called OIDC login because OAuth 2 doesn't have anything to do with authentication that's open id connect it'll actually store the access tokens and id tokens in your session so if your session expires then well you're not logged in anymore so we might do another post on how to do authentication patterns for expired sessions but for the moment what I'm going to show you is how to keep those sessions you know intact in redis and so if a node failure happens then you'll be good to go so I'm going to start by just verifying the prerequisites java 11 I have java 17 so let's do sdk I'm using sdk man for this you can get it from sdkman.io sdk default java 11 dash open I think it is nope sdk list java that looks like I got that one from Coretto keep going java.net local only it's here's the one I want so quit that sdk default java 11.02 open and now I'm using java 11 okay and then jhipster 770 so check that version and then docker I have installed and the octa cli so it looks like all our prerequisites there we're good to go if we just look at our table of contents here we're going to build a microservices architecture with jhipster we'll add authentication with open id connect we'll configure spring session in redis and then we'll show you using ha proxy how to you know route traffic between two instances of a microservice or actually a spring cloud gateway and then keep everything intact so if you were to refresh the page and one goes down you didn't lose anything so you can start by installing jhipster here if you don't have it installed that's the command npm install dash g generator jhipster I already have it so I don't need to install it and then I'm going to use a jdl sample jdl stands for jhipster domain language and I'm going to use this microservice ecommerce store for apps so we'll start by creating a folder for the project I'll do this in my downloads directory if using oh my zsh you can actually do take spring session redis to do the exact same command that I just did so that's pretty slick and then we'll copy that jdl locally and rename it to jhipster redis so now if we were to open this up in intelligent and open that jhipster redis file you'll see it's got application definitions for our store for a product for an invoice and for a notification so just a simple microservices architecture it's got a bunch of entities down here that belong to the various microservices as well and so it uses authentication type of jwt by default so let's change that to oop 2 and then it uses gradle we're going to change that to maven and if you like gradle of course this tutorial will work just some of the commands will change the only reason I'm using maven here is because well the person that wrote this tutorial actually did with maven and so hey that's what I'm going to use and so now we've updated everything you can see the instructions on the left here tell you what it looks like and it looks just like it does on the right and then we can run this jhipster jdl command so jhipster jdl point to that jhipster redis jdl you can see that took about two minutes and 40 seconds I did try to do this screencast on my new macbook pro m1 recently and and it failed because there's some docker containers that need to have a flag of the platform for amd64 so when I did this same command on it it took about two minutes so you can see it really depends on your hardware your internet connection speed how fast all this happens I should mention too that I'm using node 16 I didn't mention that in the beginning but if I read node version there you'll see I'm going to create a docker compose directory so we can run everything jhipster has the ability to basically generate a docker compose file that has all your microservices in there as well as a jhipster registry which uses eureka server to coordinate the communication between all your microservices so that can be very handy to run everything without having to you know cd into each directory and run a maven command or a gradle command to start them up and make sure all their docker containers are running that they depend on so this is just easier and in here we'll run jhipster docker compose which is a sub generator for jhipster it'll prompt us with some values we want to choose microservice application screen cloud gateway and then it's located in the parent directory and then you select these with spacebar arrow keys we don't want to use any cluster databases and for simplicity we're not going to have monitoring and we're going to use the good old worst best practice ever not worst best just the worst i'm using admin for the admin password so make sure and change that but if you're not going to check it into source control probably doesn't matter because you're just trying to get things working right here so you'll notice it gives us an error about hey we don't have any docker images for these various microservices so you know run these commands in these directories so we'll start with this one here and we'll do it in that invoice directory and we'll do dash d skip test so it happens a little faster and then we'll do another one in the notification directory and then product and store and you might notice it took about a minute to build those microservices and then the store which is the spring cloud gateway took about two minutes to run the reason that that took longer is because that's where all the front end files are located so this actually generates a monolith ui in a sense and we do have support for micro front ends but that's a video for a different day so i won't go into that i'll just exit out of these and then i'm going to go into that docker compose and by default this generates a docker compose file that uses key cloak for authentication and you could start this up and it would use key cloak and everything would work just fine and that's awesome if you're on a plane because it's in a docker container and you don't have to worry about actually you know connecting to the internet to authenticate but i like to show octa because we're on octa dev channel so i will go ahead and use octa cli to create a new j hipster app so this is octa apps create j hipster and we'll name it j hipster redis and it defaults to the correct redirect ui's that you'll need that 8080 is for the gateway the store application and then 8761 is for the j hipster registry which we'll also configure to talk to octa you don't have to but i like to because you know why not use the same authentication for everyone and so you'll notice this does a few things it creates an oidc application with that client id it creates a groups claim on the authorization server it creates a couple groups and adds the user to them and then it writes everything to a dot octa dot env file so if we were to open this up back in intelligent we can see that right here and it's got an issuer a client id and a client secret and so what i'm going to do is i'm going to start by modifying docker compose to use uh those variables and i'm going to do that by modifying each spring security setting that we have here this is for the uh invoice microservice so we're going to set those values and override them from uh from environment variables i'll do this one as well for the notification service for the product service and the store and then i'm also going to do it for j hipster registry just because i think it's cool that you can use you know a different identity provider for all of them if you just want to use jwt authentication for the registry you could just remove this oauth 2 right here and nothing would be used it would just use the default of jwt and so now we'll create a dot env file this is how we set those environment variables so dot env and the root directory and docker compose will be aware of this and then we're going to set up those variables and we'll grab the values from this file and this file doesn't like quotes just to warn you so don't put them in there okay so now we've configured it for octa and there is a way in the j hipster registry if you're going to this file and actually specify spring security uh long class name or long parameter name it's uh it's this one right here if we were to look here it's uh spring dot security dot oauth dot client dot provider dot you know there's a lot so if you were to put those settings in here and specify it for octa it would override all the microservices so that's a little bit better way to do it but i wanted to stay true to the tutorial that was written and do it how the tutorial shows it so if you want to do it that way there's this uh other blog post that i wrote java microservices with spring cloud config and j hipster and that will go over how to do that and so now we can do docker compose up i'll do this in a terminal over here but this will take quite some time to initialize the first time especially if you're like me and you had to download all those docker containers which i would imagine you would if you're new to j hipster and then you have to wait for everything to kind of start up and you can see if you see my screen right here it's actually going through and you know color coding the different services so you can kind of see them going but once you see a message from the j hipster registry then you can open that up on port eight seven six one and you should be able to actually you know log in and see the status of the various services so let's try that now there we go and automatically redirect to log in let's check our configuration maybe we messed up in docker compose ah look at that we had a little error on the end so fix that up stop everything with control c and start them all again sorry about that but at least you know if you you know fat finger something when you're copying you know values into that docker compose then can mess everything up for you redirecting to log in and boom now it works and it will show us the status of those various services as they come online we can hit this refresh now button or you can set this to you know refresh every 10 seconds every five seconds and you can also watch the logs to kind of see them coming online all right now everything's up and running so we're looking good there we can go to local host 8080 and make sure the gateway is working so we can actually talk to the various services now if we log in since we're already logged into octa it'll log us right in and we could go to for instance uh product order or product and add a new product so we'll just say beer i like beer it's expensive where i live in colorado here and uh let's get a large one and let's see if i have an image my hard drive here pictures there we are save it and that's all working so back to our instructions we'll put this on the left here and we're going to basically configure the store now to use spring session and redis so it currently maintains that user session in memory it's identified with a session idea it uses good old fashioned second session cookies to communicate with the front end and if the store instance crashes that session is lost and so one way to avoid losing the session is by adding spring session with redis for the storage for the session storage and share it among store notes and uh we'll start by deleting the store image so we make sure when we update it we're actually updating it we'll do that with docker rmi store force all right and then we're going to edit the palm dot xml in the store project to add new dependencies doesn't really matter where you do it just anywhere in here and then uh spring data redis does not pull any client by default that's why we're using lettuce in this case and to enable redis for our spring profiles we need to add it to our configuration for spring so that's in source main resources we're going to do it in the dev and prod profile if you wanted to you could probably do it in the root profile but again i'm just going to you know follow the tutorial so we need to go to just spring here we can add it right at the top if you want to do it alphabetically of course you can do that and store type equals redis now we'll copy that for prod and then we'll disable it in the test because you know we don't want to really deal with it while we're testing so down here there's some excludes for auto configure so we'll add this one here and then we'll also set the session store type to none so we'll just do it right here again if you want to do it alphabetically you certainly can but you know how yamla is so just making sure and get your indents right and you should be good to go and so now we'll cd into store and we'll run that mvn uh dash p prod verify jib and build it again while that's running we can modify the docker compose file to set the redis configuration so look for the store image all right there it is and then we need to set some environment variables here so we're just going to set the logging to trace and set the spring redis host and the password and the port and then we're going to add a store redis at as a new service so you could do it like right here and make sure and indent it you know two spaces there or your yaml be all messed up so you can see that's using redis 6.2 and starts that redis server and then as soon as that's done building we can start up docker compose again okay so docker compose up i should mention you might need to tweak your docker settings under docker preferences resources so you can see my cpus are up there my memory is really up there and uh the swap and everything so the defaults might not be enough i think the memory is only two or four gigs so you might need to tweak those to start everything up so if you have any issues with starting everything make sure and do that and then if we were to log into localhost 8080 here and make this a bit bigger click sign in octa still got our session so we're signed in and then if we were to go to product we should be able to see that beer so that's all working and we want to delete it we could certainly delete it and then back to our instructions here it says to run this docker exec command and you'll notice that's our session that's been stored in redis so everything's working and now what we'll do is we'll add a high availability proxy load balancer that uh that you know makes it so it'll fail over from one to another if we uh if we kill a store instance so we're going to start by removing docker remove docker compose store one oh we can't remove a running container so stop everything with control c and then try it again so remove that and then we'll open up intelligent again and we're going to extract this store definition right here into its own docker compose file so we'll start by grabbing that and taking away those ports and we'll create a store dot yml i don't want to do it so touch docker compose store dot yml and then this needs to start i don't think the version's that important but i know the services is so services and then store that way and as long as your yaml's all pasted correctly everything should work and then we'll edit this docker compose and we'll add multiple stores store one store two that extend that store and then we can override the ports and have multiple instances so you can see we have store one there extends store and let me get rid of that highlighting and we're just naming it store one it runs on 8081 or 8080 and then the second instance runs on 8081 and we'll configure ha proxy to be a service that proxies to either one so now we'll create an ha proxy dot yml and open that one up and configure it to load from this docker file and that's going to be pretty simple here and we're going to use ha proxy to five and we need an ha proxy dot cfg to configure it i need this one and you'll see it's just a daemon with the maximum connections of 2000 and it's got some round robin ing that basically says if uh if the option redispatch right here it will redispatch the request to another server if the current server is down so it's going to use cookies and all that and go from store one to store two and so because ha proxy will listen on port 80 we do need to update our octa configuration to uh to have redirect URIs without ports in them so i like to use octa login as a shortcut and it does prompt you nowadays it used to not but um i think that's probably better and now you can go to your application make this a bit bigger and j hipster redis here and modify your general settings and you'll see we have these URIs down here so we can just add one with no ports same down here and so we're just running on 8080 the default and then save that so now we can close that back to our instructions uh we should be able to run docker compose up now then we can open up local host in uh new window here and we're already logged in so it says to go to the product entities product and uh we'll go ahead and create a new one why not more beer it's gotten cheaper though maybe because it's a small and that says to check your browser's console and do document cookie actually like it on the bottom so it's a little confusing but this work document cookie and you can see it's using store one in this instance right in this example over here it says store two but uh so we're going to want to stop store one using docker here so not store two but store one and then we'll create a new entity stop that and uh we'll say what about a soda and that's only a couple dollars and we won't add an image there's a network error there oh it's trying to connect doctor for some reason I saw this earlier but I'm not sure why but here's the thing if you refresh it and then do it it didn't make me log in again right we're uh we're still trying to do some soda and it's cheap now it all works and so if we were to look at network and we look at the products and the cookies you can see now it's using store two so it didn't make me log in again there was some weird issue and I tried to create a new product right away um that it didn't actually work but refreshing the page work so um it's a pretty good solution works most of the time sorry it didn't work right there bad demo mat and uh so I'm going to give myself a pat on the back because you know I made it work without logging in again which proves that spring session and redis work quite nicely together and uh you can find the code for this on github you can see it was just updated yesterday and uh if you just wanted to clone the repo and try it out that way it's got all the steps to do that and then of course the blog post that describes everything and more details is available as well so if you like this video please follow me on twitter I'm at mrable my team is at octadev and we also have a youtube channel which you're probably watching this on right now so subscribe and smash that button and come back for more great content about spring boot spring and many other cool open source technologies thanks have a great day