 good morning or afternoon, depending upon where you are. And thank you for joining us today. Hi everyone, Robin Jeremy here, but today we actually brought a couple of special guests, rock stars. So Aaron and Zanab are going to join us to talk about integration. And while Jeremy and I get to sit back and, throw popcorn, heckle. We'll throw popcorn. Okay, we'll throw popcorn. We'll probably interject. Actually, no, people mostly throw popcorn at us. When we're doing stuff. So I don't think we'll do that. But I do have some dad jokes. I'll try to interject. Yeah, and so I'll tell you this isn't exactly true. But so whenever Rob and I do meetings together with customers, one of our colleagues will ping me on Messenger afterwards and ask how long it took for him to bring up Camel in the meeting. So we've both been big fans of Camel for a long time. And we should say we saw, I saw this presentation in Dev Nexus this spring, right? Like in this year, right? Yeah, and we liked it a lot. And that's when we asked you, we hounded you to present for for months and months. What was the scheduling? Like I was not home all summer. So this is the first time I would have been able to do it. And I was super excited to ask Zanab to come with me because she knows a lot more about this and those cooler things. So I think that's great. The last couple of sessions that Jeremy and I had, we've talked a lot about corkis and our very last one, we talked about corkis testing and you guys work with corkis. You want to mention that a little bit? And now you're going to do the demo. But I know maybe, you know, people haven't seen you before. So they want to know maybe a little bit about what you do. So I work on corkis. Less a little bit than I did in the past. But I brought my micro profile. No, micro profile. Wow, everybody's going to be mad at me. Micrometer support to corkis because of problems with micrometer with a micro profile metrics. Which is just that word salad is quite funny. But like my background is app servers. All the way to prehistory. And so I've worked with, I mean, I was at IBM for 21 years. So I worked with WebSphere on ZOS on the mainframe before actually it was WebSphere. And then WebSphere all across all the platforms. And then I was one of the founders of like project that became the project that was Liberty, which is now open liberty. And got to kick all of that off. And then now I get to work with corkis. And I have to say, corkis is just fun. It's just fun. It's great and it's easy. And I as much as I like, like we've had some architectural and design, technical choices that we made when we were creating Liberty that have aged well. Like they were good, solid choices. Corkis is funner, which you know, it's like, oh, that's my baby. But like, no, I like corkis better. I'm going to use the developer joy thing. Oh, I'm going to start saying funner because I'm just going to find her because it's funner. It's a word. It's a word funner. I just am saying it is. I am asserting it's a word. You could totally use it. It's great. All right. We were at the Neb. I don't know if the Neb has opinions because she's done her own things. Yeah. Yeah. Well, I work in the Kamal corkis project, which is the component of Apache Kamal in the corkis. So I work on many extensions for Kamal. Yeah. For me, I'm working in Apache Kamal for a little bit more than three years now. But before I was like a developer using like lots of open tours, libraries and basically for 15 years, I have been most of the time on Java. So around Java. Yeah. But yes, the biggest thing that I worked on is since I am in open tours, is Apache Kamal. Awesome. This is why she's here. She knows a lot more than I do. Exactly. I'm dying to hear. So you both know more than us. And you both know more than us. That's for sure. So that's hands down. So why don't you guys take it away? And the. Sure. We'll see you. Is that OK? Oh, and I should. If you guys, anybody who's watching, if you have questions, toss them in the chat. We can see the chat. Oh, absolutely. And and do you, Erin, do you prefer me to just interrupt you with questions or? Yes. Go to Leigh Ann. OK, all right. Very good. Yeah. Questions are way better than me. Questions are fun. OK, so how can I get my stuff? I have to dip my mouse on the right thing. And then, yeah, then it works. OK, so we were talking, we were chatting before the stream about whether or not people are rebelling against microservices. So I know we said, like, like this whole introduction is, like, integration patterns in microservices. So I did want to talk about, like, what the characteristics are with microservices anyway. And, like, there is a theme with camel about integration patterns, which, you know, I'll get back to. But the twelve factors emerged as, like, emerged as a best practice pattern and you had all of the factors that you were supposed to, yeah, supposed to is the wrong way to say it. Successful microservices followed these twelve factors. That's where they came from. They were emergent from actual successful practice. But what I found in looking at how people actually apply these to when they try to create microservices is that they miss the most important factor. So they might get one second. John said that we are not what's going on here. OK, go figure that out. We, yeah, the link is not active. What? Wow. OK, just a second. Yeah, John said this. He said there's 54 people waiting. What the hell? I can't help you because I can't. No, I didn't go cancel. Yeah, sorry. So YouTube says we're good. So somewhere else that we're good. What? You two are good. You actually see a chat. It was we have a check incoming. YouTube is good. I live on YouTube. What? OK, just keep going. No, wait a second. I don't think it is just a second. What's that? You're going to trim all of this whole beginning part out for that rebroadcast. Right? Yeah. Where I need to. I did this. OK, so anybody that can see us live in YouTube while you're waiting for us for Jeremy to find the right buttons. Put in all of the questions that you might want to see if we can answer. Or if you have camel jokes, those are fine, too. As long as they're, you know, dad joke, flavor, work appropriate jokes. That's fine. OK, so John says he had to go to the main page on YouTube to find it. So it might just be a link issue. Yeah. Yeah, I see it live with three or six people. But I guess it's not the right link. So, Erin, what do you call the camel that drives? What? I can't hear you. Where is it? No, I did. Are we? Oh, my on. Zineb, should we just go? Everybody can hear us. It's just Jeremy and Robert. We could just go without them. Yeah. We could just keep going. Yeah. OK. So he's waiting. The thing everybody is ignoring when they're implementing microservices. Yeah, Robert, it's just you. You must have. Oh, man, it's like it's like this is a train wreck. I hear you. I can't hear you. I can hear you. So he's got volume probably turned on. So the number one thing that I think people are forgetting is that these pieces really actually need to be independent. So, like, if you think about how people do. Deploy microservices are some of the patterns that you see. They can kind of get the autonomy part, because we have auto scaling and we kind of know that things have to go up and down or whatever. We kind of understand portability because we're doing containers now and those can help us port across environments, kind of understand disposability, although I think some people still struck still struggle with a scale back part, especially if they're used to long lived state. They don't really understand how when you scale down, stuff goes away and why that makes eventual consistency important. What they really don't understand is the independent factor. And what I mean by that is like when you have a helm chart or whenever anybody says I have to stand up all five of my services together to be able to test them, you've like broken the independence rule because you then have, you know, entangled codependent services and you're missing the point. So one of the things that we want to do with this whole notion of going beyond rest and crud and understanding, whether you're doing microservices or you're doing something else is how you allow your system to evolve over time, because we do know that we don't usually don't start with a clean slate. I build really ridiculous things. So I very often start with a clean slate, but in real life, that's almost never what you have, which means you're always adapting between one thing and another thing. And the important part about either building up evolvable systems or trying to decouple the life cycles, that was the whole reason we wanted to do microservices to get rid of these monolithic monstrous deployments. And in order to get there, you have to be able to decouple the pieces. And you have to be really conscious about how to do that. That's a very deliberate thing, because you could argue that the whole point of SOA and ESBs was to decouple the system. But the problem with that was all of the information about how the system was supposed to work ended up in the ESB, which just ended up being a new way to completely couple the system, because you couldn't update one thing without updating everything, because you had to touch the ESB. We did it all wrong several times. I mean, in fairness, it's a difficult problem to solve. So I found, and again, this is my app server brain, right? I've either been writing the application server or writing applications in the apps that run in an app server or in a framework kind of situation. So I have never thought about this adaptive tissue, this glue between how you adapt, like how you actually adapt the one thing to the other thing. I could picture on a chart which component that was, but I never really thought about the actual mechanics and glue that go into that stage. So I could describe on any cake diagram or any architecture diagram, here's how messages are routed. Here's how this should flow, and maybe there's a transformation there. I knew the words, but I never actually really thought about how that part happens. And I did talk about patterns earlier. So this is another case of like this enterprise pattern book, the enterprise integration pattern book. It was written, I actually know Bobby Wolf. He worked with me at IBM. This book is old, just like the design pattern books book that I have somewhere on my bookshelf back there. But it is still accurate and applicable. And this is it's another one of those case, like 12 factors and the design patterns book and this book are all articulating emergent patterns. So it's all of the stuff that we know that we did because it worked and we've just put words on it and tried to label it so that we can have a consistent like we understand what we mean when we're talking about this pattern. Like we already know that this is the pattern that works. Here's how we label it so we can put it in diagrams and explain to each other and use common vocabulary. Another good book, as an aside, if you've read Domain Driven Design, an important concept from Domain Driven Design is universal language. And that's what these patterns do. They give you universal language to talk about certain interaction patterns. So camel is an integration framework that allows you pretty much to do anything to anything. It's not terribly opinionated, which as a learner, I found difficult because I could it never was real. This is how you should do something. It was well, if you want to do this and you want to do this, here's how you do that as a learner. I found that challenging, but it has a lot of components and tools and I'll explain a little bit about those in a second, but you don't have to use all of them at the same time. And it's not you don't have to include all of them. Like you're not including this big, you know, big monolithic pile of stuff and making your app or your integrator really big. You just use the parts that you need. It's it's built in a very composable way, really fine grained way. It is an acronym, although I have a feeling the acronym came after the name, right? But they do like this. These attributes are accurate, right? It is concise. It does describe application messaging. It uses exchanges and it is a grammar. It is a language. So I agree with it even though I believe the acronym came afterward. So when we talk about integration patterns and camel message routing, there are some terms that as someone coming from application development or rest patterns or servlets, it is a different vocabulary. So when you talk about a message, you're talking about the data transferred by a route and exchange, like as a noun. It's kind of like the envelope around the data in my head. I used to work at the GIOP protocol, GIOP, IOP protocol level in Corba. And so to me, the envelope is that it's kind of like the IOP message that had all the context ahead of the object key, which then had and then wrapped all the data. So it is that kind of envelope that that contains the data, but it's not necessarily just the wire format in this case. And you do have end points where you have the receiver and the sender as the application developer or writing the applications, you don't usually touch end points directly. Those are provided by a component where a component understands what the protocol needs to do. So it defines the end points for you. So you work indirectly with end points. You're not actually touching them, but the vocabulary is useful to understand what's happening. And then there's processors that you can use to inject custom logic as a route is defined. Did I get that right, Zineb? Check me? Did I make any mistakes? All right, good. I gotta check with the expert, cause I am not. This is all of my learning and I don't know what I'm talking about, right? So this is what I figured out and how I figured out how to articulate it. If there's anyone in the chat who also has never done this, I hope this was useful because I found it a little challenging sometimes to wrap my head around it because it was coming at the whole scenario from a different perspective. So when we were talking earlier, just as a group, I mentioned like I, when I wanna learn something, I do purposeful off-roading. So I build really weird apps that have no, usually make no business sense because I like to play, I learn by play. And so last year I was challenged. I have some friends who challenge me. How about you make a talk on this topic, which I have no idea how to do. So last year it was create a command line application that uses JPA. And you guys are probably like, well, JPA is old, but somehow by some circumstance, I skipped JPA in my early education. I was doing like low level protocol stuff and then I skipped to no SQL. So I kind of like bypass the whole JPA thing. But with the ability now for Java to compile to native, creating command line apps is interesting. It's something we can do now, which means the ability to actually do, like create a command line app that does database things is feasible, like you can actually do it. So I created, so I created this app called Pockets, which is Dungeons and Dragons Inventory Management, RPG, TUT RPG games, because inventory managing your inventory is hard. And most of the tools that focus on your character sheets don't focus on what you have in your pockets or what your friends have in their pockets or what the shared pocket contains. And so that app was just a good way for me to experiment with that. And I'm part of a couple of different communities. And we started talking about this notion of shared pockets. And so another one of my friends was like, well, how about we do a talk on camel or on integration patterns? And I was like, well, this problem about how do we share the contents of our pockets is an interesting variant on that problem. And so I expanded that. So my plan, I added a UI and then I still have my CLI. And so what I wanted to do, and this is low cost for non-tech experts, so it deliberately, there's no web, like there's no standing up containers, there's no connecting to an external service, there's no Kubernetes, there has to be totally self-contained because people just have to be able to run the thing or push the button and then have it do whatever it used to do. And I didn't want it to cost anything because some of the people that I work with, they wouldn't be able to afford to run something like this. So I wanted these two interfaces, these two interaction patterns to be able to go against the same data and get feedback for whatever changed, visible to those sources. And then when I was thinking about how we would share what happened, I thought about making like a JSON log, single line JSON representation of what happened because that is merge friendly in some ways. And the community that I'm in, we really like running things with markdown, having like a markdown, a whole repository of notes and things in markdown. And that gives you the opportunity to do like a richer display, here's what my pockets have, here's the items that I have, I can index them like all the items or all the pockets or cross-reference and all kinds of crazy things. So I wanted to do that come out and then I wanted to leave room for, who knows, what else? Camel again, anything to anything. So Camel has support for writing to Google Sheets. Camel has support for going directly to Git. Camel, like their list of things I could do next and to enable demonstrate a few of them, right? Like sending messages to Telegram. So if somebody puts something in their pocket, I could send a message to the group chat. Like that'd be pretty cool. So we're not gonna spend all day on this app, but for me, this was a demonstration of how I had to change my thinking and then to enable teach you or show you how to make everything that I did easier. So again, I purposefully authored it and did it the hard way. So this kind of endpoint definition is what I'm used to. I write Jaxrs style rest and have four decades. So when I think about rest, I think about this. This is what it looks like. When you're in and in Camel because it's not opinionated, I could still do it this way, which I found confusing because I couldn't then bridge it to this whole other way of doing endpoint definition. Now this one bounces because what I'm trying to show is the compactness and the conciseness of this format. I'm defining multiple end points in about the same number of lines that in Jaxrs I have to define one endpoint. And of course, in that one endpoint definition, it doesn't actually include the business logic so that one would get even a little bigger. But this one is, I can define many of them. It's very concise. The thing to notice and we'll see this pattern continue and continue and continue is that everything is strings. So you can see rest is a verb that's provided by a rest component that understands rest semantics. I can show then the path parameter is right there, goes to rest. I've got methods for get, methods for post, methods for put. They're just like little, you know, it's a fluent API. So they're just little methods there. You can see two, which is how we connect these routes together. So every time you see a two, that's gonna kick off a different route that processes things. You can see a type in there bouncing by, which is how I say I want the payload for that's sent to put to be converted into that type. So I specify the conversion right in there. I have a binding mode at the top which tells it, okay, this is a rest binding mode. You're going to implicitly do JSON conversions using Jackson. The integration with corkis means it will work with the corkis Jackson extension. So that's great. And the reason, like I get a little frustrated with using strings everywhere, but the important thing to know is that even, what? It's a, it's an everywhere you're gonna say something. Now, it wasn't me. Okay, so the interesting thing about, or the frustrating thing for me, or what I thought was weird is like, I'm typing all of these things as strings. And as someone who's worked with Java for over 20 years, that feels wrong to me. It feels fragile to me. It feels like this is where you typo all the time and the stuff doesn't match and you don't know what you're doing and you're like, you never use strings. But I had to remember, like writing this in Java is just one possible DSL, domain-specific language. I could be defining all of these routes in YAML or in XML to the extent where I'm kind of gluing these things together, I can do it with less code. So once I kept remembering that, I was a little less annoyed. I'm doing a lot of direct endpoints here and that's because I was trying to make it simple for myself. I wanted to be able to understand and test the behavior of routes without having to worry about setting up external processes to go talk to. But anytime you see a two here, you could just as easily route it to an external. So. Can you show the transformation piece that you're doing on there? And I gotta say. It's a little tight. It's a little tight right between the put and the two. I can't make it stop because it's just recording the bounces. But it's just that the put that goes to a pocket, the pocket config data, we can, I have the code. So after Zineb goes, we could probably go back to it. But that's how you start directing. Like I want you to do this transformation of type. I want you to take the JSON data and not just go to, you know, go take the JSON and transition it to this particular object type to come into that method. So in the middle here, the two yellow boxes at the top, that is an enterprise integration pattern drawing. So it talks about the two parties, the requester and the replyer. And it's a description. You have the requester makes a request which goes through the channel to the replyer. This is a request response pattern. So the replyer sends a reply which goes to the reply channel. This is how you'll see these kinds of diagrams with these kinds of symbols all through the enterprise integration pattern book to explain how the pattern works. In the case of camel, the rest component understands this request response pattern. The way I've drawn it, and we'll fill in the middle in a few seconds, but in a minute or whatever. But what is important to know is like the rest, the two sides of this drawing are the same component. I'm just trying to, like I'm making a sandwich to demonstrate the concept. So you could see the request icon coming in and you see the reply icon coming out. And what we're gonna do is transform in place the contents of that message. And then the rest component knows what's ever left like the remainder that's in the exchange is what then goes out to the sender. So the rest component understands this request reply pattern and we'll take care of doing that send at the end. So I don't have to do anything. That's just how the rest component unwraps unwinds the stack basically. So, oops. So anyway, from here, right, code. We're gonna focus on one of my end points which is the pocket endpoint, that's line one. And I'm gonna focus on just the post method, right? So I've got a get and I've got two gets like two other get methods defined on line two and line five, we're not gonna talk about those. We're just gonna talk about the post on line eight. And then that one, I'm actually going to another direct endpoint to validate and modify pockets which is what does the interesting work. So that's what we're gonna talk about. When you're defining that direct endpoint, I found it a little confusing although I understand it better now. So here we're doing a two and then when I define the endpoint, I'm doing a from but it's like Camel is handling creating the endpoint and so I'm receiving the messages from, I got real confused with twos and froms. I found that really hard, but maybe that's just my brain. But so here's the definition of this endpoint. I've got some things to set up that are specific like because I've got a web thing and the CLI that's one and done, I turn off auto start. There's other things that I do in other places that will make it start when I want it to start which is that's how you can integrate with different running modes. That's kind of it's important for Quarkis but it's a very easy way to change that behavior and I set up some exceptions that are custom types and that's because I want to make sure that either through the web or through the CLI I can give good feedback to my users because they are not tech savvy. So I have to be able to give them real good messages and not a stack trace because they won't understand what a stack trace is. I always do a log before and after because when I did this I have no idea what I'm doing. So I want to know what the payloads look like and what I've managed to do to them when I'm abusing them. One of the types that you can see this icon coming in with the question mark as an enterprise integration pattern is a process which just basically says we have a custom processor, that kind of component type, that word where I'm gonna do some things at that stage. In this case when I'm coming in from this web UI someone has selected a profile, I need to validate it and I need to then put it on the context in this case. And then I have another like sub process which I'm actually modifying the process or modifying the pockets and dealing with the database. I don't want to go through what that does it's super complicated. And this is if you were looking at us like a real microservices one that would be a candidate for a call out to an actual service. In this case it's in process but this could be like the call out and the response from calling an external service conceptually. And I think, yeah, the bean is I'm calling a bean here to do that route to do the route handler for this. And this is where I start setting up again because I have the requests that I want and the response that I want and I want it to work the same from two different like two different sources. I invoke the bean, I use the bean method to define the route. I have a web route handler. I define the signature that's a bit of reflection to decide on the web route handler I'm going to invoke this do modification method. And that sets up a modification request with the profile name, sets a context, evokes the method and returns the response. So that's a way that we can route into a camel that you can use a bean in camel to inject and perform tasks. My brain is not working. The last thing I have in this route is a wire tap and wire tap is really cool. We'll show what that is, but you can see it's got it's own little, it's another pattern that's well known. It's a T in the path and everything that happens under the T it gets. So it's like I've done the process with modify pockets. I have an exchange that has basically the stuff that I want to return to the original requester whether that's the CLI or the web. When I get to the wire tap, I basically make a copy. So the result goes out to the requester that request response flow finishes. And then the wire tap takes that copy and can do additional things with it. You can observe or log or do additional queuing or any other processing that you want to do. And I do a lot in that case. The CLI has a similar flow with some variants. I don't have to, like the flow in of what that profile is is just it's command line verification. I can create that modification. I have to create the modification request pseudo manually because I'm not coming in through REST where automatic transformations would happen. And then online 11, I call the same modify pockets method. I just do it a little more directly in that case because of where I am in the chain. Because I'm calling that modify pockets directly, this is one way in camel to connect code to routes. So I can define an interface, doesn't do anything. It's just a signature. But then you can see online 10, you use an annotation to bind that signature to a route. So when I invoke that method directly, which is line two is a repetition of what was in the middle of my code. When I invoke that method, I am invoking the route. I am kicking off the route with the required requests and response, which is identical to what the REST path uses. So to make the sandwich in the same way, I've got the direct endpoint on either end. Oops, what did I just do? I don't know what I just did. I did something, there it is. Okay, so I've got the modify pockets. I got my logs, which is the same. In this case, because I'm coming from the CLI, I'm doing the modify pockets a little sooner. And it's just a semantic difference in how things are processed. So I have to set the profile into the context afterwards. It's just a little bit of a different invocation flow, but I'm not writing a lot of code or having to do a lot of, there's not a lot of difference here. It's like the order of lines in the two route definitions is different and that's it. I'm not chasing a lot of extra code that I have to look for microscopic differences in. And so I just have to take the profile that was in the response and put it in the header because the wiretap expects it in the header. So I just have to make sure it's there. And then I use the exact same entire wiretap on the response. And then that response goes back to my CLI, which can print the nice response. Like it can print the information out to the command line output. Perfect. I don't have to write a bunch of stuff twice. I'm super happy about that. Wiretap is cool. I think some of what Zineb will show you, you could picture like this is your fan out of, I have a message, I wanna do all these cool things and send it in all these different places. And it doesn't require a lot of code to do it. So in this case, I'm trying to say, okay, I get to the emit route. Remember, I'm using direct endpoints because I just wanted to simplify my life with how much I had to deal with. I'm gonna call a handler. And what the handler does is it checks my config. This is just for me. So it checks, so line seven is JSON log enabled, line 14 is markdown enabled. If I have other things, I could check for other things to just keep saying this, yeah, this emitter is enabled, this emitter is enabled. Line 17, I combine them all into a comma separated list, which is what the recipient list, which is another pattern, right? So here I'm in the middle of a route off of a wiretap and I'm gonna use another integration pattern called a recipient list to take the header containing the comma separated list of routes and call them all. So I've got my copy of the output, I am now going to spread it across however many things I have enabled. And then on line five, I'm gonna do those in parallel. I have to say this is a lot easier than writing my own executor or doing a lot of other things that take a lot more, like that's so compact and Camel just does all of the stuff. I actually was like, why do we ever do it the other way? Cause this just makes a lot of code go away that I never thought about not having to do. I don't know why maybe I'm weird. Everybody can tell me, Aaron, you're weird. That's fine. When we look at a JSON emitter, like how do I take my object, this response that I have and send it to a single line JSON file, which was my goal for this. How you define that is fairly trivial. I'm setting, I'm taking again, I'm munging these, the message in place basically still, but it's a copy. So I've got the copy that's gonna go to JSON. I'm gonna add a header that sets what the file name should be. There uses a simple grammar there to plug in the profile.events.json out. That's gonna be the file name. I'm gonna reset the new body of the message. So I'm gonna take the old body of the message like on line 10, this is what I'm doing. I'm gonna take the old body of the message and I'm gonna transfer it to a single end JSON string and set that as the new body of the message. And then I'm gonna use two with a capital D as special. It means it's like a dynamic too. It means camel at build time, you cannot optimize your understanding of what this route is, thou shalt wait and use grammar to figure out at runtime what that value needs to be. And so at that point, I can say here's the file. File is a component. It's a basic part of camel. I don't have to define it or code anything to make that work. Aside from ensuring the file camel component is in my class path somewhere. So I'm gonna say use the file component right to that file. Append to it if it exists with a line ending character backslash n, so I do the next line. And if the body is empty, that's fine. We'll add a line. So that's how I get a JSON log that just contains all of the events that have happened. The markdown emitter, remember that was the other thing I wanted to do is take these changes and make a pile of markdown files for them. And this one, it's like the general flow is the same. I have an endpoint. I've got my exceptions that I'm gonna handle. I'm gonna use a bean in this case to inject custom logic for how these markdown files should be emitted. And that one is interesting. I'll show you how the actual emitter works in a second. But a thing we can do with Quarkis is combine, like bring in cute templates. Cute templates are amazing. They're like handlebars in Node. If you do any front-end stuff with handlebars or it's a really nice syntax for creating templated output. One of the things we can do when we combine that with camel is like line seven, I'm saying, okay, we're gonna use the cute endpoint, the cute component that knows how to do cute things. I have a dummy URL, because I don't need it, it doesn't mean anything. The query parameter there allow template from header means, okay, cute engine. You're gonna look in the payload in the headers of this message for the template instance to use. And then it's the same as file on line nine. We're gonna take the rendered output of cute from line seven and write it to that file. So that part's familiar and the same. So if I go to my emit handler, my emit routes, here's where I am. Here's the JSON, make that smaller and bigger. So here's where we were on the slides. If I go to that route handler, when I try to emit the markdown files, there's a lot of stuff that I do in here, like looking at configuration for what files people have enabled. There's some things that I do for keeping track of state, what changed, journals are records, what's the items, what's the pockets, what's the coins, how many coins do we have, what pockets are they in? Here's where the intersection with cute is cool. I can do template instances. Here's where I go find the template instances. So for journals, I can use a certain kind of template. This is the other way to invoke an endpoint that's not using that interface before. I'm calling a producer template. Oh, stop the hover. I'm telling it which endpoint it should invoke. I'm creating an exchange that has the data that I need for that template. And I can then do the same for items in the inventory, for pockets, and I get then out of that a whole collection of markdown files. This is probably, I mean, again, I'm doing a lot with a very little bit of code. I'm using markdown templates, templates like this. Here's the kind of syntax for acute template to render that output. And I have one for what that JSON, an event log based on the journal output, what pockets look like. When I'm trying to run, I wanna let Zineb do the cool things. But if I have, if we scroll up a little bit to look at output, you can see I've got, let me see if I can find a good one, a good test. Here's a nice, big, long one. In this one, I'm invoking here. I'm invoking the emitter routes and you can start to see where the exchange patterns are, what the body type is. I have the mock config that I'm using, which is normal. Here's where I start to load what my templates are. You can start to see what that body looks like as it's emitting those templates. And it's very, it's, you can see where it forks and says I'm gonna do three or things at the same time because I did that in parallel. Whoops. If I go down to the target, I wanna let Zineb do all the cool things because I did this, I did this the hard way. So if I look at what was generated, no, that's not what I want, I want this one. So what would you start with? The hard way, I did all of this with manual string manipulation and understanding like right, hard coding all this stuff and figuring it out all out myself. So if I look at some of the output, like here's the JSON log that I wrote with that JSON emitter, right? So it contains the stream, the stringified record of the actions that I performed on my pockets. If I look at the ad item, right? Where I went to that markdown thing and generated a bunch of files for it, I have an event log, which if we look at the preview, right? What would show up in my notes that I would like, right? I get this nice event log that shows what happens. I'd be writing this file from scratch every time, but usually that's okay. I can have a nice inventory, right? Where I can see here's the pockets that I have. Here's the currency that I have. Here's the items that I have. If I looked at it as like an index of inventory, but I could just look at the backpack, right? And see, okay, here's what's in this particular backpack. And so the idea then is I could share this, like I could share this single line JSON activity for a pocket with my friends and they would be able to render the same information in a similar format. And then we can all see our pockets. So that was like my goal for my demo. And I tried to show my thought process on why I did it and the kinds of patterns that I used, specifically like the recipient list, the wiretap, integrating with Qt in order to really show, I don't know, for me, like I needed a purpose and reason for doing that. I found it really cool and interesting and it's gonna, you know, I have more things to do with the community to actually get some of the sharing stuff working. But I'm, I don't know, I found it really cool. I don't, but also a really difficult thought exercise. It was really hard for me to shift my thinking around. I don't know if anybody else in the community would feel the same way. But I will let Zinib, Zinib show you how to do it easier if we want to switch. She could show you the cool stuff. I showed you the hard way. I don't do like big transformation things, but I'm like, I really like your example with Qt and everything because I think like this is the way to do. So yeah, I'm more like doing like lots of cool components in general, but I try to move a bit like for our topic today which is rest. So yeah, just to, in order some people don't know because you show so many things that when you were thinking about message, always know that there's a body and headers, maybe other things in the message. And that's when you are in one route, like if we don't change at some step, the body or the headers, they're still there until like one of those lines of the route like changes completely the body. So one of the things is to be aware also when you do, at what time you send your data or you use the recipient list or wire pack. So for me, what I done is that I took one of the, one of the demos that I had before of an order API which has actually gets actually order of one coffee and then you can actually get all the coffees or get one coffee by ID, but also the thinking of when you order that coffee, you need to deliver that order. Maybe you want to generate an email at some point or a file with the bell or whatever. I'm not gonna do all of it and a nice bill but I'm just like doing some steps to show a bit like how we can do this. So I'm using rest as this is what Erin has done. So you know everything about this. Just to know that this, maybe I can show this like very, very quickly. I generate, create my apps. Me, I do the code that corpus and I use. Sometimes I use the corpus.ly but like if you type, come over here, you're gonna find the extensions that I use. So when we are creating a Java app, we would need actually to say, hey, I'm using rest, so I need to come to rest. I'm using Telegram, so I am going to pick Telegram. So all of those needs to be actually in our Conduct XML. So here I have like some corpus things and I have some come all things. And in order to write and read from the database, what I, we can use like lots of components. What I'm using is JPA, I don't know, GPA or JPA, sorry for my English. But yeah, I have my order here. So I have like the basic information that we have. I have a name query here but this is like my simple Java object and the ID is generated. But at the beginning I have like some random coffee that comes in this way because I don't have anything to generate data. So I'm using a random API that gets me the information like this. But this is not what I want in my database. I want my information to be this way. So I'm using it, my own Java being where I take that Java object and I just like return it the way I want in a copy order. And here I just generate a very basic notification. So I'm just notifying someone to deliver my message in telegram. So I just wanna like one line like saying, hey, you need to go deliver one order and that order has that ID and that person is supposed actually to use some app that we call this API. So my rest actually endpoints, I have three. So I have a post like when I create an order and I have this one to list all the coffee orders and I have one that can give me one specific coffee order so that the delivery people can know where to show them. So the data is really basic and I have another route. So of course all the classes for routes, the extent routes builder and the methods are in configure if we do it the Java way. And here what I have is that just have my routes. So this one are very basic. So if you want to, you can add like exception, handling errors, you can add logs in a, very specific way of logging, you can even define something like for all the app. So that's for a more advanced thing and some of the things that Erin has shown. But here like just to now like when I use Como, if I want to insert an order, I just like do this line and it's gonna handle it for me. If I want to to get- That works really well when you have the JPA table, whatever it's thinking, matching the fields of your object really clearly, right? So you just have to do the thing and it'll do all the magic. Yeah, and here I did two different things. It's here I create my query myself from that class. That's an entity and using the header ID in order to get the ID. And here I am using the named query. But of course you can use other stuff in Como, but this is like what I need to create an order, to get all orders and to get one. And I don't have a database, so I'm gonna use Qoacus Dev Services. So all I'm gonna say is drop and create. I have the extensions from Postgres SQL, the Qoacus one. If you don't have one of those ones, like Camel, as you say, needs to bring one extension for database or otherwise it doesn't know what to do. So I'm just gonna start the app. I have a question. So is it typical practice? I noticed both of y'all had like your, you basically built out like one route had all of your rest things. And then the other, there was another route that kind of did the work. Yeah, actually what I did is that, so here I define my routes. And generally when you look at the routes written by people, when it's too long like that, they use that direct. So direct actually will create another endpoint that is not based on any components, but it's just like you in orders so that it's easier. So here I have a direct add order and orders API order. And this is what will happen if you did a get, if you did a post, and if you go to the other one just to show that you can actually split them. They can be in the same Java plus. You can split them in other class, it still works. Yeah, for me generally, I do that because as a, someone who thinks about what my rest API looks like, is it consistent? Like, does it follow a pattern? Do the verbs make sense with each other? And do the query parameters make sense with each other? I would pick that really condensed format and move the extra stuff out specifically so I can see, do my post like does the get, post put verbs make sense with the query parameters? Like, is this a logical set of things that would be intelligible for another person without necessarily having to go do an open API definition view? Like, I just wanna make sure when I'm writing these things, do they make sense next to each other as a whole? Yeah, that makes sense. So here I created one. So it says, thank you for your order. We're gonna go back and check that this is what I wanted to have as a message. And then here I can see that I have only one, which is the plan name, Hello Forester. And if I get this first one, which ID one, I have this one. I can try to get another random data to post, just to have some data, easy data. So here I'm gonna have like the other one, which is different. And if I try the two I would have, if I try another ID that I don't have, I still have something empty. So that was like so easy to do this. So what I want is like, okay, so I have these ones, but I want to have like generator file, just to have like an idea of what we can have, like for example, go to your account, you ordered coffee, you want to click on the orders, you have a file, but also that the person that needs to prepare the order, just to have like a message. So here I have my boats. It's a Kamal Fakus boat that I use a lot of times. And I do have, where is my Chrome? I do have here a bucket in Amazon history, where I don't have any files. So what I wanna do is to add at some point the wiretap, for example, at this point. So here that I send the message to JPA, I want to just do something to notify. And it's complaining. Yeah, because I don't have the direct thing notified. And then I just kind of put them because I'm not gonna, that's not it. So of course I don't have the right keyboard, I'm sorry. Notify and... That is the camel extension magic, right? Is that the camel extension doing that? And notice you have camel there or you have magic buttons. Yeah, I have magic buttons. Actually, the camel, I have here the plugin, it's the Apache Camel. And of course, here if I do, let's say telegram, here he's gonna say, you need a type, one of the type is boats. And it can give me, for example, the properties that I can use. Way less typo, see, this is... You can do here the camel break point, because if you do the simple Java line break point, it does not gonna go inside. And the same way, because here I have, for example, for telegram and history, I have like those properties also here. I don't copy pass them. What I do is I do camel that component. For example, here I want, I don't know, secrets manager, it's gonna tell me access key. Yeah, this is how you do strings without typing them. Yeah, yeah. And I am on IntelliJ, but yeah, if you're on VS Code or Eclipse, it seems that it works better. But this one is like more the magic of IntelliJ that I have like my templates. And if I do like that, I have what I need, notify the name. So yeah, so this one, like you can, for example, imagine that you're gonna push this to Kafka or something and then, you know, like those events will go elsewhere. But here, for example, to send to Amazon S3, I just want to send the JSON file. So remember, it's the coffee order Java. So here I'm just telling it like, switch this to JSON. I'm adding a key. It's gonna be the key for the file. And because just the demo I'm using a random UID, here I'm just log in and I'm sending to my backup name. So this is also something if you don't want to, you know, type something or maybe the name are not the same in production and in test environment, you can actually use this kind of thing. So this is defining my properties. And then you can, even here, for example, I'm using all environment variables. So for my token, for my chat ID, so you can use it this way. Like for example, if you are on Kubernetes or something, this is how I do it personally. And here also I did the same thing from the chat ID. So here I'm just like using my bean to generate that message. And I say, hey, I am sending it to my chat ID. So here, the magic of DevMod Live Reload. If I do this again, if I send one order, it generates me a message. If I go to Amazon S3, I have a file. And this file which you called in Jason, that's it. For me, the most difficult part is to set up the credential for Amazon S3 and the first time the telegram. But then writing the code is just easy. So this is it. So yeah. Why did I ever write code the other way? Why do I write code the other way? I don't understand anymore. Yeah, it's really succinct, right? I mean, this is really nice and succinct. And it's pretty easy to read once you kind of wrap your head around it. Yeah. It says what it's doing, right? Yeah. I didn't want to call out. If you're not a Java developer, you could do like YAML files for Kubernetes. And there are lots of tools that can help you actually write things. So let me check, where is it? I have something here, for example, which is just one of the things that we have in community. So yeah, this is like, it's gonna generate you a YAML file. You can have like your components, like here you can do rest, then you can do set body, for example. So you see here, there's the components and here's like you can have the choice, for example. And you just click here and you have a when, you have an otherwise. What is it? And then you go to the source and you have like the route. And this is Kyoto, this is BS code actually. So there is Kyoto, there is Caravan, there are two tools that you can do those files that you're gonna deploy directly to Kubernetes. And for example here, I set some components, I set here just an expression. I'm not like, and because I don't want to run it on Kubernetes, I can use Camel J-Bank, but I don't have to do it myself because those, so it's not running today, but I just, it was running, but if it was like well-defined, it should run, or maybe I know why it's not running. I think it's just maybe the same. This is just the demo things. So I did wanna follow up before we went too far. The endpoint, like when you define the endpoint for, if you go back to your code in IntelliJ with the credentials. So she's using two there, where I had a place that was too dynamic. And the difference is when you have environment variables, that can be read and stored, one and done at startup time, right? And so then when I was using too dynamic, it's like you can't do that until the route is run, right? Because it's variables that come in with a request. So that's the difference between the two, right? So the two is I'm gonna use the stuff that's present at startup, environment variables, startup properties, whatever. And then two dynamic is at invocation time. I'm gonna calculate that. That's the difference between the two. Yeah, for example, when you use here the header ID, yeah, you need to be on this exchange that has that header ID, the copy order that you are searching. So at this time, you have this dynamic. But this one is gonna be here at startup time, yeah. That's the thing, yeah. So that was like my demo. I always show a demo when you can like connect to many things very easily. And of course, you can change some of the things you can instead of sending to S3 another time, you're gonna send to something in Azure, for example. And you don't have to change a lot of the codes. Like you're gonna change very easily the sender part. But when you are on Java, the cool thing is that you can use processor, you can use the beans. So you can do something like very more complexity than when you are on a YAML file for example, for Kubernetes. And of course, you can deploy this on Kubernetes. And I always show Java because I like the Java DSL. And I know that I'm not gonna be stuck on it because of the space in YAML. So yeah, I'm a fan of Java. If you're using Kubernetes, you're already using a lot of YAML. So yeah. Yeah. Yeah, but I would, I do like, yeah, go ahead. What I was saying is like- I like that you have the YAML plugin. So. Yes, yes, yes, yeah. Yeah, right now, at the beginning of the core history it was not ready yet, but right now it's working. So if you are on IntelliJ, but if you are on VS Code you should probably have like more things and that are available. Yeah, thanks. This is really cool. But I really like the conciseness. And I agreed like Erin said, I've written Jaxrs for ages, right? And I always thought Jaxrs was pretty nice, like pretty nice API, right? But this is definitely much more concise and allows you to do a lot of things. And what I like is like you say right there, your being is calling a being log is logging, right? Why are it happening? It's really descriptive of what's happening. Like once you kind of get your head around what this does you can come look at somebody else's code, right? And code's read more than it's written. It's pretty obvious what's going on, right? I like it because I like Cannell anyway, but you can add things really easy here that are not, that take a lot more code the other way. So like if you wanted to add exception handling, that's one line of code. But if you want to actually take action on it or do something dynamic, so you could do, there's a lot, Cannell has a lot of things like built in like a dynamic router or a slip routing kind of thing, right? So I could fork off the call and say, based on that conditional and make it really concise because it would just say dynamic router dot dynamic router right there and then create a rule that sends it someplace else. It's just so easy. Oh, and earlier, I have to go back to this but earlier I said a joke and I couldn't actually hear myself for technical reasons here. Did you, do you remember what that was, Erin? No. Oh, you don't, oh, yeah, yeah, yeah, yeah. Yeah, I have to get the dad joke in here, right? So, you know, you know, let's, you know, where do you park at Camel? Where? In a Camelot, right? What do you call a Camel by price? What? A humpback whale. Oh no! Oh, okay. That's terrible! I got one more word really that's worse than those. So what kind of camel throws a hissy fit in? Look at it. What? A drama dairy. Okay, there you go. Camels are pretty big animals. I don't know if I want to be taxed. You know, I don't think I would be. I had to get some dad jokes in here today because, you know, our little... So John, I see John in the chat and if anyone else in the chat has any comments, we were kind of everywhere. And I know I gave him a random thing. I actually went slower than I usually do. But to never thank you for showing me all the extensions, like actually showing the extension stuff and some other usage of wiretap that actually goes out to places. Because I didn't went in. Would you show your title screen with the links to the GitHub repo? I can, I have it. Wait, where did I put it? I just have our... It's not our, I have to go through all of our things. Come on, Aaron. Oh yeah. Yes, everybody. So if you guys want to look at, you want to grab these repos. Which I'm not, I want to go down really. I'm going to... Yeah, these are just our repos, which I'm like, my GitHub has tons of repos in it. But we can put, when you, I'll go put the links to ours as comments under the show tag if we want to do that. I can add it to the YouTube thing. All right. Great. All right, thank you very much for joining us. This is a really, really cool presentation. I appreciate you guys doing this this month. Maybe we can have you back. Me too. Yeah. All right, thank you very much. Thank you to everybody who attended. Bye-bye. You're a dad jokes. Yeah.