Spring Tips: the Spring Boot Build Plugin

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
iSpring fans welcome to another installment of spring tips in this installment we're gonna look at the spring boot maven plugin right so we're gonna build a new application here just a demo who cares it doesn't really matter what the application is just added into the web support I guess and everything else will just leave alone because we're not gonna forward you so much and spring itself as we are gonna on the on the plugin that we're gonna use to build it so let's open up our terminal and then open up the application here we are so let's it open up the ID just a regular maven built I could have chosen Gradle and the same things apply in the Gradle world but I'll leave that to you is a you know an exercise and documentation research to sort of see the analogs both all the things that we can talk about here apply equally though so we have the simple application and again it doesn't really matter the application itself doesn't actually matter we can create a rest controller for example and just say get mapping hi and string hi return hello there so there's my my basic Springwood application we have a build here alright this is a spring boot application it's a jar application the so-called fat jar and the the fat jar has the spring boot maven plugin and to understand and appreciate what this maven plugin does we should remove it first right so let go here and CD downloads demo maven clean install package even doesn't matter and we get compiled code to go to the target directory there we are if we look at the demo jar it's 12 kilobytes but I can't run it right it doesn't have a meta in Factory and it doesn't have a manifest file inside that meta entry and that manifest will tell the JVM what class to run what is the main class the class that has the public static void main method with that information the JVM can then run the code and you know start our application without that it's just a jar full of code that could be loaded in as a library into some other JVM process but that does not end of itself constitute a runnable jar you could run this if you specify a main class it manually as well right that's an option but you also have to specify the class path now the class path here is nowhere to be found I mean this whole target directory is 260 16 kilobytes but of course you know I've got embedded I've got Tomcat I've got spring boot start a web which brings in Tomcat which we know is at least a you know 10 megabytes right so that's clearly not everything I need to in the code I can copy the dependencies here I can use the main dependencies plugin maven dependencies copy dip end and C's and is that right let's see maven depend and see that dependencies oh no wonder none of it's working hahaha wrong folder let's see all right let's try that there we go so it was it was mavin dependency copied dependencies and you can see that that has copied all these different dependencies that I need for the application into the target directory for / CD target for slash and then there's a dependency directory and there you can see all the jars required to run this application everything that's inside of it or everything that's required to make this application work right so if I look at this directory itself is 18 megabytes there's our entire thing right and includes the web support and spinning and logging and all that other stuff right well hibernate validator yeah so all that is there okay so we have now a trivial application well if we wanted to run it we'd have to specify class path ourselves manually Java minus CP and then list all the classes that are rather list all the jars in the dependi directory and then give it the main main main class to run so we're pretty far away from useful that's why this maven plugin is so valuable this plugin first of all it it creates a meta in three and a manifest until spring where to find the enable code but it actually does a fair bit more than that you see it actually embeds all the other jars inside of the archive that gets built that's why if I run this code again may even clean package there we go there we are CD target I have here another jar and this jar is 14 Meg's right so that's the compressed version of all the library that we looked at before this jar is one self-contained thing right it needs only a JVM a JRE actually not even at JDI means a JRE and that's it I mean the the the the jar itself is self-contained so I can do Java - jar demo snapshot jar and that works because of the way that the plug-in configure everything let's take a look at the structure of the jar to see what I mean so demo ok actually I should have let me see if I Nautilus and we'll keep everything except for delete your thing except for that there are no we have here Jar xvf demo direct so now if we look at the directory output here you can see that the contents of the jar included boot in meta F and org ignore this jar of course because that's the original jar itself org if we look at the tree here org is the org are in org spring framework boot loader archive these are actual Java classes that get put in the root of our charms just like our normal compiled code would be had we not had the spring boot maven plugin so this is the code that the JVM is gonna actually run right and this is in the right right position it's right it's in the right place for the G of them to find it and load it normally and this code actually provides its own sort of class traffic provides its own class loader and its own idea of a jar file you can you can see here we have actually classes called a jar file this jar file class extends from the Java util jar jar file class it is a drop-in replacement for that jar class which is nice by the way because it means that tooling can use this mechanism if they want and it'll still work right but all this to say this code describes a custom class loader and a custom scheme for working with jars and that scheme supports nested jars you see here that we have in the buti'm directory we have the classes of our actual application itself the code that we wrote you know my little rest controller with hi and then the class path that supports that so this is the stuff that we'd have if we didn't you know if we weren't using maven plug-in this stuff would be at the root this this Lib directory under the end wouldn't be there right this Lib directory is all the class path it's the stuff that we saw in the dependency directory earlier when I ran that maven dependency copy dependencies command this is the class path required to support the application this is the application itself and and back in the org directory are this describes a hierarchy of code is designed to support loading and resolving and running the application with within the buti'm directory so it's a it's a fairly different scheme than one you may be used to you may have seen other things that attempt to get you the same effect right there's the uber plug-in and the shade plug-in uber Java plug-in in this way the shade plugin these are different maven plugins out there that attempt to give you self-contained jars and they're all very interesting but most of them we have found they try and explode the jars into one global namespace and that you know you're quickly run into a situation where you have conflicts right the the jars themselves they the contents of the jars are exploded into a global namespace and then so you get conflicts and you need to reconcile those conflicts and that gets tedious right you get you have things like the meta infrastructure where of course you know every jar is gonna have one of those and some constants in there or just they could and you have to reconcile you have to reconcile the difference there so that gets tedious very quickly and so we found that you know wasn't so hard to support doing it this way to actually support resolution of code within a jar as we are here and that's where that whole custom scheme does the only limitation to our custom scheme here is that if you're writing code that uses the system class loader that's not gonna work the way you expect it to work instead you should be using the context class loader right so if you are writing code that uses the class loader and you know about the class loader then you'll know what that means if you don't then great you're probably fine right you're not gonna need to worry about it most libraries most frameworks use the context class loader anyway so this is not a not a problem that you run into except in very exceptional circumstances but other than that this will work right this is actually a self-contained jar this star is not something you want to put on the class path of other jars though of other applications it you know you by building it in this way you make it harder for the JVM to load it the library doesn't work they do the way you'd expect but that's fine we're trying to build an application not as self-contained library so we have everything within the application and that's fine you know the applications now like you said we we can we can do job - jar demo dot snapshot jar we can override properties for example the port I could say export server port dossier export server underscore port equals 8020 and then do each other- jar demo and the application now spins up on port 80 20 right so you can see that we're able to change the default behavior I could have a property file here I could say echo server the port equals a t10 application properties and then just you know in the same directory and open this up again close this one and open that one up and you can see here I've got cat application up properties and I've got the jar so Java - jar demo that jar and I said I wanted to run to port 80 10 and that puppy file and there we are so I'm able to change the default behavior of the application I'm able to build the self-contained application all I need to do is manage starting and stopping and restarting and status in the application I need to tail the logs and so on so one of the common reasons that people use application servers like Tomcat right which is the most obliquity by far an application server in the java community and ecosystem the more the reasons that people use it is because they want to have the lifecycle management right the life cycle of the application itself to start the stop the log following etc so you have to reinvent that in this case in this case right is so far we don't have most of that capability and additionally there's no easy way to manage this you have to have to do that you have to do the admittedly not so painful but still tedious work of installing this as a service in your operating system if you're running this in a production environment it's more than likely gonna be some sort of UNIX flavor so a Linux and so you're gonna want to install this as a service so that it gets run when the application weathering that when the environment starts up and it's gonna be it's gonna be destroyed when the environment is itself destroyed so all of it is a kind of left as an exercise for the reader and that's you're using an application server that said we're not using an application server we have the embedded web server so we need to solve that problem ourselves and that's easy to do with the spin boot configuration here so there's a lot of configuration options here for the spring boot maven plugin right you can specify things like what Java agents you want to run which custom classes directory you want to run you know what artifacts you want to include or exclude do you want to specify JMX crit in you know you don't sort of specify gem X properties the you know lots of different things you can do here in the maven plugin for the spring boot plugin but for what we care about is whether the jar is executive or not so we're gonna make it executive or equals true by default it's a executive jar but that's not quite the same thing as what we're talking right here it's a what we're building now is a a a new kind of executive jar so maven clean Anne's main clean package all right mmm seedy target now same thing as before basically 14 Meg's but this is different right so less so what I just did is I did less demo zero one snapshot jar and I'm greeted with a shell script and the shell script is actually the first it's the header if it's the first part of the of the jar archive and the the header the the the shell script does a lot of things for you it actually does a lot of stuff for you and um it installs a PID directory you know it installs a folder to store a paid file where you can see the status of the application it gets a folder it you know it manages logs it manages permissions for the application itself it gives you functions that you can use to see if the application is running you can say P it you know it's running for example you can you know there's a lot of support here I don't expect you to read all of this yourself but suffice it to say there's a lot of functionality for starting and stopping and status seeing and for stopping and force reloading and running the application you can see all that here as commands right so these commands are all supported they're very useful and the reason they're useful is because you can use these in conjunction with an ad or system you know V style initialization so the script is meant the script the the script is actually run before the JVM runs the jar with this what the script does is it actually loads the jar itself right this coat this the script gets run by the operating system it then loads itself it reads its own file and loads the jar and the jar of course is the binary data that you see here as gobbledygook on my screen is all the contents of the jar kind of encoded in that and that shell script and to understand how that works you have to consider how the operating system reads files right the operating system reads of a program the memory starting from the top and going to the EOF the end of file marker right and that's just sort of how most UNIX operating systems work the JVM contrary to the operating system weeds it's our archives and applications and reverse it reads from the end of the archive until the beginning of file marker well of course there's no reason that those two things have to agree there's no reason at the beginning of the file for the operating system has to line up with the beginning of the archive for the JVM in fact you can do some very interesting things if you keep those things separate that's what we're doing here our shell script has an end-of-file marker which the operating system then reads and the shell script then reads itself and gives it you know it gives its own contents to the JVM it does so by reading from the end of the shell script which is the jar to the beginning of the file marker which is that of course you know right after the shell script it's the first byte right after the shell script it's you know there's a discrepancy there but that works now the benefit of this is of course I can do this demo all right I didn't have to say Java - char I just executed the program like an executive shell script on my operating system I still need a JVM mind you but I just I have that ability already and I can now use this within knit D and system D so a nip T spring boot maven plugin okay so you say exactly what it goes true here's a calming little Gradle configuration and you can now use this with an ad or system genie right here so you they go sudo LLNS my jar and it said it cetera and it D my app and then once that's done you can say service my apps start for example so you get to you get the ability to manage the application as a service on the operating system just like my sequel or any other thing that you're running as a daemon in the background and of course you have logs written to var log app name and there's actually a paid that gets managed for you by the operating system by the script itself as well and you can tell the operating system to started automatically using update our CD my up default priority etcetera right so you know lots of things you can do here you can also look at the documentation for information on how to secure it right so that a it only when it runs in a secure protective process and with a certain you know protective permissions a lot of options right so I could you to prove that at your own measure one thing I want to really mmm you know make sure in the sense that you can change everything right including the shell script itself you can provide your own custom shell script and you can even copy ours and just you know change it a little bit you can provide a custom shell script here and provide your own embedded lunch script and that long script can do whatever you want now maybe you you want to override just the properties that are used inside of our large script that's fine as well you can do that here so a lot of options I encourage you to prove that and to sort of explore that later on but for our purposes I think that's a good enough introduction the nice thing about this char is that it's self-contained I as I say it's a it's a self-contained demo application and we have we have got one endpoint here we have one rest controller we have three lines of code and that three lines of code required eighteen megabytes in space might seem a little disproportionate but you do get benefits as we've just seen you get operational benefits from having to it is co-locate all the libraries in the application archive the binary itself that said things could be more compact I agree they could be a little more svelte a little bit more convenient and this is only a problem if you start archiving these these binaries and something like like your Nexus repository artifactory there you might not want to store 18 megabytes every single time right this is just a trivial application I haven't even begun to add anything else to it so in this case you might enjoy the fact that you can use the thin launcher now the thin mantra is a custom maven it's a custom spring boot maven plugin layout layout is an extension plane for the spring boot maven plug-in that you can override and there's a few default layouts this jar there's dot wire and then there's a new one that the good doctor sire who is the co-founder of both spring boot and spring cloud has created this is called the spring boot thin launcher it's a you know not officially part of spring boot itself but it's very very useful already and you can find the cohere desire spring boot thin mantra the code is fairly simple to get going so here we're gonna win it we're gonna override the spring boot plugin here we're gonna add this bit here to our spring boot plugin okay oops don't need this and don't need that and we need the version it's one not oh six I think yeah 1.6 release so they're back there's a custom version and our custom maven plugin with its own custom spring boots in layout right but then layout has everything we need to to run the application but with the thin boot layout does it actually it installs in the in the binary the ability to resolve its own class path using maven using a you know the same maven dependency management mechanism so here maven clean package CD target do you - HS demo oops what did i do there do you mind chase okay 20 kilobytes right so it's a little larger than we saw in the very first time when we had no plugin at all but it's still trivially small and if we run this application everything will still work so Java - jarred demo of snapshot jar there we are you can see it's you know the application spun up as quickly as we'd expect except that it's resolving its class path dynamically if right now right now it's looking in the local em - you know my local m2 repository directory and it's finding all the libraries that are in that that repository directory and it's you know loading those as it needs to dynamically I can tell it to load those dependencies in a separate class packed I can say job up - thin dot root is it I think and it'll just be right Lib Lib I'm gonna say yeah drop my star thin Dutch I think it's been that route I say that is CV Lib you can see that when I said thin that root equals Lib it created a directory called Lib there in the repository directory we see that it has created a class path it has created a maven repository basically that has all the artifacts needed to run this application so it used the maven dependency resolution mechanism when it started up the application and it resolved all the dependencies and put it in that jar now of course if I run the same command again you know with that same exact invocation it won't need to resolve them right there cached right that's what it happened the very first time it ran this I ran that command relative to the local m2 a repository directory and then it just worked right so here I'm saying that root equals Lib job - jar demo done whatever Oh see you target okay so again doesn't have to resolve anything now consider an operating system where you have no dependencies in the on the class path you have nothing on the local machine nothing on local m2 nothing anywhere right then you would need to have internet connection right so the unit you need to download it right obviously this is not going to work without its dependencies so that adds to the startup time hopefully you've got fast download capabilities no doubt you do in a production data center but that's a cost that you have to be prepared to pay so you can either have it pre cached you can actually stage your your usage of the libraries the dependencies you can actually run a pre-flight if you will in which case you can get all the libraries downloaded and then cache them as you would write for example here so Java - teeth in that root equals jar our equals here and you know like that this will download everything to that that directory you could do a dry run by specifying a property here fin dry run equals true and that will actually download the dependencies for you and not start the code so that you get the best of both worlds you can download everything and then start the application guaranteeing that it's gonna work when you do start it right and the benefit of that is that of course you can you can have all the defenses you need to run the application but you don't have to store the built application with all the dependencies included in the artifact or or you know Nexus repository you can have it only in the container itself that needs it right and or you could just do everything you know sort of dynamically you could choose the thinnest smallest container that you need for your operating system and then just deploy the tiny thin jar and let it download the the the dependency the classpath that you need for that application that will work just fine as long as your your platform whatever technology using for cloud computing doesn't have a requirement for timeouts right hopefully you don't need to long to download all those dependencies if you can do it within that time out then great as it happens this trivial spring boot application that I've just built here is small enough that and quick enough that it will download and work just fine on something like cloud foundry right so if I if I were to push the application here with it as you can see here CF push might be my my app minus P target demo jar and then to specify a build pack this will actually stage the jars before the applications tries to start up so it's a it inserts itself into phase in the cloud for any life stuck on the cloud for the app lifecycle before the application starts up I downloads all the jars and then it does job my start and so you're not again you're not counting against that that time out but even if I were just to do CF push my app specifying this jar and ignoring the build back you know for for this trivial application that would absolutely work right it's small enough that I could get that done in the time before the the time that applies right so you can either use a custom build pack to get around that or you can just you know if it's small enough it'll just fit and you might not even have that problem who knows I mean the point is this is a good option and there's very few cases where it's gonna be a problem the only places I can think of where you might have problems is if you're running against a timeout when you start up right because it's going to have to do all this when the program gets run I want to when it starts up so keep that in mind and you know I like the thin approach I think it's like the best of both worlds you can you can do interesting things too because remember the the class path is being provided external to the application if you wanted to you can actually provide a thinned up properties file that then contains its own dependency manifest right that's actually what's happening here if you look at this char let me see you open this again and I will grab only that delete that I'll say unzip there you go see if you look at the directory here you can see the directory contains the Menem code it contains a thin jar wrapper class which in turn is tailgating to this dim application and to your maven pom it's using the maven pom that's in the archive to resolve the dependencies but you can provide those dependencies in a custom format as well you can provide your custom preppy file so thin dot properties right so here it says dependencies spring boots starter web equals org spring framework boot spring boot start a web right so here's yeah you an externalized cut you know custom dependencies and you can use that as the class path you could overwrite the class path that the the application has inside of it so if you want to upgrade spring mood and spring cloud but nothing else you know you want to change the dependency version for example um you could do that by overriding the bomb's section in our property so here you'd say BMS that's the spring boot maven bombs a bill of material dependencies bombs that spring boot dependencies equals Oryx bring free mcboot spring boot dependencies 1.5 times 6 really so here it would be forcibly upgrading the awareness of a particular penalty 21.5 dot six everything that uses the spring boot bomb would which in a spring wood application is everything would now be pinned to win dot 5.6 you don't have to recompile the code now do I recommend doing this in production code no of course not I mean you should definitely absolutely go through the regression test and auditing and all this stuff but it can be very convenient in a pinch if you need to do that and you know you can we try our best to keep things saying so that they work backwards and backwards and forward compatible you know obviously we don't this with a a giant you know 1.56 to 23.0 you know bump or something like that but you would you would be what you'd be better off if you knew about that if you had a security vulnerability that you need to get patched right now something like that right that's just a convenience so you have a lot of options here right a lot of options to run your Springwood application and again we've talked into I've talked about servlet container options right in previous in a previous spring tip so that's not what we're talking about here we're talking about the spring boot maven plugin and a number of different strategies for running them also of note is that the so-called fat jar thing that I showed you that can be used with a bar the first approach that we showed you with the maven plug-in without it being executive you can use that with a dot waar as well that actually gets you the best of both worlds you can deploy that into a server container environment and also do java - jar my dot wah right and that actually get to UM you know something at work in both environments so a lot of options here a lot of flexibility now one thing that isn't there yet that I'd love to see especially in light of day are he9 Java 9 is the ability to have for this for the shell script that we saw earlier to download a JDK I'm modern GDK and j 9i I think it's a perfect vehicle for that it provides modularity and that modularity applies mostly to the JVM itself you can decompose the JVM into smaller modules that you can then repackage and whatever range but you want and so you could for example build a JRE that doesn't have the code for korba well good you know we weren't applying and using that in later application so we can cut that out you can have a custom redistributable JRE and I think Oracle even signals that they expect applications to to ship the JVM with their they expect Java 9 the job and I'm Jerry to be shipped to the application so so as to make it easier for developers to get a consistent experience right especially now that they're gonna be releasing a lots of new games every every what is it six months something that they're gonna do schemer it's a twice a year something like that so it could be very valuable to paint your application to a particular JVM as opposed to relying on whatever resident JVM is on the operating system so we'll see and I think that would be a interesting extension you could do that of course you could already since you can control the launch script you can provide you own Jerry resolution mechanisms we could actually download your own as opposed to the Java you know Java command detection logic that's in their launch script right now so okay so with that we've looked at the default behavior of spring boot and the maven plugin without the maven plugin we get to a jar we looked at how you could resolve the classpath if you didn't have that plug and we looked at the spring boot maven plugin and saw what the default behavior gets you we looked at some of the configuration options and saw that you can change a good deal of things about the the resulting fat jar using the maven plugin we also looked at the executive all option right in the executive launch script that you get in UNIX operating systems and how that allows you to run the application in system D and init.d style environments and then we finally looked at the one of many possible layouts this one is called the thin layout that applies to the spring boot maven plugin this is a project from Dave sired dr. Dave sire when I spring team members and we then talked about some of these shoes you may have if you use this approach and some of the virtues you may have if you use this approach so with that thanks so much for watching and we'll see you next time you
Info
Channel: SpringDeveloper
Views: 8,057
Rating: undefined out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud, maven, gradle
Id: arOqTOEtAVA
Channel Id: undefined
Length: 33min 52sec (2032 seconds)
Published: Wed Oct 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.