 Okay, are we ready for the next talk? Is that? Okay, thank you. See you guys. Okay, so I'm Stefan February. This is me. I'll be talking about spring boot configuration. I will not be covering any parts of actual Cloud Foundry, running Cloud Foundry deployment tonight, unless Tapping agrees to come and play with me and show me how it's really done. Otherwise, I'll embarrass myself. What I will do is I will talk a little bit about spring boot configuration. We'll do a bit of a code. I'll do a bit of live coding to show you how to actually get it going. It's quite easy to actually build the application yourself, just from some basics. My technical blog, which hasn't been updated in almost a year now, is hashtagbin. Yeah, that's me. So, spring boot configuration. Now everybody now. Okay, so first of all, apologies. I did a bit of a bait and switch. I threw the word microservices into the description on the Meetup group, because we all like the buzzwords. So, microservices. So, just to satisfy those of you who came here today to talk about microservices, 12-factor applications. So, we all know about the 12-factor applications if you haven't already. 12-factor.net lays out some really nice 12 points, almost like a modern manifesto for how we would like to deploy and manage applications for scalability, maintainability, and all the rest of these things. The third point of the 12-factor is actually configuration. Anybody who's ever deployed or had to maintain or manage an application in deployment knows that configuration is a bit of a nightmare. And it's actually usually the thing that trips you up and that gives you all sorts of nightmares when you're trying to manage an application. So, the 12-factors actually state that we should store our configuration in the environment. What they really mean is let's externalize the configuration that the configuration ought to be kept inside. Now, spring already provides for externalized configurations. It is the spring framework that is. It is not that difficult to actually externalize your configurations. It's been around for a while. But externalized configuration does have some issues. It means that once you've actually changed your configuration, you typically have to restart your server. There's pretty no life reloading or reapplying of your configurations. There is no audit trail. In other words, unless you are actively, unless a part of your application, the resources folder where your application lives, is managed in a separate GitHub repository, you kind of stuff because you won't actually have a log or a change log as it were to know what have I done or who has done this change in the config server or on the configuration of my application. That information is gone. Typically, it's decentralized because the applications all have their configuration managed locally. Even if it's externalized, that tends to be decentralized. That's why we have things like puppet and shift to try and push out these configurations and manage them from a central location. But decentralized configuration, even when you're externalizing, it's a bit of a problem. And then, of course, there's the problem with encryption when your configurations are at rest, even if it's externalized. It could be a bit of a problem if you're storing, for example, clear text passwords in those configuration files. So this is some of the problems. We'll get to some of the solutions later on. Did you want to ask a question? You just did the old... All right. So why do we want to do good configuration? Well, you've got runtime logging. For example, you want to at runtime change your login level and actually see your application respond. So Dapeng actually messed with his server and he crashed it. One way that could be debugged with live... If he was able to, for example, say for this particular instance running there right now, the one that keeps booting, or even for all of them, just up the logging level to debug just for the next while, I tried to figure out what the heck is going on. And then you do a Cf log to tail and see basically what is going wrong. That would be massively helpful. No application restart needed. You just basically say up the logging level, promoting the application for these packages, the way that we can do it with log4j, right? You say, I only want spring framework boot. I only want that part of the logging for those packages to be up to debug because I know somewhere in there it's crashing, right? That's very helpful. And then, of course, feature toggles. You have a feature flag somewhere that's in configuration. You want to turn things on and off and see what happens after you've deployed. And, of course, we'd like to protect our passwords at risk. Spring boot configuration allows for us to encrypt our things and actually manage those cryptographic keys in a really nice manner. Okay, so configuration flow. I hope this is actually the diagram is clear. I'm going to try and explain what happens. There is a one. There's a two. And there's a three. There's a GitHub repository in the mix here. Over here is where the developer typically would be sitting. The spring boot config server is the one on the top right-hand side there. And then at the bottom here are three instances of your application, right? Or even three different applications. It depends on you. The way you do this is you push your changes to the GitHub repository. By now it should be obvious that at least one way of managing your externalized configurations with spring boot config server is to externalize them in the GitHub repo. So let's say you have a GitHub repo where you now decide, okay, this is my application configuration repo. I'm going to clone this repo locally and I'm going to make some changes to my application. I'm going to push this file up to the repo. Once the file is in the repo, the config server will actually take the change by a web hook and actually pull it in. It will pull in the change and apply the change and keep the change within its own state internally. Now the config server knows about that change. The config server is now ready to redistribute that change to everybody. But it doesn't just push it, right? They have to ask for it. So you now have to go to the application and there's a way using actuator that you actually just say, okay, pull the configuration change for this guy. Or you can say refresh the configuration for this server and that will actually trigger a pull on the config server and all of the configurations will be pulled down and then applied into your local state of your application. All right. That's enough talk. Now we're going to demo and do some stuff with keyboards. How are we doing for time? Okay. So what I'm going to be doing now, I actually need to write two applications. I need to write the config server and I need to write the client instance, what you saw at the bottom there. App A, B and C. I'm going to be doing app A. If you want to scale it out, taping has to come and help us. But for now, we'll be writing the config server and app A. It's not going to be particularly long because it's spring boot. We are going to win. All right. First thing you want to do, I've already gone to, if you're not familiar with run, run the Pivotal IO, not run. Start. Start spring.io. Right. Spring.io initializer. You can generate sort of a skeleton, basic skeleton for your application from here. You can choose whether you want it to be a Maven or a Gradle project. Choose the version of spring boot you'd like to use. And then you can sort of add in all of the spring boot packages that you would like to have added into your starter. I basically came here and the only thing that I changed was I changed my group and the name of the artifact. And what it ended up with is basically this config demo.zip file that we have here. So I'm going to unzip config demo and config demo is exactly the same thing right now. I'm going to split it into two applications, create two subfolders, import it into my ID and then we're going to go from there. Just give me a second. I just need to double check and confirm that I'm recording the screen. Yes, I am recording the screen. All right. Let's unpack this file. Right. I've got it in the config demo folder. I need a client in the server. So I'm going to move the config demo folder to config client. I'm going to unzip it again. And I'm going to move this copy to config demo to config server. Right. Now I have two instances of my application. First thing I'm going to do quickly, I just want to show you guys where I am. I'm in this folder. You can see it in the command line here. I mean idea projects, config dash talk. And there's an app config folder here. In the interest of time, this is actually a link to my... Sorry, this is my remote Git repo. It's a publicly configured repository at the moment. We'll come later to how you secure access to your Git repository. But for now it's a publicly accessible repo, which means that even you guys can pull my application configs. Although, of course, you won't be able to push things into it. But at any rate, let's have a look. Start with... I didn't show you what was in that folder. I've already got a whole bunch of things in here. We'll create a new configuration file, a bunch of YAML files here, which is some externalized configurations. We'll create something new. Let me quickly go to GitHub. Right. This is the app config repository that I'm talking about. I'm going to import these applications into my IDE. So I'm going to create new projects. Let me import an existing source base. Config client, config talk, config client. Import it as a Maven project. Yes, it requires us to do what we need to do automatically. Since I need to actually... Which one am I doing first? Did I say the server or the client? The client? Okay. All right. I'm also going to do the server. So I'll open two at the same time. One from existing sources. This time, we'll do the server. Okay. Carefully import automatically. Remove Ruby. Okay. Carefully import automatically. Remove Ruby. All right. I'm going to do a quick bit of housekeeping. Before we actually get started, one of the first things is I'm going to change the artifact ID for the server to actually be config server. Going to go into the client. I'm going to change the artifact ID for the client config client. I'm going to do the same for the name. Okay. Let's start with the server. In order for something to be a config server, it needs to have this funky annotation called enable config server. Then you're a config server. Where does that live? Okay. We need the spring cloud bits. So in my Maven project, I'm going to do or spring framework cloud. Right. This is spring cloud server. Which one? Cloud config server. Okay. Sure. We can do a release as well. You can specify the version of the server that we want. Anything else that I need here for now? Let's say no. Anything I need, because this application has automatically been generated for me, a skeleton application has been created. I'm going to enable config server, add the enable config server annotation to the spring boot application entry point. Let me get this out of the way. All right. Then I'm going to hit the command line immediately and fire it up. So config server. Because I'm pretty much done with that. Let's do Maven spring boot run. I'm going to run this here instead of in the IDE so that we can see the entire log of what's actually happening. Let me open the new tab. Go to the first one. And we are booting. And we failed. What did I forget? Ah, of course. I did not set up a repository. Okay. So, other thing that I dislike is properties files. I like YAML files. So let's create the application dot YAML. And I can never remember. The reason why I have my notebook here is because I can never remember the spring cloud config cloud config server cloud config server git. The git config. Git URI. Yes, the git URI that we want. Come on. Boom. There we go. So I know that my git repository lives at Stefon Fib. And this particular one is appconfig.git. Right? So let's try and start this guy up again. All right. Seems happy. Okay. That's the server done. Now our server is basically going to start pulling configuration information of the, of the, of my, of the server, of the GitHub repo. A bunch of the end points have automatically been created for me that I can already see here. I can, for example, go and look in. So one of the, one of the nice things that you get out of the server, it started on local host AT-AT automatically. One of the nice things is if I go to config client, something interesting is going to happen. Now the reason you're seeing this is because if I go to my GitHub repository, let me go to the GitHub repository. When you go to the GitHub repository, there is actually a file here called config client. Now I don't know how many, how many of you have worked with Spring Boot before, but Spring Boot has this opinionated way of picking up its configuration files. So when you have a configuration file in the resources folder locally, the way that those configuration files are actually identified is through this little algorithm that it applies where it first looks to see whether or not it's a YAML or a properties file. YAML files have precedence of a properties files. Then it looks to see whether or not you have some, you have the Spring dot application dot name environment variable set anywhere. If it isn't set, then it will look for, from the artifact ID, basically what your application name is. It will infer that. That will be the name of your Spring application. It will look for, application dot YAML is the default one. Any configuration in there will be applied. The next one is whatever that environment variable for the name of your application is. It will, sorry, Tapping, I'm going to turn off your phone here. Whatever the environment variable is, it's going to give, say if my server is called config server. Config server dot YAML, that's going to be the one that takes next level of precedence. If my config server, if I've configured Spring profiles for development, testing, et cetera, if I add a Spring, if config server dash something else in there. So for example, I'm going to give one here now. This is just by way of showing that I can actually have another configuration file in here, something like if this file was called config dash server dot YAML, that could, if the application was called config server, that YAML file would be picked up. If I had two different profiles that I would like to, that I've configured. Say for example, actually YAML files work in such an interesting manner that I can have both profiles active in separate documents inside the YAML file, right? A document is denoted by the dashes. Spring profile, active profile there. Spring profile here. Set the environment to the profile that I want and I will get it. For now, let's just say that my application YAML is being picked up and it's actually pointing at where my Git repository is. Now because of these rules about how to infer the file name of the config that I want, since I've enabled my application to actually go and reach out to a Git repository to pick up configuration information, it's read the entire Git repository. It's picked up everything in there. It's picked up the client config dash demo YAML, client config. Now the reason why this is interesting, the names that, every one of the names that it's picked up is because if you recall from the slide that I showed you before, which was this one, was it that one? No, it wasn't that one. No, yes, it was this one. So if you recall from this slide, right, the actual, the way that things actually work is that the client who is the guy who is a BFC is actually the guy who wants the information, is the guy that wants the configuration changes. And he will have to ask the config server. But he's going to have to ask the config server for something. Now because we were spring booting, there is some level of opinionatedness built into the framework. The default naming conventions that apply to your local configuration in your client application will automatically be applied on the config server. So if my application is called app, if I have a configuration called app-a.yaml and my application is called app-a, that file on the config server is basically going to get pulled. And where is the config server going to get it? The config server is going to go and get it in my Git repo, right? So back to the code. Right, next thing I'm going to do, I'm immediately going to jump in and build out my client application, right? Let's do that. Change to the client application. What do I want to do? Right, first thing. This application, before I start running it, I need a few things. This needs to be a RESTful application. I also want actuators so that I can do a nice, interesting actuator. It's going to give me a bunch of extra stuff. So I'm going to first make it a spring framework. Let me pull in the cloud stuff. Spring the client config. So I need to have the client configuration. It needs to know, okay, I'm basically a config client. I need to go and look somewhere for my configurations. Next thing that I'm going to do is I'm going to ask for spring framework REST controller stuff so that I can basically make myself a, I can ask spring boot to make me a spring, I'm going to spring data REST. So start a data REST, right? And I want actuator. So actuator is going to give me all the nice little endpoints, automatic endpoints for my application. So or spring framework boot. And I like it when the ID is always so helpful. It gives you all of these nice things. You can just look it up without having to worry about where it's actually coming from. First things first, let me go and create a controller that actually, so I'm going to create a new package, create a controller, create a controller folder package there. I'm going to create my greeting controller. And this is just going to be somebody who's going to basically say hello. This guy is going to be a REST controller so that it knows about how to return certain types of thing. I'm going to give it a request mapping so that it knows how to handle hello. I'm going to return a string and say hello. And I'm going to return hello dot dot dot. Right? And that's it. I'm going to start it up and cross my fingers. Let's not start today. My dear project is config talk. Config. This is the client. Get maven, spring boot to run. Make sure I'm not missing out anything that I want to touch on. Ah, crash. I love crashes. Tell you what you've done wrong. You have something running on the same port. What did I do? Ah, running on the same port. Oh, okay. All right. That's an easy fix. The config server actually starts up on the port 8888, like 4-8s. So I'm just going to force it back to, sorry, to run on port 8888 for the config server and keep my client where it is. And the reason the config server runs on that port is completely just some developer at spring decided that by default the server will run there and also that by default any locally run config clients on the same machine will go look for localhost on that same port. I'll show you guys a neat little trick in a second about how to figure out what the opinions of spring boot is because this is actually something that I found incredibly useful. Let me rerun this guy. Confirm this guy is now running on port 8888. Okay. Start it running. Can you guys see this? Should I make it larger? Okay. All right. Start up this guy. Okay. Up and running. Now, the first thing that I want to do is I would actually like for my client to go and look for a configuration on the server. So how do I tell my client, you know, you really should go and find any environment variables. Now, we all know, is everybody familiar with the value annotation? The value annotation in spring is really nice because it allows you to grab properties or variables, environment variables from properties file or from the environment. So if there is a variable environment called greeting, it will go out, will grab that, and it will apply that. The way that it normally does this is by going to look for... Sorry. I will need to make this change in the application YAML. Hang on. I don't have a YAML file here. That's something I haven't done yet. Sorry. So let me create an application.yaml for the client and quickly make sure that the client actually is more or less configured for what it needs. So my client is ready to say hello. I've got this variable bound. Sorry. I need a private string here. I'm just going to call it greeting. And instead of returning hello, I'm going to return the greeting. Now, this guy needs to be told that there is actually an environment variable somewhere, right? So this environment variable greeting doesn't exist right now. Usually what you would do is this. You would say, okay, in my YAML file or in the environment, either via properties like minus D, greeting would be something. So I'll just now make greeting hello everyone. Which... Oh, the thing that I didn't show you probably was I didn't actually visit my local host to show that the hello endpoint was working before. So this is still the old hello for that the controller was returning. I'm just going to shut down the client and run it again. I don't have JRebel. If anybody has $500 to give me so I can buy JRebel, so I can have auto reload, you know where to find me. There is actually an auto restart feature inside Spring Boot as well, which I haven't turned on. Okay, so now it's reloaded. It's picking up hello everyone, but we don't want this guy to pick up hello everyone. We want this guy to go and look at the config server and pick up something from the config server. And in order to do that, we need an annotation to basically tell this guy, okay, a lot of the stuff that you're looking at here should be obtained from the config server. And that annotation, which I just mentioned, is enable configuration properties. The moment that I've enabled configuration properties for this class, it will actually go and look up configuration properties from somewhere and try to apply them to my greeting. The other thing I'm going to do now is immediately, there's one more thing which I've forgotten to do. The binding between this application's name in the greater scheme of things at the moment is wrong. This application's name is not what it needs to be. I'm going to give this application a name, but for the sake of the demo, I'm going to give it the name that corresponds to one of those YAML files that already exists over here, right? So I've got this config-client YAML, so I'm just going to give it that name. We'll come back later if we have time and we'll play around with it and create some other files and other file names on that repository. So in my YAML file, alongside the greeting, actually, yeah, okay. There is also another file called bootstrap.yaml which takes higher precedence than your application YAML, which is, of course, where bootstrap things that should run before everything else gets picked up, but for now, let's say that application.name, we want the spring application name to be config-client, right? This should actually allow us to go and pick up the greeting from elsewhere, right? Let's hope this works. Actually, it shouldn't work because I know for a fact there is no greeting configuration in that file in the config server. In fact, I hope it doesn't crash because it can't find the config variable. There we go. Can't find the configuration variable. Now, this problem that I'm having here is because there is an intermediary step which I'm going to skip over. I'm going to skip over directly to the advanced version of the talk, which is that I'm going to create, I'm actually going to bind the... Actually, I don't want this package here. What I'm going to do is I want to bind my configurations to a beam. For me, that's just going to be easier, right? We like that. We want our configurations to be picked up from a beam. So, let me call it config settings. Create a beam called config settings and in this beam, I'm going to create a string called, shall we call it greeting? Rather imaginatively. I'm going to make this into a proper beam with getters and setters. Why does it keep giving me files that aren't properly indented? Okay. First thing, I'm going to add the annotation for making this a configuration properties file. The configuration properties, I'm going to give it a... Just ignore this annotation processor thing up here. The configuration properties, this configuration properties file actually has this thing called the prefix, which I'm going to leave off right now. So, I'm going to make it pick up things from the default scope. The other thing that I need to do is I need to go and tell my REST controller that it actually needs to pick up the configuration properties from my configuration properties config settings file. So, I want to enable configuration for config settings of class. I'm going to have to import this class. Why isn't it picking up my class? Did I misspell my class name? I'm in the client class config settings in config. Okay. I'll get back to that in a second. Let me auto-wire in the config settings class. What did I do wrong in this config settings file that nobody wants to have anything to do with it? It's just a regular Java class. Am I going mental? Oh, I know. It's the flippant package name, isn't it? Nope. The package name is correct. io.pivotal.config. Public class config settings. Preview controller. I know what I'm going to do. I'm going to rename it in case something in the IDE is really messing with me. And my IDE is locked up now. Brilliant. Okay. I've had this problem before. It really just needs you to wait for it. Here we go. And we're back. Let me rename this guy. This is the weirdest thing. Import the REST controller. Import my values. Just drag to the other end. Just drag from that to the other end. So that can send package back. Yeah. This is... Just drag that in. It's weird, right? Yeah. I'm not going crazy. I'm not... I'm not losing my mind. Enable auto-configuration for this guy. I want to... So this annotation for enabling auto-configuration. Yeah. Then it knows it now. This auto-configuration will allow me to bind the... Where am I now? I mean the greeting controller. But I don't want this guy anymore. I want to auto-wire in my config setting, right? Create a local config setting. And then I will return config-setting.getGreeting. In this way, since config-setting will be auto... Will be automatically enable auto-configuration from the prefix. It's configuration properties from the prefix. I think I've mixed them around. Always get them wrong. Enable auto-configuration does not actually have that. Enable configuration properties for this guy. We should let him allow him to automatically be pulled in. So if we auto-wired in the config setting, this will basically auto-enable configuration of the config setting. Create a bean for it. The bean will be bound to all our properties. And that should hopefully just run build failure. Enable profits. Sorry? Enable config setting is not... Enable auto-configuration. Yeah, config setting. It's not? It's complaining something. Yeah. Cannot find anything. Yeah, I don't think it... I think I've got the wrong annotation here. I have the wrong annotation. That means that this guy is the other one which needs to be the auto-configuration client. Okay. So, really? No configuration properties for IOController annotation found on... No configuration properties? Ah, it's... No, sorry. It should be the configuration properties. This is the annotation. It's a configuration properties annotation. What the prefix is typically default. So, the reason why there's a prefix here is because when you have a configuration file that has a config property like spring.application.something, typically in your YAML file, you would have something like the application YAML, spring application name, and then here you'd have something else and then another thing. And on the same level here is basically what will be configured by the config setting here and automatically bound to this guy. So, I'm going to... Because I've been failing failure mode, I've been failing for a few seconds there. I'm going to say my prefix is failure mode. I'm going to go back to... Now, this is going to fail. I'm going to run this again. It should stay up this time, hopefully. Right, it stays up. The thing that I want to show is that when I go... What I expect when I see when I go to this hello endpoint is an empty string. It's empty because there is actually not a configuration anywhere in my application that corresponds to the value that would map onto failure mode dot greeting. And because that actually would be what gets bound to my config setting here, the config setting would be... The bean for that would be instantiated by this annotation, the enable configuration properties, and the auto wiring would then take care of tying that bean into my controller. So, how do I fix that? The fix for that is basically that I need to go into... Let me blow this up a bit. I need to go into my GitHub repository, modify the appropriate configuration here. I'm going to edit this one, and the reason I'm going to edit this one is because the fact that I've chosen the name for this client application to be config client, so the file name corresponds to that. I've cheated a little bit, so I'm going to... I've already created one before here. I'm going to create a new one now, which should correspond, if we recall correctly, to failure mode... So, failure mode greeting. Hello, CF. This configuration now needs to be pushed to the GitHub. While that is pushing, the server which is running here should pick up the new configuration changed. The Git push has exceeded. The server at some point will get a notification that something over there has changed. This is the client application which is running here. I'm going to issue a refresh on the client server by doing a curl minus x local host onto the client. At the endpoint is actually... Because of actuator, the endpoint is refresh. Local host, okay. Method not allowed. Why is it not allowed? Of course it's allowed. Didn't I tie up my actuator to the application? You have to have a refresh scope enabled on the variable. You are right. But that is not my problem at the moment, though. Yes, you are correct. I need refresh scope on the annotation here. But also I've forgotten to add something obvious into my config, my YAML here. I've got Spring Boot Starter. I've got the config client. I've got data rest. I've got actuator. You don't see anything obvious. Okay, I'm going to cheat. The easiest way to cheat is to look at your previous example. Which is... Okay, never mind. Are there any questions so far? Let me ask that. People have been awfully quiet until now. Any questions so far? So, why did the config client is running to the server? The config server? Yeah. Where is the exact configuration? So, that is the place where it actually... It infers that. So, it will right now... It's actually looking on localhost at the specific place. And that is an inferred setting. Remember before I said that in order for us to actually... If you wanted to figure out exactly where all these things are pointing to, what you can look at are places like these in the configuration. There is this very specific spring framework import for spring boot cloud called auto-configure. This import here. And if we look for the cloud configuration, we'll see cloud auto-configuration, which will point to other parts of the application like cloud scan configuration. That is interesting. It thinks that some of these files are missing. Some of these dependencies. It's missing them. Okay. How are we doing for time, by the way? Yeah. You are a bit over, so probably more... Okay. So, if I'm a bit over, I'm going to jump ahead. Just pull up my working application and just quickly run you through the actual working of... This is the config. Let me shut down these guys. I will go into the config client. And I'm really interested to see what exactly in my YAML file it was that just bit me. Because I can't, for the life of me, think of anything. I've got the config client dependency. I've got actuator. I've got data-rest. I've got the starter web. Everything is in there. I don't know what's going on with my computer right now. It didn't rate. So, if I run my server... So, my server is working. I am just going to start up the server again. And run my known working client. Which also happens to point at exactly the same place for the configuration file. Except that it is reading in a different location on the YAML file. Want that one? We want hello. So, this hello CF meetup is right now from being served from my client, the working client, which is, for some reason, unbeknownst to me, working, where the other one was broken. So, this client right now is working. No problems here. It's picking up the actual configuration from the GitHub repo. And where it is picking it up from, if I go to my GitHub repo on GitHub directly and I look at the client config YAML which is where that running application is actually picking up this change. If I edit this file directly, which you really should never do, but for the interest in the interest of privacy, hello direct edit. Let's go home already. And then I'm going to commit these changes. And when I now tell my application to refresh itself, let me set it not allowed. Yeah, it's supposed to be a post. Anyway, why on earth is it not? This is really bothering me now that the refresh is not working. Sorry? Yes, of course. Thank you. I need to say exactly what it is that I'm doing. So that is actually what was wrong, was that the method wasn't allowed because I was using curling correctly. Thanks, Mike. So, the funky cloud greeting has been pulled from the configuration. What has actually happened here is the config server or rather the client has basically said the only configuration that has changed is this funky cloud greeting. I've done a diff against my local changes. This is what changed. If I now go to my endpoint here, then there is this guy here that says, hello, let's go home already. There is one more thing which I will quickly point out. Inside, and I just want to talk about the fact that we talked about why it's so great that we can have encryption. You'll notice that there is actually this encrypted string inside my application YAML, inside my config client YAML file. That is automatically decrypted for me if it won't be now. It won't be automatically decrypted now because I haven't configured my client keys yet. So, I'll go to start up the server which knows how to decrypt the keys and this is just to give you an indication of something that you might like to do for further reading. We'll do spring boot run and once that local version which is running on 8888, if I look for the config client's configuration, it will come back to me, it will go to the GitHub repo and come back and it dumps the entire raw or parsed GitHub client config and instead that encrypted string which was on the server is now being decrypted. The way that works is basically you have to configure a cryptographic key with a simple secret that you specify in your application YAML and that is really it. So, if I go to source main resources here, I show you what my bootstrap.yaml looks like. There is just this encrypt key and that's it. Once I've specified a cryptographic key I'm then able to use the encrypt tool that comes with the spring command line tool or I can run on the... I can directly encrypt elements on... That is something... Okay, last thing. I can basically use my config server as a cryptographic endpoint. So I can actually encrypt things directly against my config server because one of the things that the config server makes available for me is if you see during startup there is a slash encrypt endpoint. There's also a slash decrypt endpoint. So I can do a curl. I can post to encrypt or since I'm sending data now I can just... No need to expose. I can just say send the data for Stefan. You still want that? Really? Ah, rom server. Again. Thanks curl. Sorry, my foo is completely not strong today. So it's encrypted that for me, right? And I can pass the string back into it and ask it to decrypt it. And in the same way that it's able to encrypt and decrypt for me it can do this over a... So you can imagine, right? I've now got cryptographic services for anything that I want to pass in. Right now it's decrypted with the Stefan down here. Right now it is actually an open server but it could just as well have been secured with spring security. I could have set up either security rather symmetric key based authentication using OAuth or I could have done something like a basic OAuth and secured my keys using configuration, externalized configuration where the key is stored and then have my client, my server securely communicate. Yeah. That's the gist of my talk and I'm going to bring it to a close now because I think I'm well over time at this point. If there are any questions please ask them now before we go. I've got one, two, three more books left to give out. Any questions? None. Okay. That's the end of the talk then. Thanks guys. Thanks for coming.