Spring Tips: Spring Native 0.11!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

I have not tested Spring Native, but I have a question to some of you that have:Will we be able to use some parts of this project also for regular Spring application. For example to my company there is currently no value in using GraalVM, but we would still be very interested in faster deployment and startup, especially during local development. So, as far as I understand, Spring Native implements some kind of build-time analysis of Spring beans. Can this feature also be used for regular Spring applications to move the reflection stuff that Spring does during runtime to build-time (like Quarkus or Micronaut)?

👍︎︎ 1 👤︎︎ u/Yesterdave_ 📅︎︎ Dec 10 2021 🗫︎ replies
Captions
hi spring fans welcome to another installment of spring tips i've been eagerly awaiting the chance to talk to you about today's video today we're going to talk about the brand new spring native 0.x release which brings with it a bevy of new features which we'll look at in just a moment but before we get into that i want to contextualize where we are and why we care this new release makes marks to me at least the largest single step we've made towards spring framework six and spring booth three so if you went to spring one 2021 this year then you know that our big uh spring framework six revision will be coming out next year in 2022 and a huge part of that is our hope to make spring uh deeply and natively aware of growl vm and gravium native images and aot in general that's a big part of the promise there's other things as well there's uh you know the new baseline supporting the jakarta ee apis and java 17 and all sorts of other stuff but a huge piece of that is this new spring native support um and i don't know that spring native itself will be merged it's not i'm not sure if we're just gonna like take the code and put it in the spring framework or what but something like it will appear in spring framework right something that might be uh newer and improved by then you know that's after all that's almost a year away in some ways but but nonetheless this is a huge part of that work that research that that uh that journey so i'm really excited about that i'm really excited about what this pretends right now spring native is an experimental and second project it's not the same as spring framework itself but it it is aware of the patterns that people have when they use spring boot and when they use spring framework and so it is a great way to take your existing applications and make it work with graviem gravium of course is an ahead of time compiler or the gravium native image compiler is an ahead of time compiler that takes your source code and turns it into an architecture specific binary that is statically linked that's self-contained right these applications tend to have a much reduced memory footprint and rss and they tend to start up in fractions of the times that the equivalent application would start up on the jre it's a really exciting piece of technology and spring native is going to help you fully exploit that technology to make your applications just that much more ready for production growl vm works by looking at your code at compile time and throwing out all the things that it determines again at compile time that you're not using the problem of course is that it doesn't know everything that you're doing at runtime right java for all of its styginess and its words can be a very dynamic little language indeed it can do things at runtime that you might associate more with the likes of something like javascript or ruby or python or pearl or lua or whatever it's it's got a runtime first of all so you can actually dynamically register classes in the class loader you know create instances of them with reflection create proxies out of them serialize instances of their bytes to disk hydrate those and load them up in another jvm all without ever having a concrete reachable type and that's impressive right uh so as a result there's this there's this world of difference between what the compiler can understand and what it considers to be reachable and what actually gets executed at runtime spring native is how you bridge that divide uh with your spring boot based workloads which is to say how you bridge the divide for your typical enterprise application so we've got a lot to look at in this new release some of which you might have seen before all the most of which i don't think so and so with that let's get right into it first we'll need to get the environment set up and running so that we can use it we'll need growl vm let's use sdk man on my mac to find the graphion java installation you can do sdk list java now sdk mn is a very convenient tool that works on all unixy sort of modern operating systems so mac and linux and you can use it on cygwin or wsl for windows and if you scroll down you can see all the different java versions out there all the different sdks etc uh you can see that grav vm uh is already installed i've already got it i've already got 21.300 r17 ground right if i want to install it i would say sdk install java and then the version it's already installed i can then say sdk default java and then that'll be the system-wide java version or if i just want to use it for the current shell i can say sdk use java and then that version and that'll set up the java home and all that stuff for the current shell to be pointing to that that's not all though you also need the native image compiler and there's a command in the utility called gu that comes with grav vm so you say gu install native image it's already installed so it works with that we can start programming against gravia all right so let's go ahead and build an application uh we're going to go here to the start that spring today and we're going to build an application that talks to a database i already have a database running i can connect to it here and i can see i've got a table called customer i've got some sample data so what i want to do is i'm going to build a reactive application now to be fair i'm kind of goosing the numbers here a little bit because reactive applications are by definition going to be a smaller footprint and they're faster right they take take up less resources uh and they tend to be very very fast uh because of that uh in terms of startup so so admittedly this is a fairly ideal sort of use case but hey that's me i'm mr idealism uh that said this isn't the only thing you can do obviously with reactive programming we uh we want to support new architectures but when it came to spring native uh we wanted to make sure that everything that you can do in spring you could do in spring native and so we we have good support for uh all sorts of workloads not just the reactive greenfield stuff of tomorrow right and we'll see some of that in a bit but for now just to kind of get a feel for the lay of the land we're going to take a look at building a reactive application i'm going to call this customers or but you know what i'll call it reactive that's probably easier we want to get access to the latest and greatest version of spring native which is not ga yet um but we don't even want just the rc we want the actual milestones uh because as i record this for we're just a few days before the actual release and so this will look uh pretty similar to the um the next uh release candidate that comes out and so we're gonna use 2.62 snapshot for spring boot we're going to use java 17 i'm going to bring in our postgres support we're going to bring in r2dbc and the reactive web support and of course we're going to bring in spring native now by bringing in the snapshot version of springboot 2.6.2 we automatically get the snapshot milestone repositories added to our build and it's configured to use the spring native version 0 11 0 snapshot which is what we want let's go ahead and hit generate and we'll open this up in our ide okay uao okay uao reactive.zip [Music] all right there's our application uh you know first things first notice i'm using java 17 the last 0.10.x line of uh spring native didn't work particularly well um with the newer versions of java beyond java 11. uh and so part of that of course is that gravium itself has now released a you know there's a version that supports java 17 and spring native works against that so i am super excited about that because it means i no longer have to have this this uh you know fork in my decision making am i gonna target uh gravim native images no okay then i uh i can use top 17 otherwise i need to use java loud that's no longer the case now there is officially no reason at all to ever use anything besides java 17 or newer and that by the way is our stance on it for our applications today and going forward right if you um are using spring framework 5.x then of course we still support uh as far back as java 8 but going forward the new generation of spring spring framework 6 that will be the foundational layer will be based on um java 17 right and and that in turn will inform the baseline for spring boot 3. so let's add some types here this will be a record at java record i'm going to create a repository uh that uses the reactive code support integer and we're going to create a functional reactive http endpoint to serve up the data so router function server response turn route good customers new handler function dot build server response dot okay dot body and here i'm gonna return uh data by talking to our functional you know our reactive repository rather so we'll say uh repository.findall and the type of the payload is customer.class good so there's this and there's that so that'll do that that should be enough we need to connect to our sql data store of course so uh we'll go back to the property file r2bc url r2dbc colon postgres localhost bk username is bk password is bk let's see if this works let's just run it locally on the jre okay up and running customers voila seems to be working just fine good so there's our trivial application it's doing fine let's turn this into a native image so what i'm going to do is i'm going to go to the command line and i'll use the maven plugin that's already been pre-configured for us right you can see that here the plug-in with spring boot maven plug-in with spring aot maven plug-in we've also got build pack support you know you know that spring boot can automatically create a docker image for you you just use maven space spring hyphen boot colon build hyphen image well we've pre-configured native image support as well so if you should so decide you can actually have spring boot create a docker image in which you have a linux architecture specific binary of your application a gravium native image so it's a gravium native image in a docker image and you just do maven spring hyphen boot call and build image that's super convenient right this aot plugin is very important this aot plug-in you've probably seen before if you've used spring native it's a clearinghouse for code transformations that we do against your code base and at the debut at the onset it was fairly limited we did a few uh transformations on the code um before we passed that code onto the gravium native image compiler uh but they were not substantial as we'll see in just a bit 0.11.x is a huge stride forward a huge leap forward right um in terms of what we're able to do with the uh the aot maven plugin beyond that we've got all this and of course down here we've got a maven profile so if you just want to build an image you know forget about docker for a moment if you just want to build a native binary on your local mac or linux or windows machines then you can just run this package uh you know the maven package command it with the maven native profile so i've got different uh i've got test support um i've got the gravim native image maven plug-in all the usual stuff but that's all pre-configured for you so let's go ahead and now build this application i'll say maven skip tests just you know you don't have to you can actually that's one of the nice things about uh the spring native is that we actually support compiling your test code in a native context and then running it in that context uh so you can actually create native jain tests run them and make sure everything works there uh you know and have a sense that what you're gonna do at runtime also works um you know in your test code so maybe skip test equals true uh and then minus p for for profile clean package let's go ahead and run this [Music] all right the application built in two minutes uh let's go ahead and visit the target directory and see what they gave us we can run the native image here just by hitting reactive and there we have it our application starts up in 67 milliseconds and by the way sometimes that number can change depending on you know your your operating system and the entropy in the universe and and whatever what all but either way really fast and what's also interesting is that um it uh it took very little time to compile okay so this is now you've got a feel for what's possible here right we've successfully built an application and compiled it using spring native011.x the new aot engine is a huge part of the reason that spring native is so amazing it's a central piece of infrastructure through which all your code passes the aot engine looks at your spring boot application and transforms your code in such a way as to be more amenable to the gravium compiler it also produces the hints that are required for the code that isn't yet optimized uh to be passed into the gravium compiler so that it understands the things that you're trying to do like reflection like serialization like proxies like loading resources from jar class paths and so on so that it works in grav vm when you compile your application we want to get as much information about the behavior of your application and the relationships of the objects in the application context as possible uh one way we do this is by running your application we don't actually start the application context right but we do register all the beans we all we we start up an application context with all the beam definitions uh registered this gives us a chance to see the relationships of these different objects and to make it under easy to understand how they relate to each other what their what their configuration looks like what their shapes are what dependencies they have etc we can then use this information that we collect by running your actual code to then inform the generation of hints and and transformations some of the transformations that we do are fairly straightforward for example we have a text file called spring.factories and this text file is used most famously as a service loader for spring boot so you might know that in spring boot and in any of your jars in any jar in the class path you can have a meta-imp directory with a text file called spring.factories springboot will detect the presence of those uh files on the class path through its service loader mechanism and it'll evaluate uh it'll instantiate and then uh you know evaluate the conditions on all these different java configuration classes this is how spring boots you know so dynamically is able to register and contribute objects to the object graph these configuration classes are just java config classes they're they're they have beans they have conditions one of the conditions that you can see here is conditional on class spring boot will not register this can this class unless this type called cash manager.class is on the class path so there will be no cash out of configuration if there is no cash manager dot class well that's something that we evaluate normally on the jre at runtime by starting you know by starting up the application and then looking at the very dynamic class path of a typical jre application well in the gravim native image world there's no such thing as a class path you can't swap out one jar for another after it's compiled it's a statically linked self-contained binary right that's architecture specific there is no more class path and so we can we can foreclose in the possibility that that will be swapped out we can just say hey it's not here right now therefore it'll never be here because once we're done with compilation that's it no no going back right so we can look at we can pre-compute that condition at compile time and so we do we actually pre-compute that condition at compile time and we generate a java class that contains the result of that pre-computation that java class is staticspringfactories.java and it's just it's it's what you think it is right it's a new version of springdale factories but sort of refined as java types um and we've you know we've configured the spring boot running under aot to consult this and not spring.factories this is not just for your code it's also for all the code that gets contributed to the running application so here's the result of all the auto configuration right the we have a reactive uh we have a reactor server resource factory and that in turn has the following type with the following you know in factory method and so on right so very very very powerful mechanism this is a quite a leap forward this this ability to transpile your configuration into functional configuration and the results speak for themselves they're they're amazing right the applications are much faster now in compile in compilation and so on here the native image compilation process uh invoked the aot infrastructure and that's how we got all this code you can go short of a full native image and run the aot transformations manually so here i could say maven spring aot generate [Music] the maven plugin uh is what actually generates all these uh these these you know transformations so we can actually see all that without actually having to do the full native image build and it's not just the native image build that benefits from that you can actually run your java code in the jre using the aot infrastructure and that actually has a it has the effect of reducing the resonant memory footprint of the running application just a little bit you know maybe not a huge amount but still it's there it's free performance and and it'll contribute uh to the startup time as well so and java minus jar reactive 01 snapchat so we're going to run this without enabling the aot infrastructure we're going to run it on the jre all right so we ran that it's fine it starts up in you know 1.8 seconds it's 2.28 jvm time okay good so 1.8 okay almost 1.9 now we'll do spring aot equals true and you can see it's you know 200 milliseconds that's not that's not nothing nothing to sneer at right and you can see there's the telltale sign this application is bootstrapped with code generated with spring aot uh you would see this also say uh disabled when it's not enabled right when when you run it without spring aot being involved so spring aot is a win because you can actually pre-flight what your native code is going to be compiling and running with you can actually benefit from it even if you're not using gravel vm it's just a win even in performance so it's just a good thing to know about all around all right i've got three sample applications the first is just a traditional typical spring batch application uh it is a job uh you know spring batch is all about um uh sort of long-lived uh sequential data access centric uh jobs and so i have a job that has one step that step is defined as having a task all i do is i print out hello world um and i'm you know not doing anything special i just got this the only reason i've got this is from israelite test what i want to do is i want to run all these applications and let them run for a second and then capture their memory footprint right so in order to do that the process needs to still be running a spring batch absent some other thing will will start and then stop right so when you start the application it'll start the job and then when it's done it'll finish the job and if there's nothing else to keep the context open the application and the jvm to shut down so i'm keeping the thread open and i'm joining the current thread so as to keep the jvm running all right so just a typical spring boot spring batch application nothing special here um nothing no config i'm using h2 for my my sql data store access so i've got an embedded database here i've done nothing to the build it's just stock standard you know release candidate stuff i'm not even using the the new stuff i'm using the release candidate here java 17 spring native all that all right i have a reactive application this is a stock standard reactive web application um it's a application that when it starts up we write um several records to the database we have a functional reactivation pinpoint uh a record and a repository that's it again same as you've seen this before this is a nothing special right i've got the schema here people want to create their own scheme on their own database in this case the database i'm using is postgres and so you know i've got that uh in the on the class path here spring native h2 embedded oh this is h2 but the other one was postgres you saw the one with because either way uh it doesn't matter right they're both they're both sql databases so this is actually a little bit more involved in that we're creating the database in the application itself or embedding the database in the in the memory of the compiled application as opposed to just the client that connects out to some other database so in that respect it gets a little bit slower right it could actually be a little bit slower than the post goes one we also have a traditional application and this is when i say traditional i that's my euphemism for stuff that i wouldn't write today if i had a choice but you know i i can appreciate that a lot of people still do this is a jpa tomcat you know servlet api based api so here's a regular http servlet based spring nbc controller um i'm just injecting the repository and returning all the records i've got a jpa entity this is a like like it's using hibernate behind the scenes so i can't use java records because hibernate and jp don't support it um and um i've got a repository now again for any other spring data module such as spring data uh you know spring data r2bc i can use records but this is a lot more verbose even though i'm using java 17 it's a lot more verbose for that but okay so this is going to be your slowest application there is a lot of stuff happening in in hibernate it is it is absurd right and it's also the least scalable of the three because uh well i mean up the two certainly between the reactive one and this one this one will handle the fewer fewest requests because there's a synchronous blocking i o right so it's a little bit more involved but it's pretty representative of a traditional typical application and again the build is just stock standard go to start.spring radio generate a new project use spring boot 2.6.1 use the rc1 for spring native and bring in webm webmvc spring data jpa h2 etc okay let's look at some of the numbers we've looked at three sample applications that demonstrate non-trivial use cases the batch application traditional hibernate tomcat servlet based applications and reactive applications using the more modern spring webflux and r2dbc and so on and i've got a little script that i use called measure.sh that runs the jr jre version the aot version and the native version of those three applications and measures both the startup time and the resident set size time the aot version and the native version are of course faster but the native version is going to be dramatically faster right obviously that's what we're what we're here for is we want to take advantage of that whole paradigmatically different uh approach to to memory management and speed and startup time but that said the aot engine can be remarkable in of itself even if you're running on the jre it can do some very interesting things you can actually lower the footprint and shave off whole seconds for example in the in the case of the the traditional application from your startup time for more typical applications such as those i would write in 2021 it's it still manages to shave off let's say 200 milliseconds here and there that's not nothing especially in your dev cycle rinse repeat cycle when i write code on my laptops these days it typically starts up in one second 1.5 1.3 something like that so if i can shave 200 milliseconds off of that that's great i'll take it thank you very much so i love the new aot engine and the numbers speak for themselves both in terms of how the jre version of the application runs with aot enabled and how the native application runs with the the benefit of the aot engine in place let's take a look at some of those numbers you can see here that the reactive application when it's run in native mode starts up in 61 milliseconds and has a resident memory size of 57.8 megabytes 57 megabytes right that's an application with a web server and a database client and i think maybe the actuator whatever i'm not sure but very very very small application uh the jre version of the same application starts up in 1.7 seconds i would i would remind you that i'm screen capturing uh as i run these tests so things are going to be a little bit slower there and it has a memory footprint of about 472 megabytes that's you know a far side better than it was for typical applications on the uh in the enterprise let's say 10 years ago but yeah that's a lot right if you can if you can run a a service unless why wouldn't you want to right so what about the aot version well the aot version of the reactive application starts in 1.5 uh you know seconds right so almost 200 actually just about 200 milliseconds that got shaved off there uh and it takes 493 megabytes of of memory so it actually in this case balloons the memory footprint a little bit to use the aot engine but it shaves off a considerable amount of time in the startup okay now what about the you know going back to the uh the traditional use case the pendulum swing and the other way to the least efficient stack that you can use today using something like hibernate and the servlet stack right well in that scenario the native application starts up in 155 milliseconds so 155 thousandths of a second right almost a tenth of a second a little bit more than a tenth of a second right that's awesome and and it takes about 127 megabytes of ram so you know more than twice as much ram as the reactive one at runtime and uh well past more than twice the startup time just just for using hibernate and and all that right so if you can avoid it maybe you will maybe you should the jre version application takes 3.6 seconds to start up and takes 649 megs of ram to sustain the aot version dwindles down to 2.8 seconds to start up so again almost a full second faster for the traditional application using aot and the memory footprint is about the same at 647 megabytes the spring batch application the native version of the spring batch application starts up in 65 milliseconds so 65 1000 of a second it has 83 megabytes of memory so again uh you know three two thirds or three quarters of the traditional application uh the jerry version the application starts up in 1.3 seconds and has 416 megabytes of of memory so again 460 compared to the 650 almost uh for the traditional application right almost 200 megabytes less just by using something like that right now obviously batch versus web these are different use cases all together but for lots of workloads you can expect numbers that look like that from messaging for batch for data for these kinds of things the only thing i i think these numbers are more typical the traditional application with with hibernate and the servlet stack that's going to be more atypical okay all right the jre version as we say is 1.3 seconds um 469 megabytes the aot version 1.0066 seconds so you know 200 milliseconds there and uh 419 megabytes of resonant memory so there you know call that 420 that's 460 we saved 40 megabytes of ram just by using the aot version that's a big difference if you're measuring in terms of you know 500 megs right that could be an eighth of your of your footprint saved right there so spring native does a lot for you and a huge part of that intelligence comes from the aot engine the aot engine has a lot of built-in smarts to help you get the most out of your spring applications but what if it's not enough well spring native like all of spring is a framework it's open for extension uh but closed for modification now of course strictly speaking that's that's not exactly true is it a spring is a is an apache to licensed open source projects so of course you can get the bits and recompile and change and do whatever you like without telling us or contributing back to your heart's content but the point is you don't need to right it's got well-known extension hooks or extension planes that you can use to override the default behavior to make spring do what you want it to do and the same is true for spring native right you don't have to recompile spring native to get spring uh workloads that spring native doesn't understand to work well so in this section we're going to look at some of the extension points that spring native gives you including tie pins which are annotations that you can add to your code as a start native configuration native bean configuration processors and native bean factory configuration processors let's get right into it we've looked at the basics here we've looked at how to use uh the new spring native release we looked at how to build uh an application and get it compiled with gravim uh we've looked at uh the aot infrastructure and some of the uh implied benefits of that and some of the uh ramifications for more or less typical kind of workloads and use cases obviously there's a good deal many more but you'll find that the list of supported technologies uh in the spring ecosystem is vast and growing day by day right so we have for example uh you know much of what you can do with spring boot is well supported lots of spring cloud is well supported and obviously the list expands every day and it gets easier and easier uh to create uh and add to that list part of the reason we have to have a list however is that it's not guaranteed that it'll work remember spring native can do a very good job of adapting code uh that that that spring knows about it if it's just a regular object that you've declared or a regular bean or something that is an auto configuration uh assuming there's no um funny business you know things like reflection and loading resources from a jar or proxies or a serialization or anything like that assuming that there's none of that uh sort of more uh esoteric kind of stuff going on then gravium and spring native should just be enough right however sometimes there are things we need to do that go beyond what the spring native infrastructure and the aot infrastructure uh can understand deterministically at uh compile time so for example let's say you have a bean method that returns a type and that type is an interface okay well that's still not necessarily enough to be a problem but what if that interface the implementation of it is actually a proxy well now you've got an issue you've got to tell spring native and you've got to tell gravim about this proxy uh what if it's a a spring siegelit proxy well of course the gravium itself has no notion of this so you definitely need to tell spring native about it what we're going to look at in this section is the support for those kinds of extensions so let's go ahead and go to the spring initializer and we're going to build a new application as always i'm just going to call this extensibility and we're going to use java 17 and i'm going to bring in spring native and that's it so i'm going to open this up in our ide [Music] so we're going to build a simple example here okay we're going to say we have a bean and we're going to create a bean that returns an interface an implementation of an interface so let's say it's customer service all right and the customer service has a find by id method where it's an integer id and the id is a customer so you know let's say integer id string name all right so very very trivial very very you know plain kind of thing we could create an implementation there's no problem but for whatever reason we're using a proxy okay so uh we would say var cs equals proxy factory dot get proxy and we pass in the proxy interface which is customer service.class and we'd uh return a new method interceptor so if you've ever used spring boots uh sorry spring frameworks um uh alp support then you've probably seen this before it's not all that new and what's happening is we are simply intercepting method implications it's going to create an implementation using jdk proxies of this interface and we get to register a callback a listener an interceptor that gets invoked every time somebody calls a method on that implementation so as an example we can return a application runner that injects a customer service customer service dot find by id one okay so i'm going to say find the id and we're just going to print out the result all right so there we are so that's just it's going to call find by id but of course something needs to actually happen when you call find my id and that's this that's this callback so we're going to say if it's like java lang you know boolean equals or java lang you know javaline object boolean equals or javalink object to string or or hash code or whatever all that we don't care we'll just return null uh which is not great for collections but that's not what we're trying to demonstrate here so we'll leave those cases uh un uncared for but if we're trying to if we're trying to call you know let's say um find my id well in this case i want to return a new customer and it'll be number one and uh it'll be you know dr sire i don't know whatever okay so now let's see if that works okay we'll make this a lambda and uh it's just a trivial example here right all i'm doing is i'm i'm creating a proxy not something you are likely going to do in your code but you can kind of understand uh why this might be complicated so we're going to run it on the jre first there you go got the got the record back when i printed it out so it worked our proxy worked but this isn't going to compile well and the reason is because we're creating a proxy and that proxy doesn't look the way we think it looks right if we actually say cs.getclass.getinterfaces and then do 4 var i and this let me do the system out i get name what do we get alrighty so we ran that again you can see there's actually four interfaces here not just the one that we created but three others are you know part of the uh the proxy process with spring new you know the mechanism we use to create these proxies for you so we can tell spring native about it through the type hints mechanism and there's there's a whole slew of hints that you can use here right i um like i've got i've got native hint and this is great for uh for you know fauna register jdk proxies i have to say jdk proxy hint uh and then here i've got the types okay well what types i have to actually add commas and classes so i'll say class comma all right and then that goes there there we are okay so there's my jdk proxy hint telling oh i'm gonna did i forget to add the comma good so this is my jk proxy telling spring native about the uh the interfaces in the order they appear that's very important right it has to be in the same order so jdk proxy hint uh is going to make the difference so let's not let's compile it and let's run it and see what we get without this okay we'll do a native example so maven minus d skip tests equals true uh minus p native clean package [Music] all right so there's our application let's go ahead and check out the result so extensibility it fails right it is not happy with what we did it's a proxy class defined by interface blah blah proxy classes need to be defined at build time by specifying a list of interfaces that they implement so this is a jdk proxy it uses just interfaces spring has support for another thing called an aot proxy which actually we we subclass concrete classes not just we don't just uh create implementations of interfaces we actually have we can actually enrich or or apply aspect orient you know cross-cutting kinds of concerns to concrete classes um why is it interesting well uh it's interesting because graviam doesn't know about that right and so you have to be aware there's two different kinds of proxies in the spring ecosystem regular good old-fashioned jdk proxies which are limited to interfaces and also aot proxies but the mechanisms you know the use of these annotations is the same so let's now add this back and uh rebuilt [Music] okay there's the application now we try again and it worked right all we had to do is to register that little proxy hint telling it about this and then gravim did the rest uh and so that's what spring you know that's the power of string natives you can easily add these hints for things where spring couldn't deterministically figure out what you're trying to do spring doesn't know that inside the body of this method you're doing some of this you know funny stuff right it doesn't know about that now are you statistically likely to be to be doing something like this no probably not right again spring does a fair bit of this kind of stuff behind the scenes and we make sure that we have hints for the respective frameworks like spring data and and uh you know uh things like that but it's just useful to understand why that's there and there's a number of hints that you can use right these are all this is just i looked at jdk proxy hints but there's also uh aot proxies as i say and that takes an aot proxy hint you've got hints for resources like if you want to load a file you can say this is a class path resource maybe i'm going to load this file from the class path or something like that so i can actually register that there's um we've got serialized serializable hints we've got um you know hints for you can provide a trigger you can say okay this this type sort of this this hint should only be evaluated if this type is there or more usefully you could put like a you know a what's a let's say environment uh you know some sort of auto configuration so let me see auto configuration you know you could put um whatever on that uh if this is present if this auto configuration evaluates to true then and only then does this hint apply so you can do all sorts of things to make this hint uh more robust and and to encompass more things and and you can have like oh i'm gonna register this serialization uh hint and this resource hint and this proxy hint but only if this class this auto configuration is active okay so very cool right you can and you can have as many of these as you want you can have native hints upon native hints or you can use the umbrella type like native hints uh you can say um native hint you know it's just a it's a an array of native hint right this is very useful if you're going to do the the most useful one i use on a daily basis or you know not daily but certainly a lot is uh the type hint okay so type type hint here you can specify uh the types you're going to use for reflection so let's say you were going to reflect upon a type right and it's a type that's already known to grav vm it just doesn't know that you're going to reflect upon it because maybe you're doing something with a string version of it or whatever and here you can actually specify type equals customerservice.class and the access that you want people to have the access that you want people to have you specify in terms of access bits dot right so this is the uh the old thing so access bits dot all for example now this has actually changed this bit right here the axis bits so let's go back to the initializer and let's make sure we're using the latest and greatest we'll hit explore copy and paste all that in there okay so now you can see this no longer works but now you can understand why that was there with that what that was before now it's a something called type access and you have a lot of options here auto detect declared classes public methods queries resources blah blah blah right resources if you want to load the type as a resource from a jar that's it you just want to literally load the type the class file from a jar for example um if you want to enumerate all the declared classes or all the different declared fields whatever or just to auto detect so this might be very common you know you might see this a lot particularly for framework code that isn't spring right if you're using spring but you're using some other thing with spring and spring doesn't know about that then you might find yourself using type hints a lot all right so we've we've met the new version of spring native uh it has a lot of really interesting possibilities but if we want to go further we need to bring in the spring aot framework as a dependency so go to the build add aot maven reload project okay so first things first you've probably met the type the you've probably met the native configuration uh mechanism in earlier versions of spring native so that still works so extensible native configuration um what you may not have done before what you may not have seen before is that we can actually just create this in the same jar as our application now it's no longer fed into the class path of the maven plug-in itself it's fed into it's just part of the uh class path of the uh of the application just like auto configuration and and so many other things so we're gonna implement native configuration and the the contract here is very simple you're given a registry and you can programmatically register type so maybe i wanted to create a native entry proxy for those interfaces that we looked at before right here we go there we go good uh i want interfaces all right so there's that and that's programmatically registering my types now of course in order for this to work i have to create an entry in this in the spring.factories um service loader mechanism so we'll say meta imp a new file spring.factories so now we need to register this in the new text file let's uh the the the thing the key is the type that we're implementing so copy this reference equals and then the type is this one here so copy that reference that all right good so there's my uh native configuration type and you know we can we can see that it's running we'll say law you know uh system out running inside uh extensible native nativeconfiguration.getname right so let's let's see what this looks like and remember we've commented out the hints here so they're no longer there and yet we should see they had still contributed now we could we can let's compile the application as before [Music] okay so there is our type that's worked right and you can see we don't have those hints anymore when the application was compiling way up here we would have seen that we're running in um you know that type so let's see if we can find that needle in the haystack uh running let's just do this there you go running inside comics com example extensibility extensible native configuration so it got picked up and it was given a chance to contribute the hint and that made the difference because without this and without those annotations as we saw before the process would have failed so good so this is very useful but this is also very low level right what you're dealing with here is a a registry and you have access to the code but really you don't know what types you've got there you know you don't know what you're dealing with so it's not great i i this is fine it was it was the old way but there's a better way now right and that is you can create a type like this you can create extensibility or extensible native okay so it's it's a it's a b native configuration processor that's this thing right here right and i just called it extensible b native configuration processor and to make that work you get a callback method now this is not our uh favorite most recommended way but it can be useful um because you are given a chance to sift through each object in the application context so i can say you know give me the injection points give me the user instance creator give me the user bean class you know i can just get the name here so let's say system out extensible the name native configuration processor dot get name okay and uh run this and uh there we go okay so i'm gonna print out that we're inside this class and that we've got this type that we've discovered from a that's being contributed to this bring the bean application context uh i can i can i can just basically inspect every single type right um which is useful right it's very useful i can actually uh look at the properties that's to say oh the the the the java bean properties the setters that thing that kind of stuff i can look at the injection points which is where this thing is being used it's it's very useful but this is a sort of one being at a time approach to working with the system and maybe that's what you want you know maybe that's enough and you still have access to the registry as well so you can say registry dot proxy serialization jni initialization reflection all that kind of stuff you can do that as well let's register this type just as we did before again here in spring.factory so the type as before is uh the name of the interface and the value is the name of the implementation so there we are goody okay good so there we go there's my um uh new contributed thing let's go ahead and rebuild this [Music] okay so uh you know it worked of course nothing has changed for the presence of that particular interface uh but let's look for this right there you go so you can see we're given a chance to work with every bean that's being created and so if you want to use that information if you want to inspect the properties or the return values or anything like that you can do so easily now but again this is a it's it's a one bean at a time approach the final and my preferred i think all of our preferred way uh to build integrations is to use the um bean factory native configuration processor so we'll create another one here extensible bean factory native configuration processor these these uh types don't leave a lot to the imagination but that's okay there's not supposed to be an imagination here it's supposed to be very clear what you're supposed to use so there you go um implement that all right so there's our our our last type and now you've got access to the whole application context you got to also you have also got access to a type of registry right to the registry so let's go back to our code and let's go back to the type system uh the native configuration version rather and let's just drop this out okay there we go and let's re-implement it here instead what i want to do is i want to go and look for all the implementations of something or maybe i want to find the the being of a in a certain way so i can say beans with annotations okay so i could actually maybe i could have an annotation on the um uh on the type maybe it's a marker annotation right uh just any any old annotation it could be you know at customer service it could be a qualifier it could be at component it can be in you know anything just any any arbitrary annotation and that way i could find all the instances right or maybe i want to just inspect all implementations of that interface in this case i've only got one but let's say i do get beans of type uh customer service right so whoops not css service.class and that gives me back a map of b name to type right and i can say okay um beans uh sorry beans of type for each k and then the bean and um now i can actually just iterate over each one and programmatically register that type okay so here's my um you know maybe i have a uh maybe it has other interfaces so i can actually get the bean i can say bean.getclass dot get interfaces and and uh you know go through all that but we know that spring proxies automatically create these three and we know that there's only one instance that has customer service so in this case it's you know the effect will be the same i'm just registering one instance um but this is very interesting because now i have full access i don't need this anymore now i have full access to the application context right so you can imagine all sorts of use cases in fact this interface is used in lots of places in the spring native projects right so for example repositories right spring data repositories you can see we actually have a fair bit of logic here to make sure that we programmatically register the interfaces for each of your spring data repositories right including these common ones and and so on so you know we use the slot for all the sort of sort of stuff that we're doing in spring native itself let's go ahead and register this with our spring.factories just as we did the other one so here it's a bean factory equals and the uh type here copy reference all right goodie there you go so there's our bean factory native configuration processor um and that's the final piece so let's print out where we are so system out running inside extensible bean factory native configuration processor dot get name goody all right so remember we don't have any other hints anywhere else we don't have it here we never did we don't have it here we don't have it here anymore clean that up so it's just here so we're hoping that it'll find the bean of type customer service and that way you'll be given a chance to register the hints accordingly so let's try this [Music] all right it's worked look at that there's our application uh we have our proxy we have our interface uh based proxy uh and it has worked right as we expected it to so these different mechanisms give you different access to the uh to the application context i would use bean factory native configuration processors for just about everything um unless you're dealing with something that lives completely and utterly outside of spring it's never registered in spring uh it's never part of spring in which case you might you know you might want to just use a native configuration uh interface the native configuration interface also has the benefit of being the right place to stash those annotations so we saw that i had annotations on the application itself um those annotations can also live in a native native configuration interface as well implementation so if i put those here those will get picked up and they'll be applied to my code base right so in this case i can reuse those annotations i can reuse those hints by packaging them in a native configuration and adding that to the class path of some other module and they suddenly benefit from these hints so maybe you don't need to programmatically register uh your hints you can just use the annotations on the native configuration type so uh with that we've looked at how to extend spring native and how to extend its understanding of your application you shouldn't need to do this but if every now and then it happens at least you have the tools in place to make it easy graviam is an amazing opportunity it represents a way to take springboard applications into new categories new horizons new niches like for example infrastructure you can take an application and write uh write something that that controls kubernetes for example right you can actually build kubernetes controllers and operators and so on using spring native i even built a set of spring native hints for the kubernetes java sdk think about the possibilities there you can write spring native code to control the way it manages and works with your springboot applications which themselves could be spring native based and speaking of kubernetes gravium changes the whole discussion around what it means to be cloudy cloud native if you choose spring native in the spring initializer then it'll pre-configure build packs support for you build packs are of course a great way to take an artifact an application artifact be they a.jar.net exe or you know ruby on rails app or python app or whatever and turn it into a container a docker image that you can then deploy into your cluster you can easily get a gravim native image inside of a docker image just by saying maven spring hyphen boot colon build hyphen image and then you can deploy that newly built container to your docker registry you know the vmware harbor docker hub google container registry or whatever just just as you would any other container this is a great way to take applications uh to production on something like kubernetes it's always wonderful to be in production and now thanks to spring native it's less expensive too
Info
Channel: SpringDeveloper
Views: 9,588
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
Id: DVo5vmk5Cuw
Channel Id: undefined
Length: 59min 35sec (3575 seconds)
Published: Thu Dec 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.