Building a Spring Boot application in Jenkins (part 1 of microservice devops series)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi it's Tom Gregory here and welcome to this first video in this three-part video series where we'll be taking a micro service from inception to deployment using all the continuous integration best practices and in this first video we'll be building a spring boot application with tests and we'll be running it inside a Jenkins pipeline to make sure whether it's building correctly so let's get right into it spring boot is a framework for easily writing in java web applications and in our case we'll use it to create an api service and this is a common requirement of micro service architectures especially those that have a UI that communicates with a back-end API and just for fun we'll base this application around theme park rides and it will be geared towards doing basic get and create operations on theme park rides comprising a get api at slash ride to get all the rides the application knows about a get API slash ride slash ID to get details of a specific ride by ID and a post API at slash ride to add a new ride and in this application we'll be using a fairly simple spring Boot Model View controller type architecture and this normally looks something like this where you've got a consumer that's calling an API defined by a controller and then that calls a service where your business logic lives and then that call is a repository that handles communicating with the database the only difference in our case is that we're not going to have the service layer because we're not going to have any business logic today and if you want to follow along with this tutorial and write the code out yourself I encourage you to do so because this is going to be the best learning experience but if you want to a fast-track then you can get all the code at github comm /tk craigory slash spring poo api example and i'll put the link in the description and we'll be using the popular Gradle tool to build this application and if you don't have that installed just head over to grade order org slash releases and install the latest version here and if you're not familiar with Gradle and you want to learn more then check out my introduction to Gradle tutorial so now we're ready to get going and actually start writing some code and I'm going to be using the IntelliJ IDEA IDE today and I'm going to use this to actually create our Gradle project in the first place so all I need to do is say create new project Gradle it's going to be a Java project and click Next and I'm going to call this spring boot API example because it's a spring blue API example and then select finish and now IntelliJ very kindly has gone ahead and created us a project and we've got the build.gradle file we've got the Gradle wrapper scripts we've got the Settings Gradle and we've also got the empty source main Java resources and source tests Java and resources directories so we've got everything we need to get going first things first here we're going to configure the build script or the build up Gradle file and rather than writing this out from scratch I'm just going to paste in the code that we need and run through it so we've got a list of plugins here we've got the Java plug-in and then we've got to spring plugins that are required to bring a spring functionality to our build we've got spring dependency management and the spring framework boot plugins and also we have here the acción release plugin which is a way to add versioning to your project using tags and then we're relying on maven central and J Center repositories and in terms of dependencies we've got several spring boot dependencies and the nice thing about using the spring boot plugins with Gradle is that you don't have to specify the versions here so I can say I want spring boot starter web actuator data JPA and dev tools and it's automatically going to bring in the spring blue version defined up here which is two to five release and just as an FYI the start of web is going to allow us to create a web application with rest api's actuator is going to provide us some useful endpoints such as a health check data JPA is to do with communicating with the database and dev tools just means that when we're running the application and we rebuild it it's going to automatically restart with the new changes and here we've got the comm h2 database library which means that we're going to have an in-memory database running so when this application starts is going to be bringing up a database in memory for communication so obviously this isn't going to be what you really want to use in production because it's gonna disappear as soon as you restart your application but it's a good way to demo and we've got Lombok here which is an annotation processor which essentially means that we can reduce the amount of boilerplate code that we need by automatically generating things like get our methods for example and lastly here in our test implementation we've got spring boots start a test because we're going to be writing an integration test and next start we're going to create an entity class and this class is going to describe our theme park ride entity and we're going to create this in source main Java and I'm going to add a package here comm Tom Gregory and in that package we will insert a class called theme park ride and once again I'm just gonna paste in the code to save time and actually this should go into a package inside Tom Tom Gregory called entity let's just put that in there and then I'm going to auto format which is control Holt L to make it look a bit nicer so here's our entity and spring boot knows about entities when you annotate it with the entity annotation and here we've got three Lombok annotations - autumn actually generate gets a methods a two-string method and a no argument constructor and then we've got the fields within the theme-park ride entity and this is just a plain old Java object it's just got a load of fields and we're going to be able to create a theme-park ride entity and then we're going to be able to get the value of those fields so we've got an ID and that's annotated with ID and generated value so that we automatically will have an ID generated when we insert a new theme park ride and then we've got name description thrill factor and a vomit factor and the name and description have this not empty annotation which means that when we create a new theme park ride you're going to have to provide a non-empty name and description and lastly here we've got a constructor which takes in every field apart from the ID and does anyone remember this game from the 1990s and this is partly what's inspired me to make this API because I always thought it would be very cool to create a game about a theme park and next up here we're going to create a repository class which as I mentioned earlier is to do with communicating with the database and we're just going to create another package here and actually this is an interface and it's going to be cooled theme park ride repository and we're just going to paste in the code Auto format and the really nice thing about using the spring boot starter JPA library is that when you define your repository you really don't have to implement it and it's going to add all the code automatically for you so here we've got a class annotated with repository so spring boot knows what type of class this is and it extends crud repository and extending crud repository basically means that you get a whole load of methods for free so you can see here for example we've got save save you'll find by your ID vandal all these methods come for free but you can also add extra methods so here we've defined a fund by name method which takes in a name string and returns a list of theme park rides and the nice thing about this is that spring boot started later JPA is going to be using the name of the method find by name to match with the name field in our entity to know what to search on so it's going to be automatically generating all the SQL that it needs to now moving up to the higher levels of our application we're now going to add a controller class which we're going to put into a controller package as you probably guessed and this is going to be a Java class called theme park ride controller and once again I'm going to paste in the code Auto format and let's let's run through this here so we've got a class which is annotated with rest controllers so that spring buta knows what type of class this is and in the constructor here we're actually injecting a theme-park ride repository so this controller is going to be interacting with our repository that we just created and then we've got several methods we've got get rides get ride and crate ride and each of these corresponds to an API so the first one get rides is going to return all the rides that our theme park application knows about and it's a get request to slash ride and it produces Jason and all it does is cool the theme park repository dot find all method and it returns an iterable of theme park rides and these singular get ride methods a little bit more interesting here it's got a also get mapping it's a get request but in the path here we've got a slash ride slash ID so we've got a kind of placeholder ID that can be used down here in the method parameters we just annotate a method parameter with path variable long ID and that's going to match up so if we say slash ride slash one we're gonna get the ID one coming through as the parameter here and in this case we're going to do theme park ride repository dot find by ID which is going to get an optional type response and then we can say or else throw now what this means is that if the value of the optional is empty then it's going to throw this exception which is an exception returning not found with invalid ride ID and then the the ID there so it's just a little bit of exception handling in line and lastly we've got the post API so this uses the post mapping annotation to slash ride and here we have consumes as well as produces so we need to consume Jason and produce Jason so we're going to take in a JSON document to create the theme park ride and we're going to return that same JSON document and in the parameters here we have a theme park ride and this is the entity we defined earlier and that has the request body which that the Jason is going to be automatically mapped to this object and we have the valid annotation which means that spring boot is going to apply validation based on whatever validation annotations we have here like the not empty on the name and description and in the method body here we just have theme park ride repository dot save and the last class we really need here to get this application going is what's called in spring boot an application class and we'll just call this theme park application and I'll put it in a top-level package and this looks like this so it's a class with an annotation of spring boot application it has a main method so that we can actually just run this which does spring greet application run and we're gonna add in an extra beam here for a sample data so this is a way you can return this command line Runner which essentially runs some code when the application starts and the code we want to run is going to use the theme park ride repository to save three theme park rides that I thought I would add by default here we've got a rollercoaster a log flume and everyone's favorite teacups so now the codes done it's time to run this application and test it out and we can do that in two ways we can either right-click theme-park application and say run or we could likewise go to the Gradle panel over on the right-hand side here and go to tasks application and we could run the Gradle boot run task so let's do this one and now we can see that our application has started and one way that we can interact their application is using this tool here called postman and I'll put a link in the description for this I recommend using it as a nice way to send REST API calls and I've got a collection here and we've got a few API calls so the first one here is get all rides localhost:8080 slash ride see what happens and here we've got a response with our roller coaster log flume and teacups and let's do a post request and in the post request we need to remember to add the content type application Jason header and in the body here I've added a monorail ride jason body and let's just send this and in the response we get the same entity back but also with an ID this time and here we've got the get single ride api cool and we can say localhost 8080 slash slash ID and i'm just going to put in the ride ID for from the ride that we just added a success and interestingly let's just try ride ID / 5 to see our error handling is working correctly and yes here we go invalid ride ID 5 so that's all great but wouldn't it be nice if we didn't have to test this by hand so let's go ahead and add an integration test which is going to test our application all the way through from the API to the repository and database layers so back in IntelliJ here I'm just going to stop this application I'm going to close that panel and we're going to add a test in source test Java I'm gonna add a package um Tom Gregory and we're going to add a class in here theme park application IT for integration test and our paste in this code format and let's run through this so we've got a theme-park application ID annotated with spring runner spring boot test and auto configure mock MVC and these three annotations are required to bring up the spring context and also to configure this mock MVC object down here which we're going to be using to interact with our application so we've got several tests here the first one is get all rights this is annotated with tests and we use mock MVC to make a get request to slash ride we pass an accept header of application Jason and then once we have the response we can say that we've got an okay type response and likewise we've got similar for getting a single ride we've got an error scenario where we check that we have a is not found response status and we've also got a test for the post API where we're sending through some jason to the post slash ride with the content type the accept header and we're expecting an okay response so we can run this if we want to by going to verification here and running Gradle test and we've got a success and in this second part of the video we're going to be applying continuous integration to our spring boo application to ensure that whatever we check into the master branch is always built and tested and it's in a good state ready to be deployed into production and we're going to use the tool Jenkins for this purpose and we're going to set it up so that it's running inside a docker container on our local machine and a good DevOps philosophy that I like to use is that all infrastructure and configuration should be defined as code and I like to apply this also to Jenkins which means that we're going to be bootstrapping Jenkins that means that is gonna be minimal manual configuration that needs to be done via the UI and everything is provisioned on startup and this concept has been discussed in quite a lot of detail in my other video which is how to bootstrap Jenkins for disaster recovery and accountability so check that out if you're interested and we'll be building on top of the example from that video and you can find this at github comm /tk curry slash Jenkins demo so let's get engines up and running and to do that first off we're gonna clone that repo here and then I'm gonna CD into that directory and before we start this Jenkins instance make sure that you've stopped the spring Bou API example application and you've got nothing else running on port 8080 and all we need to do here now is run Gradle w build docker and docker run and this is going to build our application build our docker image and run that docker image and it goes without saying that you do need docker installed on your machine and I'm on Windows here and I'm using the git bash terminal and I'm using docker for Windows and now we can see that we've got an output that Jenkins is fully up and running not just up and running but fully up and running and what we need to do now is head over to localhost:8080 and here we've got our Jenkins instance and you can see automatically we've got a job here called C job and this is what I was talking about earlier with bootstrapping and this C job is part of the docker image it gets added in automatically and when we run this seed job what it's doing in the background is it's going off to a repository which is actually the repository that I just showed you and it's downloading that and it's looking inside one of the files in there called create jobs groovy and it's using that to create additional jobs and that's succeeded and we can see here that it's also created a job pipeline job and let's see what happens if we run this one and that's succeeded and this is a Jenkins pipeline and a Jenkins pipeline is just a kind of job in Jenkins where you have separate stages for different parts of your build so here we've got a build and a test stage and if we look in the job output by clicking on this blue circle next to the job number all this pipeline is really doing right now is just printing out build and printing out tests but the key takeaway here is that it's really easy to get an instance of Jenkins running and we can use a seed job inside our docker image to go off and grab a father then creates other jobs for example this pipeline job automatically and we're going to take this concept a bit further by adding a new pipeline for our theme park application and just to make it a bit clearer here here's a diagram which really explains how this setup works so in our Jenkins container that we just ran we have a seat job which we run and when we run this seat job it goes off and fetches a repository which in our case at the moment is the Jenkins demo repository that I have available on github and it gets the whole repository but importantly it's looking for the create jobs groovy and then Jenkins is using a plug-in called the Jenkins job deer cell which is a plug-in that has its own syntax and the create jobs groovy file is essentially using that syntax to generate a theme-park job and then when we run our theme-park job this is going to go off to the spring boo API example aka our theme park application clone that whole repository and then it's going to run our pipeline against that and this is going to be assemble and test and if you do want to write this all from scratch and this is that as I said the best learning experience you are going to need your own two repositories and obviously you can set this up for free on github yourself but you're going to need the equivalent of what I've got here so you need a repository for the spring boot API application aka the theme park application and you also need a repository for Jenkins demo which contains the create jobs script because we're going to be editing that very shortly so if you've got these two repositories than you were you're all good and in terms of the Jenkins demo repository what you're going to need to do is go into the project here and edit this seed job file and in this XML file which defines the seed job you're going to have to edit line 10 here where I'm pointing to my own Jenkins demo repo and if you want to use yours you'll have to paste in your github URL if you're not bothered about that and if you just want to get up and running what you can actually do is I provided a branch in Jenkins demo here so if we if we go and look at branches we've got a branch called theme park job so you can just clone my repository here and you can actually change the branches here on line 15 to thin pipe job and that's going to include the additional job that we need for running our spring boot application so the only change on this theme park job branch is inside this create job stock groovy file and we've added an additional job configuration and this is the Jenkins job dsl plugin syntax that I mentioned earlier and essentially you can define whatever pipeline jobs you want and we've called it a theme-park job and then you provide a git URL and in this case I'm pointing to my spring boot API example and the master branch and obviously if you've got your own repository that you've built up yourself during this tutorial then you need to change this to that repository location and it's important to point out here that this definition is not at the pipeline itself it's adding the job and it's referencing the pipeline from this repository location and what Jenkins is going to do is it automatically looks for a file called Jenkins file so what we'll have to do is go back to our spring boot API example and add a file in the root here called Jenkins file and then this is where we put our pipeline syntax so in our case we're going to be using the Jenkins declarative pipeline and the syntax is like this and we say agent any which means that it can run on the Jenkins master in terms of triggers we want to poll version control and this five stars means that we're going to be doing that every minute and then in terms of what stages we have we want two stages the first is to run the build and that includes the steps of Gradle w assemble which builds our application and secondly we want to run the tests and that is Gradle W test which is going to run that integration test that we wrote earlier so in my repository here that's all been pushed and I've got the Jenkins file available and obviously if you're doing your own repo then you need to push that Jenkins file and once all that's done we will go back to our Jenkins project and we're going to run greater W docker stop here which is going to stop any existing Jenkins instance and once again we're going to run a Gradle W build docker docker run and this is going to build our image with the change to our seed job where we pointed at the theme park job a branch of Jenkins demo and once again we've got a provision Jenkins instance and we'll run the seed job and now we've got a theme-park job as well as the pipeline job let's run this now and the first stage here is to check out the code which it's done in one second very nice and now it's building the code and now it's built the code it's running the tests and now the tests have also passed so this first pipeline run was successful so good job so there you have it we built a spring new application and we had it running in a bootstrap Jenkins instance fairly easily and obviously if you want to run this in a production setup you'll want your Jenkins to be highly available so if you're using AWS for example check out tools such as eks Amazon's kubernetes service or ECS Amazon's container service and in part two of this series we'll be looking at moving this spring with application into docker and also building that in Jenkins and then pushing it to a remote repository aka the docker hub so thanks a lot for watching if you like this video please hit the like button otherwise I'll see you in the next video and in other videos on Tom Gregory take so see you next time
Info
Channel: Tom Gregory Tech
Views: 19,191
Rating: 4.9176469 out of 5
Keywords: Spring Boot, Jenkins, continuous integration
Id: sCcuUMn1vdM
Channel Id: undefined
Length: 28min 16sec (1696 seconds)
Published: Wed Mar 25 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.