 Welcome everyone. In this session, it's called zero to hero and Kubernetes Java. So what is Kubernetes Java exactly? Or what is Kubernetes native? And what's the difference between Kubernetes native and cloud native? Is it the same? Kind of, not really, but kind of. So cloud native basically is a super set of Kubernetes native because it can be an application that you deploy. It could be to Kubernetes, but it could be maybe you're deploying a serverless function into the cloud or your container to the cloud and you're not using Kubernetes. So that's kind of, you know, the difference between cloud native. So cloud native, you know, can be AWS or Google cloud or Azure or IBM cloud, whatever Alibaba is on that slide here too. Whereas, of course, Kubernetes native is always on Kubernetes, which could still be on one of those cloud providers or on a Kubernetes on-prem or something, but, you know, just to clarify what Kubernetes native is. And so we're going to be talking about Kubernetes native Java and there's one particular stack that does that really well, and that's Quarkis. So if you haven't heard of Quarkis yet, it's a Java stack that's kind of built from the ground up to be really well integrated for Kubernetes applications because whereas a traditional Java application kind of starts up a little slow, it's built for, you know, kind of more dynamic behavior, you know, classic application servers where you don't constantly start up these applications, right? You just, you know, do some dynamic loading and everything. But if you want to run Java in a container, those containers can, you know, you want to scale fast, so new containers start up. Maybe containers get moved from one server, one node to another and they need to start up fast, right? Because, you know, like if you scale multiple containers and they don't start up as fast, well, then your scaling isn't going to be so great when you get a bunch of requests, right? So Quarkis starts up way faster because it moves all that kind of build stuff, the optimization that the JVM and the classic Java applications do during start up time, it does that during build time, and then it, you know, it does some elimination of things that it's notices that you don't need and so it packages it down way smaller, too. So that's also an advantage in the cloud native and the Kubernetes world. So that's why Quarkis is going to be the stack that we're going to be using today. It also has a really cool developer experience and I'll show that, you know, I'll show that too. And that's pretty much it for my slides. So, you know, are you ready to be a hero? And we're going to start from completely from scratch. We're going to build an application, you know, add some rest end points and then we're going to deploy it, of course, to Kubernetes. We're going to see how we can actually leverage things in Kubernetes like config maps and secrets to deploy, you know, kind of a production ready-ish application. And hopefully I can do that in less than half an hour. So wish me luck. All right, so to get started, we need to get started with Quarkis, right? So one way you can do that is you can go to quarkis.io and then you'll end on this pretty cool page and, you know, it shows right there supersonic subatomic Java. So supersonic because it's really fast, subatomic because it's very small and well, of course, it's Java, right? We can use our Java skills that we all love and, you know, use the entire ecosystem, but, you know, have all the advantages of fast startup time and use in small footprints and everything that other stacks also have outside of Java, but now we can use it with Java. Anyway, so if you want to get started, one way to do that is, you know, you go here to start coding and then, you know, if you're familiar with maybe the spring starter, it's kind of similar, right? So you have a way to get started with the applications. You can choose which dependencies you want to use. There's a whole bunch of them. And then you can generate your application, download it as a zip or push it to your GitHub and you're up and running. You can also use plugins in your IntelliJ or VS Code and get started like that. Or there's Quarkis CLI too and that's kind of handy and that's what I'm going to use because, you know, that looks way cooler, right? You know, CLI terminal. So I'm going to create my application, Quarkis creates app and then some name, let's call it cube native. And just by doing that, Quarkis create app, I could have specified certain extensions, dependencies that I was going to use. But just if you do this, Quarkis will create an application so you can see, you know, like there's Java and it uses Maven by default. I could have also specified Gradle. It generates, you know, of course, some Quarkis libraries and even some Docker files so I can get, you know, build a container pretty easily from scratch here as well. And then it adds this rest easy reactive code start because I didn't specify any specific things. So it's like here, Kevin, here's some stuff to get you started with your cloud native application or your Kubernetes native application in this case. So let's go and take a look at it. So I'm going to use VS Code in my case, but, you know, I could have used IntelliJ too. And so we have here our application and, you know, this should be pretty familiar if you're a Java developer, you know, you'd have your regular palm.xml. We have the Quarkis bomb here. We have the Java 17 that we're using and some dependencies that it added like Quarkis arc for dependency injection. So we get some stuff kind of for free out of the box. And then we have even a little greeting resource. So we have a little endpoint to get started with and it says, you know, hello from rest easy reactive. That's kind of the default here. Now Quarkis has this dev mode, which is pretty handy. So if I open this, I'm going to run this in my terminal here and I'm going to do Quarkis dev. So, you know, using that Quarkis CLI again could also do Maven Quarkis dev. But why would I type Maven if I can just type Quarkis dev? Anyway, I'm going to start that up. And so that's going to start up the application on my local machine. And then in a few seconds I can go and look and see if my hello endpoint has started. So I'm going to hit W and that opens it up right in my browser. So congratulations. I already have a Quarkis application up and running. So it, you know, adds this little HTML page too, which is handy, but here's my hello endpoint. And well, shocker, hello from rest easy reactive, right? Nothing too spectacular just yet. But so what's cool with the Quarkis dev mode is that, you know, now if I change this, let's say hello from Berlin, I'm not recompiling anything and I just go back to my browser. I hit refresh. And my change is there, right? So I don't need to do anything. So I get a quick feedback loop. I can work pretty quickly. But I was kind of a bad developer just now because I'm making the code changes without making the test changes, right? Because actually Quarkis in my code starter also provided me with some tests as well. And they're looking for hello from rest easy reactive. And, you know, I don't know if you're probably a better developer than I am, but, you know, like oftentimes what happens is I'll make my code changes and I'll do my Maven package or something. And then, then I'll realize like all these tests are broken because I forgot that there's actually tests that are covering my code, which is actually what's the case, right? So Quarkis has this continuous testing mode. So if I hit R, you can see here R to resume, then I start this continuous testing mode. And, you know, sure enough, it notices that my test failed because I changed the expectation. We can see that. Well, this is, I'm going to make it a little bit smaller so I can actually see what I'm doing. Test failed and then here we go. Expected is hello from rest easy reactive. So I should have changed first my tests probably. And then Berlin. And now, you know, by just changing my code, Quarkis automatically notices, hey, you made a change here. So I'm going to reload just this particular test. Or, you know, if I changed the class itself, it's going to know which tests are related to that and just rerun those. So I get a really quick feedback loop of what's, what's going on with my application and I don't need to have that, you know, kind of unexpected at the end stuff. Anyway, so of course we're talking about Kubernetes native. This is kind of pretty basic, right? It's hard coded string. So let's make this a little more interesting and let's make this a little bit more dynamic. So we'll do, we're going to return a greeting from a configuration property. So we can add a config property and Quarkis tries to use standards just like Jakarta EE like micro profile standards. So in this case, you can see we can just use a micro profile, a config property, add a name. We'll call it greeting. And then string greeting. And so, you know, so now we have a dynamic value for our string. Now, of course, I haven't defined it yet, but I'm going to be kind of silly and test it anyway. Oops, let's stay there. Hit refresh. And of course Quarkis says, well, this is not right. You forgot something. But what's kind of cool is that it did notice that there's a configuration property missing why don't you just fill it right in here. So, you know, I'll help you out a little bit, Kevin, because you're being kind of silly. So we can change this greeting again to, you know, hello developers, whatever, right, updates. And by doing that, you know, of course, my application is working again. But you can see now if we go to our application properties, mouse, please work with me. Resources. There we go. Application properties. Quarkis added that from the UI. So that's kind of handy. So of course, now I again broke my test. So I should probably fix that. Hello developers. I should have done that first, probably developers. Okay. And so our tests are passing good to go. I have, you know, a little more interesting application running, but it's not cube native, because you wouldn't hard code those properties necessarily in your application properties. In Kubernetes, you would use config maps, right. And so that's something that you can work with with Quarkis pretty easily. But before we do that, of course, I need a Kubernetes cluster. So in my case, I'm going to use an open shift sandbox. If anybody was in one of the previous sessions, you probably already saw it. So if you go to developers.readout.com, you can get this free developer sandbox to play around with. If you have your own Kubernetes cluster, you know, you can use that as well. You know, right now we don't have any resources here. And I'll just log into my cluster, my CLI. So I just go to log in, get a token and copy that. Go back to my VS code. I'll open a new terminal and log in to my cluster. Maybe if I pasted it, right? If not, it'll be OC log in or cube CTL log in. But actually I cheated because I'm already logged in. So let's pretend that that happened. All right. So now that we have a cluster to deploy to, well, let's add a little bit of capability to Quarkis to actually work with Kubernetes. So you can do, with the Quarkis CLI, you can do Quarkis extension add, and then you add capabilities such as, you know, Kubernetes. And so by doing that, if we go to my target here, you can see that it'll add a Kubernetes folder. You saw it pop up, right? And it has, you know, some Kubernetes YAML, some service and deployment. So I don't need to worry about, you know, like how to write those YAMLs or anything. And I could just apply that. And that would push my configuration to Kubernetes. But I'd have to build a container and push it to a registry probably before doing that. So I'm going to cheat a little bit. And instead of doing that, I'm going to add a couple more extensions. One being the OpenShift extension. So I can push my code to OpenShift and let OpenShift build my application. And for my configuration, there's a Kubernetes config extension. That's going to help me work with config maps and eventually also secrets when I need those. So I added those extensions. And so in my pom.xml, it added some more dependencies by doing that Quarkis extension add. So we can see here there's a Quarkis Kubernetes config and whatever more. And so now we can start building that for my application. So I'm going to go back to my application properties and add a few things to wire everything up. So for deploying to OpenShift, I would just need to do, actually to expose my ports and my URL so we can actually test it because otherwise if I just push a service, it's available. It's working on Kubernetes, but I couldn't access it from outside of the cluster. So if I do something like route expose, which is an OpenShift thing to expose your ingress. And then let's see. I want to do edge termination. Let's see if it'll work with the suggestion. No more suggestions. That's nice. Well, actually I don't necessarily need that. So we'll do Quarkis. And it'd be nice if my suggestions would work, but if not, I'll have to just remember. So to add the configuration maps, I need to add Quarkis.KubernetesConfig.ConfigMaps and then give it some name that I'm going to create in my cluster where I'm going to store my configuration. So it can be like my config. And then I just need to enable that with Quarkis Kubernetes config enabled, I think. Let's see. Shift route, expose. I'm going to remove that one. And config enabled equals true. We'll see how that goes. The IDE is not working with me right now. So we'll see. Anyway, so now we build our application so I can do Maven package or I can use the Quarkis CLI again. So Quarkis build. Then I'm going to add one special property which is Quarkis.OpenShift.Open... Wow. Nobody saw that. Quarkis OpenShiftDeploy equals true. And so by doing that, I'm building my application and then I'm going to deploy it to OpenShift. And hopefully if everything goes well, it's going to push my code and start deploying onto my OpenShift cluster. So we'll see if that works. All right. So we see that our tests are running and that could actually be a problem because I enabled the config map property. A key Quarkis Kubernetes config map was provided but it doesn't recognize it. Okay. So it is not entirely correct. So I'm going to try one more time and see if... Ah, I get my suggestions back. That's a lot easier. So Quarkis Kubernetes config. Config maps equals my config. And so there was some typo in my previous command. Okay. So let's try that again. In the meantime, everything is deploying but my config map wouldn't be used yet. But that's fine. We'll try it again because in the meantime, I'm going to create that config map still on my cluster. So let's add it real quick. So in OpenShift you can use the UI which is kind of handy. So I called it my config. I hope this is big enough for you in the back. If not, let's try to make it a little bit bigger. It doesn't want to. There we go. And I had the key greeting, right? That was my configuration property. And let's call it hello from my config map just to make sure that we know that it's actually coming from the config map and so we'll create that. And if we go back to our deployment, well, this time the test failed because I have this configuration property set to use config maps. And so even on my local machine because I'm logged into the Kubernetes context, it's trying to use the config map value. And so my test is expecting hello developers, right? What I could do is for my local testing, I want to use my local values. So I just add prod to my configuration property. And by doing that, these values are going to be ignored unless I'm running in a production environment, well, in a production environment. Whereas on my local machine I'm running in a dev mode. So my profile is dev, it's not prod. So that's how we're going to be able to do our tests properly and then deploy to Kubernetes. We'll give that a little bit of time. We'll see that the tests should work this time. And while I'm doing that, I'm going to show you another cool thing. Wrong browser. Which is the dev mode in Quarkis. So if you go to your local host, 8080 slash Q slash dev UI, you end up in this Quarkis dev UI which is something that runs, if you run that in that dev mode. And it's kind of handy because, based on the extensions that you add to your project, you can see, for example, that I can generate my Kubernetes manifests here. I could even deploy two open shifts from this UI. I can build a container and blah, blah, blah. And I can also access my tests from right here so I can enable the continuous testing and then, well, good thing my test is passing. And then we'll see in a little bit when we add developer services, dev services, some more cool stuff in there. So let's see if our build was successful. Yes. So if we go to our open shifts, to our Kubernetes cluster, we can see here that there's an application, our Kube native application that was deployed and running. So let's see if we open it. Well, congratulations. It's running in the hello endpoint. Hello from my config map. So hey, that's pretty cool. So very quickly, I was able to, you know, create an application with a wrist endpoints and integrate it with config maps deployed to Kubernetes. So, you know, we're still in time, right? For adding some more cool stuff to our application. So right now I have a very simple kind of, you know, yes, it's a property. It's not hard coded, but it's still a pretty simple application. So let's be a little bit more realistic. You know, probably an application will use a dependency like a database or something. So let's add a database. So I'm going to add a few more extensions. And this time I'll use the Quarkus plugin in VS Code. And it says add extensions to current project. And if you do that, it's a little easier because you can, you know, you can scroll through the extensions or you can start typing. And so, you know, I'll start typing Postgres. And so I want to add the reactive Postgres client. And then let's see, then I need, I want to use Hibernate ORM. And I want to use Hibernate reactive with Panache. And I'll show you what that Panache does. And I think that's it. So let's add those two extensions. And so by adding a database extension, Quarkus is going to reload. And so this is a little bit small here. But you can see here that it's reloading my application. And because I added a Postgres dependency, it notices that, well, you're actually not running a Postgres database under your local machine. You don't have anything configured in your application to use that. So why don't I just start up a container with Postgres using test containers for you to use for your local development so you don't have to figure everything out and you can get up and running pretty quickly. So we can go to Podman Desktop here in this case, so Docker Desktop or Podman Desktop. And we can see here that a container has started 38 seconds ago with a Postgres database. So it just did that for me automatically. And so now if we add, let's say, a new entity, let's call it person.java. And I'm going to add entity. And there we go. Again, using Jakarta EE core. So very standard dependencies with Quarkis. I'm going to extend with Panache entity. And that's going to give me some handy stuff to create my entity very easily. So I can just do public string, let's call it a name, and public string location. I'm probably thinking like, well, shouldn't this be private? And shouldn't you be creating getters and setters and all that stuff? No. With Panache entity, that kind of gets handled in the background. So when it compiles my application, it'll create the private properties. We'll create the getters and setters and some more kind of handy features like get by ID or find all or list all and stuff like that. So let's do that. I'm going to add another method to our resource here to get our people from the database. So in this case, let's add a path. So path, again, using Jakarta. And the path, let's do people. And then we want to create get people. I want to return it in JSON format in this time. So we'll do application, JSON. And then I'm going to return the person.listall. And so I get that out of the box with Panache entity. And so, of course, I'm not returning a string, so I need to replace that with uni because I'm using the reactive hibernate and then lists of person. Okay, so I need to import lists. Java, util, yep. All right, so now I have a method that's going to return people from my database. Now, I don't have anything in my database yet because I don't have any import statements, so let's add one real quick. So create a new file, import.sql and insert into person, right? ID, name, value, and values. And then we'll create a few values in our database. So let's do one Kevin from Brussels. And then two, we got Natale, who was nice enough to introduce me here. He's from Milano. Oops, my cursor jumped. And we got my colleague Alex from Barcelona and we got, sorry, I can't type faster. And we got Hans-Peter from Graz in Austria. Okay, so now we have some values. And so, let's see if this works. I'm hoping it'll work. Hopefully, I didn't forget something. So let's go back to our live mode, which is still running. So we got hello slash people, right? So let's try that. And we got an empty result. The good thing is that it is working. We got some, it does recognize that there's JSON, but somewhere I didn't, maybe I inserted something incorrectly. Let's go look at the log zero quick. If not, sorry. Location was not, oh, you're right. Thank you. Peer programming for the win. Okay, so now if we go back, refresh. Oh, I remember I forgot one extension, which is the JSON B extension. Of course, because we're using, we're turning JSON. So add one more extension, JSON B. Let's make sure it's the right one. Rest easy reactive, JSON B. Add that. And again, I don't need to recompile anything. So that's pretty handy, right? So let's go and look and hopefully it'll work this time. Yeah, it doesn't work. Let's refresh a couple of times. Okay, let's do this. I'm going to stop this real quick and restart it just to make sure that everything loaded correctly. And then we're crossing our fingers. Everybody crossing their fingers with me. So let's see. It starts up. You can see that database is starting up. So Dev Services with Postgres starting up, blah, blah, blah. And so let's hit refresh one more time. And yes, our results are there. So we can see Kevin and Natalia and Alex and everybody's there. So now of course, there's a cube native session, right? So this is working on my local machine. We need to deploy this onto Kubernetes. So I'm going to add a database, of course, because we need a Postgres database. So let's see Postgres instantiate templates. And then we need a username, blah, blah, blah. It doesn't matter password, blah, blah, blah. I don't even need to remember it because I'm just going to use the secret later on. And then I think the database name was Quarkis. So we'll just do that and create a Postgres database. So by doing that, in my secrets here, the Postgres Helm chart created a Postgres secret with the values, right, with the username and the password. And so you can see here it's called database-password and database-user. So I'm going to be using that to configure my secret. So one nice thing with the Dev UI again is that if I hit refresh here real quick and I go to my Dev Services, you can see now it says, hey, you have a Postgres database working in your Dev Services. And I've configured some stuff for you. So I configured that your data source was Postgres and I created a default password and username and even a URL. So I'm going to copy that and use that for my production-like environment. So I need to go back to my application properties and add those to my properties. There we go. But of course, my username and password, I'm going to make this a little bit smaller, aren't hard-coded, right? Because they weren't pork as I just put in some random values because I want to use the secrets in a cube-native way. So of course, let's make sure that we're using that only on the production environment because otherwise on my local machine things won't work anymore because I don't have a database configured like that. So adding those values real quick. And password is going to be a dynamic value. So it was, I believe, database password. And correct me if anybody remembers if it's wrong. And then I think the database was database user. And then I just need to, of course, it's not going to be a local host database. It's going to be the name of the service on Kubernetes. So it's going to be PostgresQL as the name of the service. And let's go take a look at it real quick. So we can see here, hopefully my database is running. Yes, I see that there's a nice blue circle, which means that it's running. And sorry for those in the back. This is probably a little small, but I can see here the name of my service and the port. And so I need to copy that and add that to my configuration here. I could have added this to some config map too, but let's not make it too complicated. So I need to add two more things here. My import script, of course. So let's see script, SQL load script, which is import.sql. And then I need to make sure that my database gets created. So again, I can cheat and it's not Chrome. It's Firefox. I can create with my dev UI because it also created this database generation for drop and create. Now, I probably don't want to do a drop and create on production, but I do want to do a create in case it doesn't exist yet. So let's do that. And I think if I remember correctly, that should be all we need to redeploy our application. And in this case, use the database to be all wired in using the secrets and using the database connection all kind of automatically without me having to create a bunch of configurations and settings. So let's go here. I think it was in this terminal. If not, I can just do quarkis build. And again, we'll do the quarkis open shift deploy to make the build happen on open shift. Otherwise, afterwards, in the booth, in the Red Hat booth, I can show you how to create a container image and then push it to a registry and then use the Kubernetes YAMLs, apply those. And that's how you can deploy too. In my case, because I have this open shift, which is nice enough to build everything for me in the cluster, it's just a little bit faster here in my session. So I'm using that. And it's actually a great way. So if you want to see the other way, come find me and I can show you as well. I don't know why I keep going back to this slide when I need to go to Firefox. But so we can see from my application here that the build is running. And yeah, this is kind of small, but you can see it here. And we can look at the logs that it's using these images by default. So because it's open shift, of course, it's going to use Red Hat containers. These are tested verified and supported by Red Hat, which is pretty cool. It has open JDK and Maven in it to do the build and then it'll create the container image and then do the deploy. So let's see if everything happened correctly. So we can see here the blue circle is for our previous container that didn't have the database connection. And our container is creating with the connection to the database. And we can see now that it's running. If everything went well, then we can go back to our application slash hello slash people. And we get an error. So let's go see what the error is. I can go look at the logs here. And it says that password authentication failed. Okay. So I didn't create my secret correctly. So let's take a look at the name of the secret, postgresql and then database dash password and database dash user. So let's take a look and see if I did that right. Actually, I know what it is. I need to enable, I need to tell Quarkis to use the secrets. So I need to add a prod Quarkis Kubernetes config secrets to, you know, give a name to my secret. Well, the name of the secret that we have, which is the postgresql and then prod Quarkis that Kubernetes config secrets enabled. And by doing that, that's how you tell Quarkis to use the secrets and then to look for the secrets that match with with this value. And so we'll redeploy one more time. And that's hopefully it'll make it work. In the meantime, I'll show you how this Kubernetes YAML also keeps getting updated with, you know, the extra properties that I added. So in this case, it added a service account, which is something that you need in Kubernetes to add, you know, to create access to somebody or to something, it added a role binding to view secrets and to get access to these secrets. So it, you know, as all this complicated YAML that I could never just, you know, kind of come up with in my head, I'd have to like cheat and find ways, but Quarkis creates all this kind of stuff for you. So it's really kind of cube native Java development. And so, you know, let's give it just a moment to deploy. And in the meantime, you know, because we have, I think a few more minutes, we'll add two more things to our application. So when I deploy my application right now, as a container start, Kubernetes is going to be like, okay, your container has started. So I'm going to send traffic to it. And actually what we want to do is we want to tell it, well, wait until the application is actually running. So in Kubernetes, there's this thing called health endpoints. And so you can add those to your application to say, report, you know, if my connection with the database is up and running and everything that now you can send traffic, not before that. So you can do that with some extensions in Quarkis. So there's just a really simple small right health, which and small rise and implementation of micro profile. And that's going to add those health endpoints automatically. And it knows that because I'm using a database that, you know, look for database connections as well and make sure those are up and running as well. And then just for fun, I'll add the small right open API extension as well, which is going to add, you know, like swagger and open API, YAMLs or JSONs to my application as well. So it's going to scan and find the endpoints that I've defined in my application. And we will see those as well. So right now, first, we'll go and look and hopefully everything deployed correctly. So we'll hit refresh and boom, yes. Our application is now up and running using a database, using secrets, config maps and all that in Kubernetes. And we did that in, you know, about a half an hour, right? So that's, I think that's pretty cool with Quarkis. And so just the last thing here before we wrap up is in my local hosts, because I added those health endpoints, I just want to show you in the dev UI again, I don't think we have time to deploy it again to Kubernetes, but we can see here that we have small right health. And we can see, you know, in the health UI, that my database connection is up and running. And, you know, if I deleted my database, we would see that, you know, eventually it would say, well, it's not up and running, it's red, right? So, and that would be the same thing that happened on Kubernetes. So it would, you know, Kubernetes would see this application is not ready to receive requests because, you know, there's a health endpoint that's not running. And then the same with the open AI extension that I just added, just by adding that dependency, I get, you know, the JSON or YAML for my open AI and I even get a nice handy swagger UI to test my application, you know, so I can try it out again on my local machine and we can see that, well, let's pretend that it worked. I think it's probably trying to connect to the remote database. Anyway, that's it for a very quick introduction, you know, going from zero to, you know, let's say hero, we did pretty good with deploying an application and everything. So a quick wrap up here. So if you want to get started with Quarkis, go to quarkis.io. Super cool. There's a lot of cool other features that I haven't shown. So, you know, definitely check it out. If you want to get started with that OpenShift Sandbox you can create your Quarkis application once you build it. You just go to developers.redhat.com slash developer sandbox, you can create a free account and then you get access to that and maybe I'll just give you one second and see some people taking a picture. All right. And then tomorrow, book signing. So there's a modernizing enterprise Java. So, you know, modernize your legacy application to kind of a Quarkis or Spring Boot application. With Natale and Marcus who are right there. They're going to be signing books. And then Alex is also author of the Quarkis Cookbook. He's also there signing a book. And with that, the link to the slides, which, yeah, there weren't very many, but you know, if you want them, there they are. And if you want to connect with me, ask questions. I also put videos on YouTube, you know, with building Quarkis applications and building containers or whatever it is or you want to follow me on Twitter. I try to be active and post some interesting stuff. So that's it. So thank you.