 Hello and welcome to another Dev Nation Live. We're coming at you live in my case from Wake Forest area You know outside of North Carolina, Raleigh, North Carolina James. Where are you at today? Today Burr? I'm in Orlando, Florida Fantastic, so we're actually actually both at home normally I'm out traveling about when we do all these live sessions and so you have a really great topic for us today I know a lot of people out here who've been watching this session either watching it live now We'll watch the recording have been loving the fat jar fat jar seem to be all the rage these days And which is kind of interesting to me, you know, if you think about it, you know Would you actually put that that jar on the cover of the magazine? I don't know So let's talk about fat jars and so James take it away. All right, great. Thanks Burr. So I'm gonna go ahead and share my screen I got very minimal amount of slides. I know we're gonna try and limit ourselves here to our time So I don't want to take up too much here So hopefully you see my screen. We're good Yep, very good. All right. Great. So hello everyone. My name is James Faulk Norris Burr mentioned I'm a Technical marketing manager for JBoss middleware within Red Hat today. I want to talk to you about fat jars we're gonna look at a couple of different technologies and and Explain kind of what's going on here with that jar. So let's just go ahead and dive right in So you've all probably heard of fat jars if you're here Drop wizard is a is a packaging and a framework that started it in around 2011 a fat jar is essentially a Jar file a Java archive file that contains both your application its dependencies and all of the things need to run it With Java dash jar. So they're they're very easy to understand. They're easily portable You can run them very easily Java dash jar You can set up your IDE to run them very easily and the dependencies that your app requires are resolved at build time Not in production. That's kind of a key tenant of fat jars Everyone supports as I mentioned drop wizard of first also. We're gonna look at spring boot Wildfly swarm as well as vertex today Again, everything's in one jar which means in the world of Linux containers and container orchestration. Everything is in one Container layer When you rebuild your jar when you make a one-line change to your application add no dependencies the entire fat jars rebuilt and restuffed into that Layer Linux container layer and then pushed out to your production cluster. So you can imagine the complexities that come along with that and the cost of that so if you look at the relative sizes of a hello world Fat jar with a single 500 kilobyte library the Joe to time library Comparing them between the different technologies you can see it clearly wildfire swarm is the winner here Produces the largest jar largest fat jar file followed by spring boot and drop wizard around 15 megabytes and then finally The the winner here vertex at a very small seven megabytes That's actually grown from four megabytes about six months ago to the latest version. It's grown a bit So there are any more features and as you can imagine that that makes things grow So when you push that 45 megabyte Fat jar file to a new Linux container image layer and then out to your network You can imagine the cost of transferring that over the network storing it in a docker registry and spinning up nodes and and Containers within your cluster the cost gets starts to go high. This is a hello world application if you look at a Larger application may be a real world application instead of hello world They can grow up to around 200 megabytes for the code plus dependencies So the size of the of the libraries the frameworks you're using whether you're using wildfire swarm or spring boot Or what have you start to become less important the more important thing is the overall size of that application as it grows So that can present issues as I mentioned HubSpot Experienced this quite a bit. They wrote a nice blog post about a year and a half ago You can look at exactly what they're doing So they had around the 200 or 180 to 200 megabyte fat jar and they were generating tons and tons of build artifacts per day Rebuilding and redeploying out the production and they quickly faced that that that problem that that wall where you are Transferring so many files and storing so much on disk that their AWS bill started to creep up and up and up and up and up And they they decided to look for an alternative. So we're gonna go through some alternatives today Also in the Java EE world If you're a Java EE developer, you've actually been doing the alternative, which is a thin jar or thin war file Since the beginning of Java EE Adam BN is a proponent of thin wars Deploying to application servers You don't necessarily need a fat jar to get the same kind of benefits that you that you've been able to get for a decade or more Using Java EE and app servers So the only issue with that is the traditional Java EE container Contains a number of components. First of all, it contains an operating system. They also contains the JDK the runtime You also have some negligibly sized build scripts, but then you also have your fat jar plus the app plus the app server itself So in a in a Linux container image, you can see the problem here, right? Every time you make one line change to your application at a minimum, you're going to be pushing 200 mega 209 megabytes with this particular image Obviously, we've we've moved further along from this so going from this to say spring boot So with a spring boot fat jar and a minimized operating system namely help line Linux in this case You still have the hundred megabytes of your JDK, but now the application is only 14 megabytes plus the dependencies that it needs So it's a much more attractive option, especially when you need to make a one-line change now you're only pushing 14 megabytes instead of 118 megabytes so awesome Wildfire swarm is a has a very similar Layout here and at Linux container image. We also have a small operating system small JDK And then the application sits on top of that so the point here is that if you're able to split up your application and and put boundaries between the different layers and have the layers that change Quickly at the top and the layers that don't change very often like your library dependencies or your application server Or whatever runtime you're using Lower in a lower layer then when you make a change only the upper laders get changed and the the caching mechanism within Docker Linux containers takes over and can minimize the amount of change necessary to actually push that updated container out of production So just a brief Level set here on terminology. So we all know what fat jar means. That's everything in order to run the application the thin Variant is where you remove the runtime the application runtime, whether it's a Java e app server or tomcat or jetty or some other Runtime and only have the application plus its dependencies in the thin layer then Going down further we get to the skinny layer. This is where you remove the application dependencies in addition to the Application runtime and you're left with only the things that you literally type into your IDE when you're developing very very small But again must be deployed to a something that can run it. They don't they don't run on their own. They're not fat jars Okay, so let's do a demo. So I've got some some code prepared here You can see the the URL here to my github repository if you want to Check it out later. He's checking out the recording. So we'll switch over to My IDE here and I have a number of different projects. So I'm going to demonstrate some of the tech techniques you can use to to Make your fat jars lose a bit of weight. So we'll start with spring boot So I have a simple spring boot application here. It's got a Spring boot application Main class here. I have a simple property and then I have a controller which essentially exposes a restful endpoint to the spring Boot application. So I'll go ahead and build that and let's take a look at what happened. So maven clean package I'll go ahead and build the the spring boot fat jar and if I look at what the Result is that is I can see my spring boot fat jars here sitting around 14 megabytes. I can actually run that Java that's jar That's and it will fire up spring boot. I'll switch over to another terminal here and hit it with my URL here It's not the right one, so I go ahead and remove that so it's API slash greeting So this is a sample application I'm using for all of the different run top different frameworks here So that's my spring boot fat jar pretty simple to understand about 14 megabytes So let's move over to wild fly swarm. So the same kind of deal here maven clean package And build that wild fly swarm application again That is also a very simple application uses these jacks RS to expose a single restful endpoint And if I look at my result here, I can see I Fat jar is sitting here Where's it's here 45 megabytes? So you can go ahead and run that Very similarly to to spring boot it'll start up and I'll be able to hit that with my same URL here And I get my handle. Hello world message. So let's take a look briefly at what that looks like inside the jar file So we make this a bit bigger Let's just like target targets You see what what wild fly swarm did is essentially package the application The application is actually way up here at the top Well, it's somewhere up here. It based basically the applications inside of there as well as a maven repository Maven has a number of ways of doing dependency Resolution so packaging the dependencies as an internal Maven repository makes a lot of sense because you can then use those libraries to automatically link Applications in application dependencies into the application itself. So and then there's also some bootstrap code in here But it's essentially a an opaque Fat jar file if we look at spring boot fat jar file. So let's take a look at that targets Just comparing these this is the last time we're gonna look under the hood here So here's my spring boot fat jar very similar. It has a number of boot bootable or sorry boot Bootstrap libraries as well as the libraries for the application itself There may be some libraries in here I could potentially remove with some maven magic. Maybe my application doesn't use I don't know JPA or something so I don't need some of the libraries in there, but that's the the Fat jar spring application. So okay, so that's fun. So let's do a couple more here. So let's go to verdicts The verdicts is interesting. It uses a what we call the Maven shade plug-in. So Maven clean package And it essentially does the same thing it takes the dependencies takes the application itself packages it into a single jar file And then you can run it if we take a look at that one here Dar they're very similar Got a bunch of stuff in here all in in this case. It's all kind of in a single flat class path Thanks to the Maven shape plug-in all the dependencies are there and I can go ahead and run that I won't run that to save some time, but it'll essentially Open up a single restful endpoint as well. Okay, last one here for fatness drop wizard. So drop wizard was the first one to do Dars, so I'll go ahead and do that one. That one also uses the shade plug-in to take all the dependencies of the application and Inject them into the runnable jar file, which you can see here Forget slash Our jar so you can see here's my runnable jar file. I can actually run that one as well with Java dash jar So you've probably all done this In the past I'll open up that one and then you can go ahead and hit that one and then you've got your drop wizard fat jar running So fat jars are cool very easy to understand, but they can grow inside as time goes on So what we want to do is look at some alternatives and this is the point of this this particular hangout here So let's start with spring boot. So for spring boots There is an experimental plug-in in spring boot written by the one of the founders of spring boots Called the spring boot thin launcher so you can see in my in my palm file here I'm using this particular plug-in called the spring boot thin maven plug-in And this is essentially going to do the work of separating the application from its dependencies So if I go ahead and build this same that same exact application Go ahead and build that one. We'll take a look what it does I'm here Okay, so that's done. So let's see what happened So it actually created this directory under the target directory into the build directory called thin So I go into thin roots. Here is my application This is my thin jar file and then the repository is again a maven repository very similar to some wildfire swarm It creates a separate maven repository Which you can then package separately in separate Linux container images So but without even packaging it I can simply run it here and it will find this repository in the local directory And then be able to boot up boot itself up. So now I have my running thin spring boot jar But the magic comes when it's time to package because we're all using docker and Linux containers now. So let's go ahead and package that up. So I have a very simple docker file here So the docker file adds the this thin repository this maven repository and then my thin jar file into separate layers Notice they're in two separate lines. So if I go ahead and docker build on jhf spring Latest dot Let's go ahead and package my application. You'll notice in in the process of building and actually Realize that the repository hasn't changed. I haven't actually touched that repository in a couple of months So it's able to use the cached version of that repository and only the application is is not cached So if I look at the history look at the layers in this Jar file I can see if I look at Spring latest See the top the topmost layer is what contains my application It's only 11 kilobytes much better than the 14 megabytes From a spring boot fat jar file and then you can see the site in the next layer down is the repository Which is around 25 megabytes, but it hasn't been touched. So it was able to reuse that cache So which is awesome. So now if I can just run this Docker Suppose the port spring made us run So we'll run this in a docker Container started up and then I can hit that as well And I can see my thin jars still the same exact message but coming out of the Runnable docker container that I created with my different layers instead of a single fat jar and single layer So that's cool. So Let's see what's next. So let's take a look at wild flies swarm and what that it does so wild flies swarm is an interesting I have an interesting property Let's see fat and so wild flies swarm when you build it actually builds both the Fat jar, which is here as well as the thin war file, which is here the thin war files only contains the application Plus its direct dependency. So if we look at this file wait We can see it contains my application here, which is very small about two kilobytes and then also contains the Direct dependency, which is this time library. So I can do a very similar thing that I did with With with spring boot and you know create separate layers for those but what I wanted to talk about is this Application dependency here. So wild flies swarm is based on the upstream wild fly application server It has a project or functionality in it called J boss modules This is for doing class loader isolation and being able to load multiple applications with the same app server in different contexts. So In order to do this you need to package both your application plus its dependencies as a single war file So that it can put them both on the same class path And they don't conflict and you're able to use multiple versions of the same library in different applications without having conflict So if you with wild flies swarm in order to create this Skinny wharf or skinny approach to packaging we want to remove that because this this Thin jar thin war file while it's 500 megabytes or 500 kilobytes still not as small as we can get So but before I do that, I just want to mention that that thin Warfile can be deployed to any app server. So I'll go ahead and start up while fly here I have while fly running on my local machine here, and I'm going to go ahead and copy this The thin war file Just to demonstrate to the thinness here. I'll copy this to the Standalone deployments directory of while fly and you'll see I'll go ahead and deploy that and it's running on port 9000 So if I hit it on port 9000 E slash while fly thin war running in a full fledged app server in this case while fly Running locally on my machine here. So that's the thinness of while fly swarm So let's let's do one more thin and then we'll move on to skinny and then we'll be done here So let's go to vertex. So vertex has a concept called verticals and these are kind of independently deployable pieces of business logic that you can deploy out to a a Vertex runtime so in this case, I'll do maven clean package to build the thin version of the vertex application Take a look at what happened there Target star. Here's my thin Vertical only 624k because it includes that same time library that I mentioned earlier so in order to build this as a Separate layer in Docker you will use a another Docker file. So just take a look at this real quick. It's Finds long here. I'm essentially using a pre-built vertex 3 runtime It's to have to supply the runtime and then simply adding my vertical to the verticals home directory And then I can run that so if I don't want to build that here docker build dash Tag J7 vertex latest Docker build Then build my thin vertex application and you can see Docker history latest You know my top layer here is my very thin Vertex vertical about 630k and then the rest of it is vertex itself, which is represented in these other files here So I can go ahead and run that Hit that real quick from my same And here's my vertex thin jar thin or vertical running in my Docker Container here. So I was able to package that so then when I make a one-line change So if I do I'll go ahead and make a one-line change vertex thin in my source directory Here's my simple app. Hello update And build that clean package and then rebuild the docker image You can see it was able to use the cache for everything except for the Small vertical here and I can run that again and it would do exactly the same thing. So when I make a one-line change I no longer touch my six megabyte that jar now. I'm touching my 500 kilobyte thin jar Okay, so the last bit. I want to talk about is a wildfire swarm again So we'll go like a wildfire swarm and we remember that Jota time library was which is about 500 kilobytes Not a big deal for 500k But as your application is becomes a real-world application you can grow like HubSpot found up to around 200 megabytes So it's important to separate those out with wildfire swarm and it's it's inheritance from wildfire the the way you do that is through the Jbos module system you and and what we call fractions So wildfire swarm has this concept of fractions where you it's kind of a packaging mechanism where you can package up functionality that only you need and then Include that in your build and make your applications much smaller and leaner and less less code and less less Croft so in order to do that you need to build the This Jota time library as a fraction. So I have a Project here which will do exactly that so maven clean package and then install it which will install it to my local maven repository I can then include that fraction in my war file right in my my building application by doing a using Declaration so if I look at the palm file for this final project here, you can see in here I'm actually including a dependency on my fraction as opposed to including a direct dependency on the application itself So I'll go ahead and build that build my skinny Char file and then I'll be able to deploy that so what happened when I built that is it created what we call a hollow Application server is essentially the runtime of Wildfire and wildfire swarm but without the application itself So I can Java dash jar that but that doesn't make much sense because the application isn't there So I need to mention the application I want to deploy which is this super thin application 249 kilobytes Or sorry 249 bytes so about 2k so if I can run that Essentially will act much like a traditional Java eapp server where you can deploy applications into it I'm have my application up and running now. I can hit it and I have seen my skinny jar file what's more interesting is I Have two applications that I want to run so I can I have another application that I've built so I'll go to my skinny to Target skinny wait to war so I can run two applications with the same exact runtime without any modification whatsoever and It's kind of interesting. We're kind of going back to the where you're deploying multiple applications to a single app server In this case, we're doing somewhat similar But the difference is we're able to package those dependencies of those two applications separately not only keep them in separate Docker container layers, but also check them into our Repository artifact repository whether it's nexus or jfrog or something like that. So now I have my two applications I have my original application and I have my other applications sitting on a Separate web context here. So I have these two applications running with the same runtime So then I can essentially this allows companies To standardize on the set of dependencies that their application developers are able to use a lot of times We talk about fat jars being very simple for the developer and that's absolutely true But it also gives you great power and with great power comes great responsibility And so companies generally try to limit that responsibility to avoid issues in production. So that's the That's the skinny Docker sorry skinny application for wildfire swarm one last thing if I wanted to package this as a As a Docker image, I have a Docker file here. I believe So let's take a look at this Docker file. So the soccer file does exactly the same thing It packages the hollow jar of wildfire swarm into one layer And then it packages the skinny application into another so I can do a Docker build that Docker build dash T It is We go ahead and package that application up if I then make a single line change again Very similar to what I did earlier. So hello update I can spell Right package that Now when I build when I rebuild my my Linux container image, everything should be cached and the only thing will be touched will be that That two kilobyte in it cat layer at the end, which is very very small So now a one-line change means two kilo or two kilobytes of change not 45 megabytes of change So very similar to us to spring boot Okay, so again all this code is on Docker or sorry on github if you want to try these things out if you're watching the replay I know I went a bit fast, but Hopefully you get the idea. So let's go back. I got a couple more slides here. So kind of a summary slide So the end result here is that there are various Mechanisms and techniques you can use to take a fat jar that's growing out of out of you know Above the size that you're that you really want And break that up into into separate layers so that it's much easier to deploy those images this container images out to your To your production clusters. So obviously with fat the fat jar approach. Everybody's everybody supports that it's kind of clear The thin jar where you have thin thin jar or thin war where you have your application separated from the from the runtime are Possible to do with all of the technologies In the spring boot case, we have the spring boot thin launcher While fly swarm has the in a concept of thinness via Jolly EE in the traditional war file deployment mechanism Vertex is it's possible to do that via maven, which I showed Drop wizard you can also do thin using drop wizard. I didn't have time to to attempt that But I did find a blog post here. There's a link that you can visit later on I think I might have it in the slides here of a community member who was able to do that with with vertex and then For for skinny hollow support where you have the ultimate kind of smallest possible unit of Of deployment or smallest possible using of your container layer spring boot has a There's a mechanism written by another community member called a docker prep plugin Which will actually split your application It's dependencies and the runtime into three separate layers and give you a lot of control over that So you can do it with spring boot via that while fly swarm as we mentioned has the concept of fractions where you can Extract all the dependencies of your app Into separate fractions and then be able to re reuse those in your corporate Developer pipeline a vertex and drop wizard. I Believe you can do this as well. I haven't tried it But there's a project out there called capsule capsule IO Which is from what I what I've seen in the last few days of kind of a Swiss army knife of Java or JVM applications And you can do a whole lot of stuff with that. So You're able to I believe you're able to split up the application into separate layers as well I haven't had time to play with that But if you're interested or if you know of that or if you're familiar with this project and have some information About it feel free to share it with me I'd love to see it and see what you can do with with vertex and drop wizard and probably any other JVM technology Okay, so last slide here kind of a summary slide. So fat jars is definitely not a anti fat jar approach or anti fat jar Presentation here they work really well in many cases and they're super developer friendly as they start to grow and grow Which they never will be inevitably will if they if they exceed a certain boundary that you have in mind Take a look at some of the technologies for doing thin deployments and separating them into separate Linux container images it makes a lot of sense, especially when you're at production at scale To be able to separate those out and minimize the change that goes out whenever you make a change and then skinny hollow is kind of a Super set of that. It's highly efficient It really separates everything out and you can have a lot of control over that the container layers that you're building and Putting the most frequently changing layers at the top with your dependencies below But of course it adds an initial complexity to kind of set that up and get your pipelines up and running Consistently along with your unit tests and and packaging Okay, so I think I'm done Burr Questions totally awesome. We do have some questions if you would throw up the URL to the github while we're taking some questions also One question on Vertex apps around making thin Vertex apps. Have you seen anyone do it with Gradle? I know Gradle supported by default, but I don't know about that specific thinning aspect. Yeah, so I have not done it with Gradle personally. I use generally on the Maven guy, but the capsule project Uses it has support for Gradle. So I'm I'm imagine you could probably do it through that But again, I don't use Gradle And I haven't I haven't seen anyone in the wild doing that, but I'm pretty sure it's possible My guess is to yeah, ultimately all these applications are our JVM applications in a jar file So you can use all kinds of Swiss army knives to split them up The question is how supportable is it and how how consistent is it and how bug-free is it? Another great question, too, is about the S2I Java Builder specifically on OpenShift. Do you are you aware of any roadmap specifically address that point? I am not aware of it roadmap. You're talking about for building like thin applications, right? Right as I know by default there assume an app server target or a fat jar target But I don't know about kind of the in-betweens there I Would be surprised if if I don't think that technology belongs in that particular S2I image because it's kind of a it's basically a Java Generic JVM runner and the the way you split up applications are different depending on which technology using swarm or spring boot So I don't know of any particular road map for the official S2I image that that comes from open JDK Okay, and I'm not I've not heard of anything either It is a good point one there was another question realm How big do these jars get and it occurred to me that back when we were in the old days of years? I regularly saw multi gigabyte ears. Yes They get they get big really fast my hello world is tiny, but yeah, so as soon as you include database drivers and clustering You know all kinds of stuff it grows really fast for a real-world application And I think one thing people tend to forget about when they build these fat jars is yes Putting them in a single Docker container and running that single Docker image and putting it into a single Docker Damon That's easy. It's not that bad But if you have a cluster of let's say 25 nodes That actually has to get to 25 nodes and you're transferring all those bytes across the network. Yep Yep, absolutely And they're storing them in Docker registries and the layers will add up and up and up as you add more essentially duplicate layers In images that have you know, a very small amount of change, but it's a completely opaque to do Docker Oh, and I've also run a disk space before too because of that Yeah, which is just bad because you can't figure out what went wrong and that's So the Kubernetes or OpenShift architecture going thin is definitely a win Okay, well, I think that's all the time we have for today James awesome stuff on the demonstration This is really a fun session. I really enjoyed it Hopefully the folks out there watching live and watching the replay enjoyed it make sure to follow James on Twitter Keep coming back to developers.com slash Dev Nation live. We are now planning for the 2018 version of this series We got a lot of new good content coming in the next year But enjoy your holidays because we'll be taking the rest of the year off James. Thank you. Thank you, Berth. Thanks for having me