 Now, I would like to talk about API documentation and reasonable practices. Well, so I enjoy Java. I am a freelancer or a consultant. And I've write a blog, and there are a couple of courses, video courses of the AXIO. AXLive is the on-demand workshops and a podcast. And if you like, you can join a virtual workshop in December. OK, what I would like to talk about today is the Jacksores Micro-Profile and some ideas how to document APIs, a little bit about open API and reasonable practices. And if you have time, a little bit about testing. So I will just open the chat. So if you like, you can interrupt me at any time. And I will try to answer all the questions. So hopefully, you can hear me. So now, let's start coding because this is what this is definition and not speak nation. So let's start with a thing. And I think now I should create an application. And this is this application will manage, of course, the definition rooms. Let's do a rooms management. Set the project version. And yes, and this would going to be definition rooms resource like this. And perfect. And this already looks good. So what this means is I will just open that. So what this means is we have a small Quarkus project. And this Quarkus project comes with a REST easy and REST assured, which is not needed here. Absolutely optional. And JUnit 5, I would like to keep. So because of time, I would like to add some extensions right now. And hopefully, what's wrong? Yeah. And the extension is going to be a REST client. And another extension is going to be an open API. Open API. And what I'm using right now is a micro profile. So REST client and open API in both are parts of micro profile. So if we take a look at the micro profile I owe, what I added now is the open API and the REST client. And by the way, if you are curious how micro profile works, you can click here at the link and go to the spec HTML. And this is the open API, for instance, spec. And so if you click here, you will get the entire specification, which I actually already opened. And this is hopefully, wait a second, here. It is written in ASCII.DOG. And it describes what to do. OK. Now we have it. And let's start the server maven compile Quarkus dev in dev mode. Now what happened is not a lot. So let's take a look. I have here Java rooms resource. And the rooms resource returns a string. So what it means is if I just switch to the browser and go to localhost 8080. And this is a goodie from Quarkus. It's not a part of micro profile official part, but it's supported actually by all runtimes. And this is Swagger UI. And what I hopefully get is the Swagger UI. And it says, what a bad day, right? So let's do it again. And I should actually find the Swagger API. And if not, we will proceed. Without Swagger, it would be hard in this session. Localhost, localhost 8080 slash openrp. And not found, which is strange. And if we just take a look, we have our rest is a small open tracing. No one complained in the chat. So open tracing is completely wrong. What I wanted to have is the open API, openrp. This is, let's add it again. I have to complain the chat was not very open API, open API. It's more like open API, not open tracing was completely wrong. So now, hard too fast to see. But if I will type slower, then we won't get enough time to see. So just add this once again, add extension and open API, open API. And what the small right is, is the reference, model rest reference implementation of the micro profile. I hope now it's going to be better. So what we should see now is the open API. So let's double check that. And now, perfect. So this is the default conventional setting setup. And if I will just pull this over, now we can go to the rooms. And I would like to try it out and execute. And as we can see, hello, there's a hello. So a little bit boring. So add a proper room. So a room is going to have a color. What I learned is I was in a green room. And then in two rooms and in the middle, in no room. So the rooms are a content room. Sorry, color. And what the rooms probably also have is ID. Let's go with ID and probably what else? I don't know. Oh, right. Because I don't think the attendees were in all the rooms I was before. So public string. And this is the permission to go to the room. And let's do this as Julian. So what I can do right now is I can go to the room resource and expose the room. And say this is my room in the white room with black curtains. So return new room. And this won't work. Why not? Because we need a constructor. But the green room is very important. And now what I also would like to do is to add a method which saves a room. And this is going to be post. And I needed to show you something. So post and consumes, consumes, consumes, media type application, Jason. So yeah. And now I would only like to print it out for now. It should be enough. So class room. Now what I need is I need one less O. Then here we need two constructors, one for convenience and the other one because of the requirements. And this one, I only would like to have the color because of time. And the other settings are this ID equals system current timelapse. Then this color equals color. And permission, we are never permitted. OK, should be enough. So now what we get out of that is hopefully, so if I switch to here, we have save and get post. Looks good. So if I just ask for the rooms, just go to the browser and take a look what happened is the following. I see get and post. And with get, I get the room as Jason, hopefully. And almost as Jason. Why? Because I forgot a very important extension. And this is called rest easy, Jason B. So rest easy, rest easy, Jason B. So now the extension is added, hopefully. Sometimes it hangs here. So just go away. We don't have time now. So rest easy, Jason B. And by the way, I could just add the extension to the poem right away. So start the Quarkus again. And then so now what we have here is just reload everything. And this is basically how I play with the APIs and try to see what actually happens here. And I say, OK, I would like try. And what I get back is the Jason. So it already looks good with the ID. So we could tell, OK, the ID is a little bit problematic because I don't like to expose the ID. It doesn't matter. It is properly generated by our conference streaming software. So I would like to hide the ID. And we can do this, actually. I can say now with a micro profile. Yeah, with micro profile open API schema and hidden true. And now with that, if I just switch to here, it should be actually not visible. So there is no API, sorry, no ID. And the same is true. If I would try, for instance, so just go here. I can go here to the post. Where is the post? Right? To post and try it out. As you can see, it suggests color and permission. But I would say, OK, the permission cannot be written. So it is read-only. So this is also doable. So I can say, OK, the permission is read-only. So let's go here and say schema read-only true. So this means it is going to be exposed. But I don't get the suggestion here anymore. Hopefully, I just only get the color. And if I would like to try it out, then I won't see the permission. So OK, now the room is like it is. And what's also valuable in projects is adding some context. And yeah, my media type is still text, really. So application JSON text plane, OK. Thank you to Philip Kruger. So this is one of the micro profile hackers, which created actually the micro profile extensions of thank you. This is a great conference, actually. You cannot do any errors, because the audience is helping you. It's like pair programming with 5,000 attendees, or no, 6,000 or half thousand attendees. OK, now we have that. We have the application JSON and disk. And the question is, how to document the entire thing? And what I would like to share with you is something which was submitted by an attendee, seven years ago, actually. And we had already the same discussion with JavaDoc. And what I see still in projects, in enterprise projects, that the developers do the following. They say, this is a getter. This method returns a name, which is a string. This method sets a name, which is a string. And this is a default constructor, and this is a class. And with that, in my opinion, what it means is extensive documentation is no documentation. If I were to describe, this is HTTP protocol, and I'm using POST right now, forget it. So what I think what you should not document here is, so POST is for saving. And POST automatically implies that the room is generated on the server. Sorry, that the ID for the room is generated on the server. At get means this is actually wrong what I did. So actually, a better alternative would be the path with the ID. And then I would get a single room. And with the get, it would return a collection of rooms. This is why we always use plural here. So designing a REST API means we always start with the plural here, rooms, chats, messages, speakers, audience, or whatever. And the rooms, get rooms, would mean I get a collection of rooms back. So now, what we could do, for instance, add additional context. So what I would like to do is the following, add another schema annotation, schema, and say, example. And we say, actually, actually can be only green or transparent. Because I have no idea in which room I'm right now. It doesn't have any color for me. Actually, it can be only green or transparent. And with that, if we switch to the open API browser, this is the Swagger UI, and just reload it again, we see, hopefully, here in the room, that actually can be only green or transparent. And Boolean is only true. And I would argue, this is a true help for developer team. But what I see instead is I don't like to do it because of time. What developers tend to do is that they tend to tell you, get returns, rooms, and 200 is OK. And 500 means internal server error. So this is exactly the same problematic documentation we had 10 years ago with JavaDoc where just the signature of methods was retranslated into JavaDoc. So conventional means I would only add things which provide added value. And this open API should derive the value from or derive the API from the signature of the method. So sometimes, it is not possible. Yeah, exactly. Udi says, how do you annotate map string string? But even worse. So what usually can happen is, what if I do this? So this is what happens in all projects. So if I try to do this and say, this is OK, and say, build. So now, it's over. So it should work as before, but I will lose a lot of information. So if we just try it out here. So it's still, I don't think he reloaded, or he's smarter than I thought. But there are situations where he still knows the schema, but I think it is an error. Let's see. Go localhost, 8080, and open API. And in the schemas, there is post. OK, it still knows. It's smarter than I thought. That the request port is that it, what is it again? You refresh the post. Yeah, I refresh the post. But what I wanted to say is, ah, I refresh the post. And actually, I meant the get. And in the get, yeah, this is the reference is lost. So I don't know anymore the reference with the post. So I thought, right, thank you to the chat. So I thought, you know, this is the problematic method of this one. And if you get to see, the context is lost. So how to provide a context? So we can actually add API response and API response. And this is the content with media type. And the media type is media type. We already have it. So actually, we can skip that schema. Let's go with schema right away. Schema, content, right? Content, no, I was right. Content. And then schema. And this is schema with implementation. And implementation was room.class. So this is not necessary. This was the answer to your, yeah, attendee-driven coding. This was the answer to the map. Because now I provide additional context. And hopefully, let's now take a look at that. You will see the additional context. And you see, OK, we are back, request, bold, and so forth. So in my projects, I do not actually document that 200 is OK, and 500 is bad, because it's obvious. This is how HTTP and REST works. But if I would, for instance, would like to express that 400 indicates it's actually OK, then I will write the API response. Exactly. If it works, it works. So now, cool. So I think we have a little bit of time. So what about tests? And we are in Quarkus project, so I would like to show you how to deal with the schema changes in the test. Because you got the point. We could discuss not the rest, but it's already discussed several times. So what I'm doing is in microservice projects, or cloud projects, like Quarkus module, just for tests and in outside and already existing Quarkus project. And this is going to be definition and room ST. And this is OK. I don't need now this and go to room ST. Now, in room ST stands for system tests for historical reasons. Yeah, someone says, Philly says, if you want to use code generator, then knowing the response is useful, I would say I don't like code generators, because they always generated, I would say, suboptimal code. And I would like to show you what we are usually doing with nice APIs. And I will generate code for, I would say, not that nice or crappy APIs. So now with my system tests. And what I can do right now is actually interesting. I can take a look. I can, hopefully, there is JUnit. Yes, there is JUnit and RestEasy. So I don't need even RestEasy. But what I need, not RestAssured, the best API for testing is actually Micro Profile RestClient. So RestClient, RestClient. And what I can do is the following, I can say, I have, what was it? Rooms, resource, integration tests.java. And because of Quarkus, source.java, yes. And, oh, interface where this class. And source.java, okay, this looks right. And I can use the Quarkus test. And now comes the interesting point. What I can also do is I can add now the message resource client. And this is now an interface. Yeah, and faster than market. Yeah, faster than market and very fast with the market. And then for the first version, and the second and third version gets longer and longer. This is the problem with, I could tell you some stories. Actually ask me the question they asked if I can tell you some more stories with generated code. They're actually funny. But what I could do is for time, I can say, register RestClient, register, register RestClient, or is it? Register RestClient. And usually always use the config key, but in sessions, a conference session is also allowed to use the base URI. And I would like to call now localhost 8080. And the path is going to be Rooms. And now the cool story is what I can do is I can actually return a JSON object and say Rooms, which is not the JSON B object I had before, and say get and produces, produces a media type, JSON media type application JSON. So, okay, now in the room resource, there is no packages. So don't do it in production, of course. Corpus test, I can create a method and this method tests Rooms and it has tests. Oh, and it has tests, tests. And now I can go here and say inject because it's corpus. So this is no more micro profile. This is corpus goodness and say a RestClient. This is the qualifier, RestClient. And what I would like to inject is the message resource client, client, and then of course write some tests with asserts and say, what was it Rooms? Bar Rooms and then this is trace and see whether it actually is working plus Rooms. Oh, I'm closing methods, Frank. Rooms. Okay, now run tests and see what happens. And it failed. Why it failed? It says unable to find a message for the reader, okay. So I think I have still to add RestEasy at extension. RestEasy.jsonB, I guess. And then try it again and wait a sec. This is Producers, application JSONs actually should work and this is the right JSON. And oh, it works, surprising. So I searched for the error and because of micro profile, the errors are self-healing, you know? You see, it works just if you wait enough, all the errors are gone. And now if we go to the debug console, we see that Rooms returns that. Why I did this thing with JSON object and with a standalone module? And the idea is what we could, right now we can test the compatibility, the compatibility of the API. So I can over time add more and more attributes, one from the system test perspective. I actually don't care, it will always work. And now what's also interesting, someone asked me about code generation. What I actually wrote is a rest stop. So this is my client. So I can actually go and provide test driven development with MicroProfitRestClient, test it first and then copy the code over to my production project so I don't need any code generation. So the code generation is more interesting in case, you know, I have to consume some external APIs which I don't care about. Okay. Okay, cool. So what this is, is a standalone MicroProfile, I'm actually misusing Quarkus for testing and the cool story is with the injection. So with Quarkus, I can just inject my resources and the cool story is you can configure the resources. So locally, so I'd never used basically, what I used the config key. So the MicroProfile config would allow me to specify the config key. So it would look like this, so let's try that. So it would be config key equals and this is any name you like. And then would be, let's say rooms. And then I probably don't get the code completion because I'm in test mode. But here in my application properties, I can actually say rooms. No, you see, there's no, it would be like, it looks like, I think rooms, MP, REST, something like that and URI, and then you have to specify the URI. It looks like, almost like this. So I don't know it out of the box. And why I doing this, following. This is MicroProfile config. So locally, I can fall back to my localhost 8080 and on Kubernetes, for instance, I can override in my pipeline where the service actually lives. Also the last thing, I think a little bit over time, is that the, we have the version here, one zero would be better, one, one, two, and so forth. And the other microservices also version. So what I can actually do, I can check out all the versions from system tests and see whether they are still compatible with a newer version of a microservice. Okay, why create a test code outside the original project, Howard? Very good question. Because if I would create the system test inside the project, Quarkus will see all my dependencies. I could just reuse my room one to one. So let's imagine that, if I would just go to my room and try to test in the room, the room, right? So I'm now in the rooms. And if I would write a test here, I could, I would see actually my own class room and this would be never incompatible because I always would see the right version, but only with a separate module. First, I'm forced to see my own API from the outside and I can check out different versions and run against the newest version. Yeah, so you could put this to the, but I only do it in trigger projects, in my, whatever. So then I put it together, but Quarkus is really nice to have two modules and in the clouds, what happens is, in the Jenkins pipeline, let's say on OpenShift, what happens then, the project is built, deployed, system tests are compiled and built and then executed against the system tests from outside. And the cool story is, if you have multiple teams, you can actually give the system tests to another team and they have already a working client. So I think really we are over time, right? I lost the track a little bit. Are we over time? Who knows? I know. Yes, we're right on the top of the hour. So if you like that, next week, still some seats, you can attend the architect in designing Java, MicroProf and Jakarta applications. We talk about stuff like that. It's a whole day, a little bit less code and more architectures. So this is Erhex Live. Still a few seats are left and it's a virtual online workshop, exactly like this with only one room. This is the thing. So we all meet in one room. So okay. Okay, any questions from the audience? And someone says, make sense. I tend to create it. Yes, yeah, the separate source sets and it only makes sense in microservice projects. Then thank you for watching and I really appreciate that and see you at upcoming conferences. Hopefully the definition next year. And yeah, and if any questions left AXTV first Monday of the month, you can just ask me and we have chat like that. And I will tell you in the next AXTV award story about code generation, which was some funny or not that funny. So thank you all and big thanks to you for helping me with the syntax errors today. I was a little bit nervous because I know I am late and we had some connections problems. Thank you. Enjoy the conference and stay healthy and bye.