What's new in Spring Boot 2.6

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello spring friends my name is dan vega and i'm a developer advocate on the spring team today we're going to look at what's new in spring boot 2.6 with each release we publish a set of release notes that highlights what's changed and what's new you can dig through these on your own but i often find it useful to absorb these features when they're associated with demos each of the release notes are broken down into two sections the first is upgrading from a previous version of spring boot and the second is what's new and noteworthy in the description below you'll find a link to the resources as well as time stamps to each of the features that we're going to cover today i hope you enjoy it what are we waiting for let's take a look at some code [Music] the first item under upgrading from spring boot 2.5 is deprecations from spring boot 2.4 i thought this would be a really good chance to talk about how deprecations work in spring boot and so anything that was deprecated in spring boot 2.4 for removal has been removed two versions later in 2.6 so once they're marked as deprecated for removal we'll wait two versions and then that is removed from that version of spring boot so how can you check to see what was removed well one way you could do that is you can head over to the spring boot docs api so in this case i'm at docs dot spring dot io spring boot slash docs and then the version that you want to check so i'm falling under anything that's 2 4 so this is 2 4 x and then the api and what i want to do is just head over to the deprecated section and here you'll get a list of packages interfaces classes etc that have been deprecated so if we jump down to classes here a bunch of classes that are no longer around in 2.6 so if you're using any of these you're going to run into some problems so this is usually the first place that you want to look deprecations from two versions back you want to make sure that there's no classes methods or properties that you are currently using again before you go ahead and upgrade this is a good place to start anything that might have been deprecated the next item we're going to talk about under upgrading from spring boot 2.5 is circular references prohibited by default so to do this i'm actually going to create a new application and this will be the only time that we create a new application i don't want to do this for every single demo but i do want to show you one so we'll create a new application using the latest 2.5.x version we'll show you what was happening in the previous version and then as we upgraded 2.6 we'll kind of show you what has changed so here i'm creating a new maven project with java and i'm going to select 2.5.10 come over here and give it a group of dev.dan vega and we'll say let's call this blogger and we're going to use java 17 and then as dependencies go we're just going to select spring web and the actuator and from there we'll go ahead and download it or generate it download it and open it up in our favorite ide intellij idea all right so here we are in intellij i'm going to go ahead and expand this out and close that and that and that for now so what i want to take a look at here is the main application class and i'm just going to go ahead and run this i like to run this make sure nothing got messed up while generating the project and of course there is this is a good time to make sure that everything is working so what happened is that there is something else running on port 8080 so we can get rid of that really quick all right so we're up and running everything looks good and we can continue with this demo so the first thing i'm going to do is actually create a new package we're going to call this service remember we are in the 2.5.10 version of spring boot so i'm going to create a new class called the post service and we'll also create a new class called comment service so let's talk about this let's say that each of these classes relied on each other so when i made a comment i may need to refer back to a post and to do that i would use the post service and vice versa when i'm working inside of the post service they may need some information about comments so i rely on the comment service so i may come in here and hey and say i have a final post service and it's called post service and then hey please go ahead and add a constructor parameter so this means that we have the constructor for our comment service takes in a type post service and we'll initialize our post service variable here so on the post service we're going to do something very similar we're going to say private final comment service why that came up and then we'll do the same we'll create a constructor parameter we'll get rid of that okay so that looks good so now let's talk about this outside of spring really quick so if we were just to create an instance of one of those classes let's say the post service we might say post service post service is equal to new post service we might say comment service comment service is equal to new comment service but now you see that common service and post service the constructor is saying hey i need an instance of one of those classes so here we could this could work we can say post service and that satisfies that constructor but what do we do for the post service we don't have an instance of the comment service yet so we can't really do that so this is where you get into a circular dependency where each class depends on each other now what you could do in the post service is say well we're not going to take this in as a constructor argument so in that case it can't be final but what we could do is say public void and i'm going to set the comment service and so i'm going to take in a type comment service and then in here i'll just go ahead and set that and then you know so again this is outside of spring right so outside of spring now what we can do is we can say hey post service i want you to go ahead and set the comment service and i'm going to pass in an instance of that comment service so outside of the world of spring this is kind of how you would approach that scenario so now let's look at at what happens inside of spring right so i'm going to go ahead and change this back and we'll add a constructor parameter and now what we're going to do is just let spring know that these are some beans that we want you to manage spring so i'm going to go ahead and mark them with the add service annotation and when i do that now spring is going to manage those beans for us so ever since spring 2.4.3 i think it was you know the auto wired annotation on a single public constructor is now implicit it's just kind of known that hey you have some types here i'm going to go ahead and satisfy those dependencies and auto wire those in for you so we've done that on both of these so now if we go ahead and run our application you'll see that again this is in 2.5.10 that the dependencies of some of the beans in the application context form a cycle so comment service relies on post service post service relies on comment service so if you use constructor injection in a previous version like 2.5.x then you saw this error now constructor injection is the preferred method for dependency injection in spring if you're curious on why i actually recently published a video on that exact topic where we go into a little bit more in depth on why you want to use constructor injection over something like field injection so if you're interested in that there'll be a card above and a link in the description below but let's take a look at what happens if we don't use constructor injection here in our application so i'm going to remove final i'm going to remove the constructor and i'm just going to say auto wired and i'm going to do the same here remove final and add at auto wired and now let's go ahead and run this example everything starts up just fine because again they're not forming a cycle when we go ahead and instantiate the beans because field injection happens after things have been created after these beans have been instantiated right so in a previous version you could get around this psychicular dependencies by using field injection and i'm not it's not right it was just kind of a hack to get around that right again we should be using constructor injection here there are many reasons why uh so we want to be using constructor injection here so let's go ahead and leave this the way it is though and i'm just going to move over to 2.6.4 which i know is the latest version at the time of this recording i'm going to go ahead and refresh our dependencies here and we're going to go ahead and rerun the application the same way with the field injection and now you see we are getting that error so the dependencies of some of these beings in the application context form cycle now you will see some more action down here so relying upon circular reference is is discouraged and prohibited by default and if you want to you can update your application to remove the dependency cycle between these beans and as a very last resort it may be possible to break that automatically by setting this property so what this means is that we're kind of giving you an escape hatch let's say you're upgrading an application and you have a bunch of these instances and you just don't you you can't prioritize trying to find a way around that at the moment we don't want to stop you from upgrading your application so you could come in here and set this to true and if you run this again everything will start up as expected so again this is really a last resort or if you just have a lot in your application that needs to change you know the recommended approach would be to come in here and find a way for these two to not be dependent on each other um there you know in certain cases there may be a way to build the application uh to do that so that would be the first thing take a look at if if you can kind of refactor that and find a way to not be dependent on each other but if you can't you can always come back to kind of this escape hatch and turn you know allow circular references until you get the opportunity to go ahead and correct those the next feature that we're going to look at is the path pattern based path matching strategy for spring mvc so i'm back in the application and i've reverted back to 2.5.10. we're going to do this so we can look at kind of what it used to do or used to be and then we'll upgrade again to 2.6.4 and see how this has changed so to do this i'm going to create a new java class and actually i need a new package we'll call this controller and inside of our controller we're going to create a new controller called post controller and inside of post controller we're going to create a simple git mapping this will go to slash posts slash name and slash name and you just have to bear with me for a second i know that seems a little funky and it is but we'll talk about why so maybe we wanted to find all our posts by author and in here we'll pull that out using the path variable annotation we'll assign it to string name and in here i'll just go ahead and print out the name which is name all right so here we have two parameters in the path one is name and one is name and this is actually allowed previously so what is changing is the default strategy for matching requests paths against a spring mvc handler mapping is changed from something called the ant path matcher to the path pattern parser so if you were to go in here and look for something called the ant pathmatcher you would find this and this is the class that was previously used to match four patterns and this would go you know most so mostly we use this here in the spring mvc world to um to match against a path you also use this in if you're using spring security you may use an mvc matcher to match against a particular [Music] path there so if you're using spring mvc double check those routes as well because it gets a little finicky what what's happening here is the in 2.5.10 the default ant pathmatcher is a little bit lenient so it doesn't care that there's two parameters here with the same name it's actually just going to take the last one so if we were to go ahead and test this path out first off i'm going to rerun this and then i'm going to go ahead and test this endpoint out by going to the http client here in intellij and in here i'm saying this is localhost 8080 slash post and if i were to put my last name and then my first name and let's go ahead and test this oops we may need to mark this as a rust controller that would help let's rerun this real quick and go back to our tests here and say that and you see we got a 200 now so if we go back over here we see the name is dan so it's taking the last one and it's okay with that so what we're going to do is we're actually going to switch over to 2.6.4 now and we'll refresh our movement dependencies here and we'll rerun our application and you will see right away we're going to get an error it says invalid mapping pattern detected post name name not allowed to capture name twice in the same pattern again here is the um spring boot telling us what is wrong and how we can fix it so fix this pattern um or you can switch back to the legacy parser so again we're kind of giving you an escape patch if you want to upgrade but have a bunch of these instances or something similar like i said maybe you're you have a bunch of configuration in spring security that's causing issues we're going to give you this way to kind of get out of that so if you come back to your application properties and put in this property and give it the strategy is ant path matcher again instead of the new one which is the path pattern parser then you can revert to that and if we go ahead and run this now it should start up just fine the next feature we're going to look at is the actuator environment info contributor is now disabled by default so before we look at what's changed in 2.6.x let's go back to our 2.5.10 version and take a look at a simple example using the info actuator endpoint so the first thing we're going to do is go into our application here and i'm going to expose all of the endpoints in our actuator so we're gonna say management dot endpoints dot web dot exposure dot include and we'll say star so this is just gonna open up everything for us so if we do that and we go ahead and reload our changes here and we go ahead and run our application should be able to go over to the browser and nothing's going to work at 8080 but if we go over to the actuator we should see some endpoints and we do have this endpoint called info and right now there is nothing on info but what we can do is we can come into our application here and go back to application.properties and we go ahead and include a bunch of properties so what i'm going to do is just copy and paste this in and this is anything off of the info property here will now be included in that actuator endpoint so uh what i'm doing here is first i need to set up this spring and let me get rid of this put these down here and so what i'm doing is just naming this application blogger and i'm adding some info to the endpoint so i'm saying info.app and then the name of that app is the same as whatever this is then the api version the api docs this is where you can find this at hey this is the department so this is really handy in maybe a company where you have a bunch of you know tons of microservices across different departments and maybe i wanted to add some info to this so if somebody hit this they're like oh who's in charge of this particular microservice oh i see here here's some information for me again this can be any information you want to attach to this endpoint so with that let's go ahead and run this and go back to the browser and refresh and now you see all of that information is here on our info endpoint so that's great if we go ahead and stop this and we upgrade our application to 2.6.4 and we run the application again you'll see that there's no information there so the reason for this is that enb info contributor is now disabled by default the contributor exposes any property from the spring environment whose name starts with info and you know after thinking about it we thought that this may not be a great situation you may have information on there that you didn't exactly want to expose but we're still going to give you that ability the only thing you need to do is enable it by using a property so we're going to do is we're going to come in here and we're going to say management.info.env.enabled is true so now you're not exposing that information by default if you come in here and rerun this and refresh there are our properties on the info endpoint the next change we're going to look at has to do with the application startup and one of the properties on the startup step that is being logged so we're back in our 2.5.10 version what i'm showing you guys what i'm going to show you right now is not a new feature but most people aren't aware when i talk to them so i just want to quickly cover it and then we'll look at what has changed so first off if you don't know the spring application.run is kind of a shorthand for this if we go in here and say new spring application and then we give it the class and then what we can do is we can get an instance of this we'll call this app and then we can come down here and say app.run and pass in our arms so this will this is handy you don't need to do this unless you need to change something about the spring application in this particular instance we will um so we get that um we get that instance back and now what we can do is we can say app dot set application startup so application startup if we look at it startup is an interface this again came in 2.4 as a new interface and there are two implementations of this interface so this interface pretty simple there's application startup um default here and then there are some startup steps and so the idea behind this is if you've ever tried to profile a spring application you might find that it's quite difficult because you end up in this same create bean method a lot and it's hard to tell which bean is the actual problem this interface allows you to get much more detailed information out about your application so as i said there are two implementations of it you could use the flight recorder application startup we're not going to use that one today there is also one called a buffering application startup and this is just going to take a value of the capacity here so i'm just going to throw something large in there for demo purposes and now if we go ahead and run this application everything looks okay and we head back over to the actuator there'll be a new endpoint here called startup so again you won't get this unless you define an app you know set the application startup so we got this endpoint now and in here there are a bunch of different metrics about what is going on so in 2.5.9 there is one called spring.boot.application.running and if you see it down here here it is so all that is changing here is if we were to go ahead and bump this up to 2.6.4 and restart this application this endpoint would be called spring.boot.application so instead of running it's ready so that's pretty cool feature again if you're not aware of application startup pretty cool stuff there so go ahead and check that out the next feature we're going to look at is records and app configuration properties so if you're using at configuration properties with java 16 or further records there's a change here that is going to help us clean some things up so back in our application we're on 2.5.10 i'm going to go ahead and create a new package we'll call this model and inside here i'm going to create a java class called author so this is a class we are going to go ahead and configure this with at configuration properties and we'll give it a prefix of blogger.author and of course intonjay is telling us hey if you're going to use that you need this maven or gradle dependency so i opened up the docs on another screen and we'll come over to our palm.xml and just go ahead and drop this in here save it and refresh maven and now that should be okay but we're also getting one more little complaint here that hey you need to go ahead and enable this so we're going to enable configuration properties for author properties.class and as we save that everything is good to go so now what we can do is we can come in here and we could say hey we may need a first name we may need a last name and we may need an email address and then what we'll need to do is we'll need to come in and generate some getters and setters for each of these properties and there we go so now what we can do is if we go ahead and build this it will generate the metadata we need to come into our application and say okay blogger dot author dot first name is dan blogger dot author that last name is vega and blogger dot author dot email vega gmail.com so there's our properties so everything is going to work good there now again we are on if we go ahead and look at our palm we are on the latest and greatest and that is java 17. so as we make that march towards spring boot 3.0 spring framework six we should start getting used to java 17. now that we're on java 17 we could take advantage of records and in fact if we come up here sometimes intellij will say hey what are you doing here this could be a record so let's go ahead and change this to be a record and the way that we do that is we can just say this is a record and this is going to take in a first name a last name and an email so that's all there is to the record that will work just fine now the problem is if we try to go ahead and run this we are going to get an error and that is going to say hey parameter 0 of the constructor author properties required a bean of string and you could not be found so what's happening here so let's take a look at kind of the generated code if you're not familiar with what a record looks like so a record is an immutable type it has a constructor that is how the information for this class is instantiated and then they're just getters there are no setters so what's happening right here is it's trying to call a setter called set first name and it cannot find it so what you need to do is tell spring that hey we're not we're not going to set these properties using setters what we are going to do though is set them using constructor binding so if we look at constructor binding says annotation that can be used to indicate that configuration properties should be bound using constructor arguments rather than by calling setters so that's the important part so now if we were to go ahead and run this we can see that everything starts fine so i'm going to go ahead and stop this we are going to minimize this little stuff here and go back to our palm and we're going to upgrade this to 2.6.4 save this refresh and the change that is coming in 2.6.x is this is a record we know that there is no way to go ahead and set this using setters so we know that the only way to instantiate this author properties or to pass in these properties is via constructor binding so this is really not needed and we can look at a class and there are you know when records were introduced there are methods on there to like find out if a class type is a record so we can easily look at that and say we don't need to be told that it needs constructor binding we're just going to assume that it does so in 2.6.4 we can go ahead and remove that we can run this and everything should run just fine and it does so that is if you're taking advantage of records in 2.6.x you no longer need to use that at constructor binding annotation the next feature that we're going to look at under new and noteworthy is the same site cookie attribute server support so the first thing i want to do is take a look at this article over on google and this gives a little bit more background on what this same site attribute is in case you're not aware of it i'm going to run through a couple of the highlights but i encourage you to read up on the subject if you're not aware of what it is so first thing you're going to need to understand is cross site and same site cookie context so basically we get through here every cookie that has a domain associated with it if that domain matches the external service and not the website in the address bar it's considered a cross-site cookie so in this instance the url is a.com the cookie is from b.com we're considering that a cross-site cookie so a cross-site cookie would be things like google analytics or loading a youtube video within an iframe on a website those are cross-site cookies they're not necessarily bad but those are cross-site they're not first-party cookies so in contrast a cookie access with the same site or first party cookie context occurs when the cookie's domain matches the website domain in the user's address bar so if it's a.com and the cookies4may.com that is a same site cookie so what's happening with this change in browsers and again this attribute has been around for a while but today if a cookie's only intended to be accessed in a first party context meaning what we just saw before there's two options that you can apply to this the same site equals lacks or same site equals strict to prevent external access again all of this is to help with cross-site forgery requests but few developers were taking advantage of the recommended practice leaving a large number of same site cookies exposed to these threats so by default forever this would just kind of default to none and everything's like wide open that way with the changes in the browsers what has happened is that they are moving to same site lacks and as we'll see in the example today even though it doesn't explicitly say lacks unless it's set the the browser treats that as a same site lax cookie so in an instance where you need it to be none you need to explicitly say that in an instance where you want it to be strict you need to say that so a lot of the browsers are up to date on this you can see in here that chrome has done this since 80. mozilla has got it microsoft has it so it's something you need to be aware of and the easiest way to get aware of it is by taking a look at an example and let's go ahead and do that now so here i am in my project i'm going to create a new java class we're going to create a settings controller and this is going to be a controller and inside of this controller we're going to create a couple of variables let's say private static final string posts per page this is going to be the attribute name so post per page and then private static integer we'll say um posts per page post per page default equals five so we're just emulating like a user's setting controller and we have those two variables there so we're going to set up a git mapping we're going to have the response body returned and we're going to say public integer [Music] command in set and we're going to take in an http session we'll call this session and we're also going to take in the http servlet request and we'll call that nope sorry i did want the response and response okay so now it should be okay so what we want to do here is we want to get a value again we're just kind of creating a scenario so we can see this in action so we're going to get an integer value and we'll cause value and this is going to come out of the git attribute so we're going to use that post per page so it's going to look up here and say okay let's use posts per page so we're going to try and get this out of the session the first time we go around it's going to be null so we need to check for that so we're going to say if it's null i want you to go ahead and set up default values so we're going to say value is equal to post per page default and then we also want to set this on the session right so we want to say hey that post per page we want to go ahead and set that attribute so post per page equal to whatever this value is so the second time it comes around it won't be null and we'll be able to get that value out of there so i also want to so once we do this there'll be a one cookie set by the servlet right they'll have a j session id attached to it but i also want to set our own arbitrary cookie so i'm just going to say response dot set cookie [Music] now actually i want to add a cookie let's add a cookie because we don't have one yet and we're going to call it new cookie and i'm just going to call this my cookie [Music] and we'll go ahead and just for the heck of it i can't see now local date time now to string and we need to import the javax.servlet.http cookie and then finally we've said we're going to return a value from here we'll go ahead and return the integer value 5. all right so now that that is done what i'm going to do is start the application let's head back over to the browser and go to localhost 8080 and as you see the value being returned is five now let's go down into application and go into cookies and we see two cookies here so the first cookie we see is that j session id this is because we set something on the session so we set a session value for posts per page we set it to five and then we have my my cookie which is the cookie that we went ahead and set using that add cookie on the response now if you look in this column over here there is a same site attribute and both of these are not anything so again there are three values that you can set for this none lacks and strict but for some reason it doesn't say anything here but we know by reading through the documentation that that is in fact set to lax so we want to be a little strict about this and say hey let's go ahead and set our default session to lacks so we know that it's lacks in case you know this default value would change in the future let's let's be explicit here and set this to lax and we can do this for anything that the servlet is creating for us so in in this case this one and the way that we can do that is if we head over to our application.properties we can say server.servlet.session.cookie.samsung equals lacs so now let's go ahead and rerun our application we're going to refresh this and now we'll see that our j session id cookie here is set to same site attribute equals lacks so now the question becomes how can we do this for our own cookie because we actually did this here in the response we're adding a cookie and we just create a new cookie and so the first thing you would think of is hey we should be able to just go ahead and add a value some type of value to this cookie class and set a same site attribute and that's not the case so this is actually part of the java ee so we have this javax.servlip.http package and this is you know just for a little history this is the one that was donated to the eclipse foundation so this is not an api that is going to be evolving everything is moving over to the jakarta space namespace so once we get to spring boot 3.0 spring framework 6.0 we will have the ability to evolve because we'll be on the jakarta we'll be on the jakarta namespace and those apis will evolve but for right now we're stuck here on java x and so we can't go ahead and just change it there so the good news is that doesn't really stop the individual vendors from adding support and in fact they've done so but the bad news is it's different for everything like tomcat and jetty in undertow so with 2.6 if you want to be able to go ahead and add change of value for change the attribute for same site on a cookie that you have written yourself then you can do so using a bean so we're going to create a bean here and this bean is of type cookie same site supplier so let's say cookie same site supplier and what we're going to do here is we're going to return cookie same site supplier but now we can go ahead and say what we want this to be so let's say that we wanted a specific cookie like the my cookie one to be of strict so we could say of strict and then we can also say we can go ahead and add these filters so there's filters here that take predicates uh if you just want to do one has a name one has a specific name so we'll go ahead and do that so we could say hey when the cookie is my cookie i want you to go ahead and be strict about it so now if we go ahead and rerun this and we refresh this we can see that our cookie that we created now has the same site attribute of strict and the cookie that was created from the servlet now has a same site attribute of lacks so that's again just some changes in 2.6 that allow you to set that same site attribute i would take some time to read up on it a little bit and how it works but as you just as i mentioned before the browsers have changed the way that they default this to a lacks now instead of none so there may be some changes in applications that you probably have already come across but now there is a solution to kind of change that here in springboot 2.6 the next new feature i want to look at is plugable sanitization rules so by default spring boot sanitizes some sensitive values that are present in both the env and config props endpoints of the actuator so if we scroll down we'll see config props and we'll see e and v so if we have things in there that match what we are calling sensitive data then we will kind of sanitize it and replace that data with some asterisks so let's take a look at how this works today and then we'll take a look at a change in 2.6 so what i want to do is intellij i'm going to come up here and i'm going to go to run and i'm going to go to edit configurations here in my environment as my program arguments i'm going to go ahead and add a few command line arguments so i'm going to say dash dash api dot secret is equal to password and then i'm also going to say api dot version is equal to 1.0 so the idea here being that we would not want to expose this password in an environment endpoint but this is not data that we care that needs to be sanitized so let's go ahead and display that so let's hit apply okay let's go ahead and rerun this and head back over to here and then go to our environment so in here we have our different property sources here's one of them which is a command line argument so we can see that api version is displaying as 1.0 but that api dot secret has been replaced that password has now been sanitized we're just displaying these asterisks and so how does this work so if we go ahead and look in sanitizer you'll see in sanitizer there are some keys that it's looking for um so did i miss them i bet i must miss them because it's very large yep so here is our hashtag so anything that has a key of password secret key token credentials anything in this list it will go ahead and sanitize so what happens if you have something that is not in that list and you want to sanitize it so this is where the new feature in 2.6 comes in and allows us to write our own sanitizer function so what we're going to do is write a new bean we are going to return a sanitizing function i'll call sanitizing function and sanitizing function is actually a functional interface with a single method called apply that takes in some sanitizable data sanitizable data has things like the value to be that we're going to sanitize with the property source so as we saw before that property source that we are working with was the command line args and then the key and the value that you're going to get so because this is lambda we can go ahead and say return data and we're going to get that data and what we can do with it now is we can say go ahead and give me that property source and if that property source's name get name is equals to dot command line property source name so if that's equal to that what we're going to do is going to return with value and now we can supply our own value so we could say this is top secret and if it's not we can just go ahead and return the data so again what we're doing here is just taking a look at the data that's coming in and if it's from the property source the command line property source so if it's a command line arg then we're going to sanitize it no matter what so obviously there are different reasons that you may want to sanitize things or different functions that you can create this is just an example of one of them but you can see i can get creative here and and really kind of customize it to your needs so now what i'm going to do is go ahead and let me just add one more in there so let's go to edit configurations and let's just say api dot name equals blogger service and for whatever reason if we wanted to sanitize anything coming in from the command line we could so let's head back over here and if we go ahead and refresh this you can see that api version and api name are both top secret and then the original one that is caught by the default sanitizer is still the same because it has a secret on it so just a a another way for you to go ahead and configure some some plugable sanitization rules depending on the needs of your application the next feature i want to look at is the info endpoint can now expose java runtime information under the java key so the way that we do this is here in our application.properties we're going to go ahead and set a property that is management dot info.java.enabled and you can see it was enabled it was not enabled by default so we need to set that to true so if we go ahead and do that and we rerun our application and we head over to the actuator and we go to info you'll see all that other stuff on there but now there is this java endpoint so or this java key and this java key is going to give us information like the vendor so i'm using java 17 from oracle and then the name the jvm so this will be helpful getting this information it's not always available so maybe on some cloud provider you want to have an endpoint that exposes what particular ins version of java you're using or what vendor specific version of java you're using this is a good way to kind of go ahead and expose that and again we're just going to add a key into our properties here to enable java on the info endpoint the next feature under new and noteworthy is the build info property exclusions so it's now possible to exclude specific properties from being added to the bill dash info.properties file that is generated by the spring boot maven or gradle plugin so if you're in the release notes we give you a snippet there to add to your maven or grado build uh i am in maven so i'm going to open the palm.xml head down to the build plugin so this is the spring boot maven plugin here this is where we'll want to add that exclusion but i just want to show it without that first so this is really when you're running if you go into maven here there is a spring boot build info you can run this from the command line if you want i'm going to run it right here and now if we look in our target folder we're going to look in meta imp there's actually a build info dot properties you can see that it includes the artifact group name time and version so if we wanted to exclude something like the version we can go ahead and put this in here so this little snippet says hey go ahead and exclude info properties and i want you to exclude the version property so i'm going to go ahead and save that and we're just going to run that again and now if we look at the build info.properties the version is no longer there so just a handy way to go ahead and exclude things like the group artifact name version or time properties the next feature we're going to look at is message source based interpolation of beam validation messages so what does this mean so let's go into an application where we might be validating some data some user input and we need to validate some of the properties on that first thing we need to do is we need to open up our pom.xml even though we have this web dependency here we still need to include the validation dependencies the validation stuff was taken out of the web dependency and it's oh it's its own dependency now so let's go in here and say spring boot starter validation and there it is and we'll go ahead and refresh and great so now we can do is we can go ahead and create a new class and let's just call this post and inside of a post we may have some properties so we could have things like a private integer id we could have a private string title and maybe a description and also maybe a date time of when it was date created so that's enough for demo purposes so we have these different fields on the post class and what i'm going to do is go ahead and create a constructor that allows us to create an instance of this we'll create some getters and setters this is a perfect time to remind you that in java 17 you can use records for this and it makes everything so much easier but i'm just being verbose for the sake of being verbose here okay so we have this and let's say that we had a post controller which we already do and we wanted to take this information in so we might have a post mapping here to slash posts and this would return nothing and we could create a new employee based on the request body so the request body allows us to go ahead and send some json in uh this is a post post and there we go it figured it out and let's just say i want to print something out which is the post so if we were to go ahead and create a new instance of a post using some json everything would go through fine now what if we had some constraints that we wanted to set up like let's say that the title could not be an empty string we want to make sure that we are not getting an empty string here so what we can do is we can go ahead and add one of these validate validation annotations here one of them is not empty and if you go ahead and click on this and look in the java x dot validation.constraints package you'll see a bunch of them here you can check for like decimal min and max an email make sure it's future present maximum there's a whole bunch of them here and so these are the annotations that we can use to say hey we want to make sure that we validate this particular field somehow so now what we're saying is title cannot be empty so let's go ahead and figure out how to test this what i want to do is run this application and i could use something like postman to go ahead and test this but i'm in an intellij and i can go ahead and actually generate this request right here in intellij's http client so here i'm saying here's what a i want to go ahead and create a post request to localhost 880 posts the content type is going to be application json and then the body is going to look like this so we're going to pass in an id which is one a title which is going to be empty i will pass in a description uh which is this is a description and then a uh what was it date created so this is dates created and this can look something like um 3 eight and i think we can get away just with the date and that should be fine so we have our post request now let's go ahead and try and send this so right away we get a 400 so 400 status code is telling us hey this is a bad request you're trying to post something to posts but the data i'm getting is not good so so far so good one problem i have here is i don't have enough information there's no error message and there's no like validation messages here so at one point there was a change made to take this off of the stack trace here or the the error response um so let's go ahead and take a look at this so there are a couple properties so if we want to set server.air.includemessage so we want to include the message we'll say always server dot air dot include binding errors as always as well so this is going to give us two things we'll now have a message key in here with the actual error message and then there are binding errors uh it'll show those errors so let's go ahead and restart this go back to here and run a post and you'll see uh cannot deserialize oh so this is not it wants the actual date time so let's do that all right so now we have a 200 and the reason for that is is here in our create method we have not said hey we want to validate this request let's go ahead and validate this request the way that we validate this request is with an annotation at ballot as the json request comes in and we create a post object out of that now spring boot is going to say oh okay now that we've created a post i need to validate that so that valid annotation is directing spring to validate that post object and then as it validates it it'll take a look at all the validation annotations on that object and see if anything passes or fails and let's hit this again okay now we have much more information coming through so the validation failed for object post your account one here's some information about it the default message is just title so it's just saying title default message must not be empty so one thing we can come in here and do is add a little bit more information to this maybe we wanted to supply our own default message so we want to say the post title must not be empty so now if we go ahead and run this and hit that end point the post title must not be empty so this is a great start but there's a problem with this right this we are hard coding this message on this annotation here this not empty annotation so what we would rather do is especially in a case where we want to use internationalization where we may have a translation for this validation message in another language you know there's no way to do that right now so bring in spring boot 2.6 and we now have a way to do this so what we're going to do is we're going to use a parameter here so we're going to say post dot title dot not empty and this is the parameter and then let's close that so now we can do is we can create a message.messages.org and we can say post.title.not empty why in the world would you leave this empty and now if we go ahead and restart this there's our message and now more importantly we can use this across different languages so let's go ahead and translate this into french all right so i've just done a little translate here translation so let's grab this and what i'm going to do is create a new file messages underscore branca dot properties and then we're still going to have that key right so that key is post dot title dot not empty and there is our message and we just need to go into application.properties and change the locale right now to francais and if we go ahead and run this again and we hit that endpoint we now see that's been translated into french so just a little history about around validation and how you validate uh data classes and then now in spring blue 2.6 we have the ability in our data classes where we're trying to use these validation annotations to use these parameters and this parameter will now be found if it's in messages.properties or a another locales property file if this is not found so if you if you misspell something here and just say post.title.empty it's going to look for that key in the messages.properties when it doesn't find it it's actually just going to display the literal string post.title.empty so it has to match up if it does you're going to go ahead and get that validation validation message so i think a really great addition to springboot 2.6 is the ability to have message source based interpolation of being validation messages the next feature i want to look at is using webtest client for testing spring mvc so what we're going to do here is actually in our post controller let's just create a new method we'll go ahead and say that this is a git mapping to slash posts and in here we're going to create a method that returns a list of posts do i not have a post set up i do not uh let's just call these strings find all posts and return um list.of post one close to two and post three so there's our method and what i want to do now is go ahead and create a test for this so i'm gonna come in here and i'm going to say let's generate a test and we're going to test find all posts and i'm going to say okay so the change now is we might so in the past we might have had a mix of tests where we're testing spring mvc and webflux endpoints and in certain scenarios we might be using something like the rest template and other scenarios we might be using the web test client and so what this does it it just kind of gives us a way to unify the way that we invoke our controller endpoints using the web tech web test client across the board now there was a way to do this prior to spring boot 2.6 but because of some changes in a recent version of spring you could go into the before each method and set up a web test client and basically bind to the mock mvc but this change basically allows us to use a web test client to tu to test in any mock environment or spring web apps against live servers this change also enables the web test client for spring mvc mock environments or basically any class annotated with auto configure mock mvc will get an injected web test client so what that means is if we come in here and we create a web mvc test and we say this is a post controller test specifically what we're going to do now is i'm actually going to go ahead and make sure spring web flux is on the class path and it's not so let's go ahead and say that we need a dependency on spring boot starter webflux go and now if we reload this now in our post controller test one thing we can do is we can get an auto wired instance so we'll say auto wired private web test client we'll call this web test client and so now that has been injected for us we don't have to go through kind of the glue and and going kind of a hacky way to get this in here so now right in our method here we could say web test client dot get dot uri and we'll say to whoops what happened there say to slash posts and then we'll say go ahead and exchange and we want to expect the status is going to be is okay and we also want to expect the body to have json path we're basically going to check the size is going to be three so that's all there is to that now we should go ahead and be able to run this test and because there were three in our post controller we can see that this test pass and everything is okay again being able to inject this web test client into your test class now just kind of unifies this across all of your test classes just a great little change to testing our controller classes so there you have it what's new in spring boot 2.6 we really hope you enjoyed this video now we know that we couldn't cover everything that's in the release notes so if there's something we didn't cover and you'd like to see us cover it or you want a bit of a deeper dive into one of the features we did cover please go ahead and leave us a comment below and we'll see if we can get to that i also want to let you know that we've started a twitter community for spring boot developers i'll leave a link in the description below we'd really like to see you join the conversation there until next time friends happy coding
Info
Channel: SpringDeveloper
Views: 65,131
Rating: undefined out of 5
Keywords: spring, pivotal, Java (Programming Language), Spring Framework, cloud foundry, spring boot, spring cloud, java
Id: 4L4LEnawcO8
Channel Id: undefined
Length: 66min 39sec (3999 seconds)
Published: Fri Mar 11 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.