JCON EUROPE

Reactive Web Apps With 100% Java | Leif Åstrand (EN)

47:37 · 20 Apr 2026 – 23 Apr 2026 · YouTube

About this talk

In this talk, the speaker introduces Vaadin, an application framework for building web applications using only Java. He explains the challenges developers face with front-end development, such as managing multiple stacks and dependencies. The session highlights Vaadin's new features, including reactive UI state management that simplifies application interactivity. The speaker conducts live coding to demonstrate building a simple application with features like dynamic text fields and collaborative to-do lists. He also discusses using Spring with Vaadin and shares insights from a community survey about developer productivity using Vaadin. The session concludes with a Q&A, addressing common queries about compatibility and integration with other technologies.

Full transcript

So, uh before we start, there you got the Slido QR code in in case you want to ask any questions. I will look at them at the end, but I will also do lots of live live coding, and in that case, just shout out if there's anything where you want to help me when I need it, or uh if you kind of have any questions what what's

going on and so on at that right moment. So, I'm Leif. I work at Vaadin. I basically a little bit of architecture, a little bit of product management, a little bit just kind of trying to look ahead and figuring out what what we should do in the future. Uh And you? I guess you're here to learn about building web apps using only Java. And at this time,

if you haven't heard about Vaadin before, then obviously, you will get to know about Vaadin. Maybe you have looked at Vaadin previously and didn't really make sense for you at that point. It might be good to take a look again because what I will be showing you now, it's it's a new stuff that we have released just kind of a couple of months ago, and in my

opinion, maybe I'm biased because I came up with the idea, but in it kind of changes what Vaadin is is in a quite fundamental way. So, it's kind of a new framework, you could almost say. And of course, also, if you are already an existing happy Vaadin user, then you will also now get to see what this new reactive UI state management, as we call it, what

it really means. But what's what's the point with Vaadin, really? who here is a Java developer? Great, you're at the right conference. Who is also a front-end developer? Okay, so like 10 persons, maybe. Who thinks front-end development is easy? Two, two, two, three brave persons. Oh, you surprised me. I mean easy, difficult, it's always just software engineering. It's supposed to be difficult. We make it difficult for

ourselves, otherwise. but I think one thing that makes front-end development quite difficult often is that you have two kind of you build your own stack, typically. So, you choose your kind of these are these are the UI components you want to be using, or maybe you even build them from scratch from just kind of low-level HTML elements. You have your front-end library you use, like React, Angular,

whatnot. You you got your communication method between between the back-end and the server, so your REST endpoints, or gRPC, or whatever you use there. And then, of course, the back-end, like I thought you said you were Java developers, so I guess you use like Spring, or Quarkus, or plain Jakarta EE, or something like that. But whatever you the thing really is that you manage the stack. You

make sure all of those parts are compatible, and whenever anything's updated it might or might not work without changes, and and in practice, it never works. So, the option, of course, is to have a an opinionated stack. Someone else puts together it, sees that, okay, these things work together, these versions are compatible, and then when they're you know already that they work together. So, of course, this

is a trade-off. You get more productivity when you don't need to do those things on your own, but also you give up give up a little bit of control, so there's no right and wrong answer. It just depends on what you need. Another thing that I think makes challenging at times is if you have separate teams doing front-end and back-end. Because then you end up with lots

of handovers, lots of just communicating, lots of just waiting for the other team continue building on whatever you were building. And and I mean it just it's a waste of time you could even say. But instead, with a full-stack approach, when you got everything as just one application, one team, then that's that's very much more productive in in in many ways. Uh we did a community survey

like couple of years ago. And one of the things we asked our users was that "Do you feel more productive using Vaadin than with whatever you used before?" And like 98% said that "Yes, we do." And also they had on average like 45% time savings. And since most of the time in software development goes to actually develop me uh most of the cost go to development, that's

also then kind of saving costs. Of course, this is what they kind of already Vaadin enthusiasts self-reported in that survey. So, I can't promise it will be the same for everyone, but it's at least some kind of indication. Now, I promised live coding. There will be a plenty of live coding. But before we get there, I'm going to show a little bit kind of the really essential

concepts so that you know what what we're talking about then. In Vaadin, everything is a component and everything is a Java object. So, if you want a button, you create an instance of the button class. Quite easy, right? If you want a date picker, you create an instance of the date picker class. If you want a grid of persons, a grid of persons. So, I mean, we

we we really take naming seriously to continue from that, kind of building an application out of those components, there are layouts. Layout is something that you can put many components into and then, in this case, the vertical layout, they are visually vertically aligned. So, nothing nothing surprising there. If you want to do the opposite, horizontally, then you do a horizontal layout. There are more more kind of

advanced layouts for specific use cases like forms and so on also, but just these two basic layouts, they can get you really far. And then, layouts are also components, so you can put layouts inside layouts. So, you can create arbitrary structures just by putting instances inside inside other instances. Then, the next step towards having an actual application have a building views. So, a view, that's your own

component. It typically extends some built-in component like the vertical layout. And then, you have that one annotation at route saying that this is the path that this view has. So, in this case, it's {slash} hello in the browser through that annotation. Finally, you want your application to also be dynamic, so that when the user does something, something changes. And for that, uh and this is kind of

the the new approach that we are launching right now with Reactive UI state management. Very familiar if you have been using for instance Angular or React Key Key concept is that for anything that changes you get a signal. A signal is a holder of a value. In this case we create a text field. We bind the value of the text field to that signal. So that whenever

the signal changes the value in the text field changes. If the user changes the value in the text field, then the signal value is updated. And then finally we create a span for that showing the greeting. It uses a lambda, a callback that is run automatically again whenever the signal value changes and then that value is used as the text in that span. And finally finally we

also bind the visibility of that span to be so that it's visible only when the value in the signal, which is a string, when that string is not blank. A little bit more kind of graphical representation of this. So when you open start with the navigation setting up all the configuration. These are the signal bindings. These are the the signals. These are the components, how they relate

to each other and so on. Set up the initial state there and then kind of entering this basic interaction loop. User does something an event goes to the application logic. You update some state. That state is then kind of used, applied by the bindings, and then the user sees the updated view, and then based on that they can continue using the application. All of this Apache 2

license library. You can use it whatever way you want. You can fork it. You can you know the deal. We also do have some more advanced UI components for kind of enterprise use cases and so on extended support support services in in general and so on but like 95% of our users just use the free parts of Vaadin and they are really happy with that. So, we

got some new found powers. Let's put them to good use. I will be building hopefully the same application that I already put on GitHub also. So, you can scan that code if you want to also maybe follow along or have a look at it later Give you a moment to get that done. I see a couple of phones raised still. Still more phones? Some people were a

bit shy. I don't know if I should do it or then still deciding to do it. All right. Are we done? Yes, great. the journey starts in our case on start.spring.io. You can use Quarkus, you can use Jakarta EE and so on but I think it's it's practical to just start here with the Spring Initializr. Let's make it a little bit bigger still. So, I chose in

Java as a language Maven for the build latest Spring version all the basic stuff here. Adding Vaadin as a dependency and also I want to have a backend for this application just using an H2 database here and that's what not the button I should press. Uh that was the button. Uh and I'm going to use Spring Data JPA also for for just simple hooking up the backend

here. So, let's download that. Unzip it. Unzip it. Thank you. Uh and then let's jump into the IDE. I'm using Eclipse. Historical reasons. Sorry about that. Uh you should probably use uh IntelliJ or VS Code or Cloud Code or Notepad or whatever. It doesn't really matter. Use whatever you prefer for for for Java purposes. So, I'm going to import the project real quick here. There we have

it. Jumping into it. And then let's see if the font size is acceptable. Let's make it a little bit bigger like this maybe. Is that good in the back? Yes, I see thumbs up. Great. So, what do we got here? We got pom.xml with just the basic dependencies like like uh well, Spring Spring Boot Starter and so on. We got H2 database. We got uh Vaadin Spring

Boot Starter. That's quite essential. And also an optional development mode dependency. And we got a Maven plug-in for doing production builds and so on. To actually build something here, let's create a class for a view. No, let's not start it yet. Let's create a class for a view, I said. That's the button. No. What? Maybe I started it still. So, I have a class uh main main

view like so. And let's make it extend the You wouldn't believe how difficult it's to type from this place. Vertical layout. Uh usually takes a minute to get up to speed. So, um let's do a constructor here. And in that, let's just first see that we got anything running. So, add a new H1 H1 Yes. Saying Hello Vaadin. With that done, let's go to the main application

here and run it. I'm running it using hot swap agent, so that's like customized JVM that can do much more live updating of code without having to redeploy all the time. Oh, I forgot to add a at route annotation. No, not here. But on the view. On the view, add Come on. Here we should have an at route annotation also. Otherwise, it says that yeah, we don't

have anything in the So now let's try. Okay, maybe I need to redeploy now because I screwed up the the sequence. Oh, I haven't saved. That might also be a reason. But now I'm also redeploying. Let's make it so we can see both at the same time. Did it launch already? Now it's there with my excellent capitalization and everything. Let's make it a little bit bigger. All

right. So, it also here in the console says that kind of we are now we have there is no actual configuration, blah blah blah. So, that's something we're typically, if you want to configure anything more, we we also have this main method thing to also be implementing a app shell configurator. Uh and that's basically how Vaadin things are configured. We need to actually again restart to get

that picked up. So, let's wait a quick moment there. >> Yep. So, now we see a different looking application because the font has changed and so on. And that's because now we are currently not loading any styles again. So, now with the app shell configurator, we need to explicitly say that we should load the built-in styles for Vaadin's built-in components. And now we again have something that

looks it looks like it used to do. So, let's build a little bit more interact- interactivity here. So, uh let's replicate what we had on the last code slide. So, we got a uh new text field. Text field. And in that we say ask for your name. That's a name field, of course. And then to get the value from that, we need a signal, so a new

value signal. And let's name that like name signal. Let's turn it into an instance field And then let's just actually add the name field. See that we got it on the screen. Yes, there we have that. And then let's bind the the value. So, bind value. Bind value. And name signal and then name sign- name signal colon colon set in this case since we just want to

pass it straight through. We will also do some other things with it. And then we need to show the greeting. So, new span span. And that's a greeting and we're going to do greeting. dot Bind text. And we're not going to do just a name signal, but actually do name signal No, actually comma Comma should be on the inside. Plus name signal dot get. Like so. And

let's put the space in the right place. So, and then finally add that to the Also. And oh, I'll get an empty here also. And then now I can type my name. Let's make it a little bit bigger still. And then when I hit enter, it actually updates. One thing, if you have been using Vading one thing you will notice here is that one benefit we get

immediately from this is that when it live uh updates, like if I like add a couple of exclamation marks at the end, immediately when I save, it refreshes thanks to the hot swap, but it also remembers the value in this signal. And that's very, very convenient that whatever you have kind of typed in, whatever selections you have made, they are actually now also preserved when you when

it redeploys. So, that's something I was always jealous of how React, for instance, had that with hot hot module reload. So, what we're going to do next? Um We should see that actually there's a couple of issues here if I reload. Uh we see that oh, it's always showing this this thing. So, let's also bind the visibility here. Greeting dot bind visibility. And there we have a

callback saying name get is blank. And we actually want to do not blank, like so. And then also let's make it a little bit nicer, so we say to the name field set value change mode eager. Eager, like so. So, that it Yeah, yeah, I had a typo when I saved. So, that immediately when I type even a single character then it also updates as I type.

Like this. Almost can't type my name name today. And when when when you kind of look at many people say that what's this magic? How does it work? And that's a fair question. So let's actually quickly have a look at that. I will stop now this running in the development mode and let's make this a little bit bigger also. Go to downloads and demo was the name

of this thing. I'm going to do a production build so just Maven package. The point here is just to kind of avoid all the extra requests and things that happen in production and development mode so that we can actually see what goes on. So if I now do Java this is Spring Boot application so it's just Java jar target {slash} demo something. And when that runs let's

take it actually bigger now. So now we're running in production mode. And the first thing we notice is that kind of the HTML here that's not where the actual content is. There are a little bit of very kind of placeholder CSS. There's some scripts here and and basically here's the main body and script. This is part of the framework. It's a rendering engine that is loaded at

startup and then it contacts the server to say that now we are at this view can you please send me the rendering instructions for that and So if you look at the requests here let's zoom a little bit. When I reload we see that it loads kind of that main script some helper scripts CSS a font and and not much more. And then when I type something

into it actually let's clear it. So when I type one more letter there it sends a request. If you look at that the request payload it basically says that now this is the value inside this text field. And then we get a response back with a bunch of metadata, but also kind of this is now the value that should be in the span with ID 4. So,

that's kind of the basic thing about how it works. If you look at this kind of again the same interaction diagram loading the page, that's just a regular get request when you enter it into the address bar. And then the kind of cycle here always goes so that user event goes to the server as an HTTP request, basically an AJAX request. And then response to that same

request passes back updated rendering instructions based on the bindings that were evaluated. Let's continue building the application though, because what I really want to build here is a to do app to keep track of what I'm actually doing. So, first I'm going to need an entity for that, so let's create a to do entity. And it's an entity, all right. It's going to have an ID of

course, and that's an ID and it's generated. we're going to have a string with just the name of the task. And we're going to have a boolean saying that is this now done or not. And let's generate all the setters and getters for it. These select all. Done. Great. And then let's create our repository interface also. So, that's to do repo. It extends uh JPA repository. Yep,

for to do and with an integer ID. And we don't need anything more in that. So, let's start the server. because again creating new repos is one of the things that Hot Swap also doesn't take care of, but once once we are through this, we shouldn't need to start it anymore. Except that now we should. We have an issue somewhere. I still have Oh, thank you very

much. Yes, let's stop the production build and run it again in in this mode. And let's close this. Is it starting? Now it's up. Yep, so now we got it up and running again. Great, let's close these. We don't need them. So, what we're going to it is gradually just change things here. So, uh we'll use this same text field for entering what is the text field

what is the new task we want to create. So, new task maybe. And let's rename this also to kind of create task field. the signal is now create task signal And then we don't want to spam, we want a button. that says like create task or something. And then that's a create task button. Almost type like that. And then we're going to add that to the view.

Then we're going to delete those and kind of reusing the same logic, but instead of setting it visible, let's set it enabled whenever there's a text there. So, if you save this, we now have so that immediately when I type anything here, it lets me create a So, let's actually make that button do Create task button. Add a click listener. Uh we get a click event here.

And before we forget it, we should also give this button a click shortcut. So, that means that also by hitting enter on the keyboard, I can also submit a new task. So, uh key .enter We don't want to have any modifiers, but we want to listen only on the field, but not if you press enter anywhere else. In the listener, what we need to do is create

a new entity, new to-do. we set the task of that Did I need to What's wrong here now? Nothing? Okay, now it Now I saved with hot swap on again. No, why is it To-do cannot be scrolled to a type. Did I type over the name of the No? These are exactly the fun things with live coding, isn't it? I've got a to-do.java. It looks like a

class. Ah, yes, I think when I switch between Maven and Eclipse, it got confused. So, I need to clean through Eclipse once. Now it found the to-do. Great. To-do. uh set task And here now we need to read the value from the signal. So, uh that's the create task signal. And in this case, we're not getting the value because that's kind of a reactive thing, but we

don't want this action to be done again and again and again every time the the signal value changes. So, instead, we would do peak, which doesn't uh do it in a reactive way. We should also take this signal and set the value back back to empty so that we can submit a new one and then finally repo not replace no ah we need to inject repo also.

So to do repo repo here ah this is integrated with spring and also with CDI so you can just inject whatever you want there. I need to import it yes. And repo.save What's it? Didn't I import you? I didn't. What's wrong with this today? It worked very well this morning. What's the name of the class? To do repo yes, no typos there. Copy pasting to be safe.

Now it works. If you do not succeed then try and try That's what I learned from an old James Bond movie. Ah repo.save ah and we save the to do there. All right so now let's start the server Okay nothing has changed of course because we didn't ah change anything the UI ah but just also to kind of prove the point I'm putting a break point here

in this click listener and now let's add that to do for for instance ah for showing a summary. And when I hit enter it kind of made that request runs this click listener and here we can do all the regular debugging that we would want to do. Ah of course I don't have bugs so I don't do that. Ah and now we also saved that one to

do in the database but we can't see it yet. So So, do that next. Ah for that, we're going to need a list of all the to-dos that we want to show in the in in the UI as kind of view state. So, that's another signal. In that case, it's a list signal. List signal. let's name it to-dos, and the type is to First thing we're going

to do in the constructor when we load this view, we're going to get from the repo find all the to-dos. Let's not do any lazy loading today. Uh and for each of them, we also want to insert it to-dos colon colon insert last. Insert last. So, that we populate the view state with the state that we have in the database. Going to do the same also when

we save a new to-do. Actually, this returns a new instance that we want to use, and then we do repo No, not repo, but to-dos. To-dos dot insert last. To do. And then finally, we want to show something. So, we're going to create a new vertical layout for showing all the to-dos. That's a to-dos layout. Uh let's add it to the view immediately, so we don't forget

that. To-dos layout. And here also finally, we're going to for the layout, we're going to bind the children. So, that means is that the children of vertical layout will be based on a signal. In this case, the to-dos signal. And for that also, we need to do a callback basically a factory for each new one, and then existing ones will be uh kind of reused and so

on. So, uh to-dos signal is what we receive there. And then let's just return a new span with to do signal .map to do to do get task. And again double colon All right, so now we should actually see the to do that we have in the database. Yes, there it shows up. And then if I create a new one, I want to for instance also be

able to to to to uh complete a to do. add that, it's immediately there. And also I can reload the page to see that yes, it's also loaded from the database. Okay, let's do the summary then. So what I want to show a text a span saying that these this many tasks are still remaining. So we create a new span. And uh we can actually do it

inline So uh a signal binding here remaining to dos. To dos. And then we going to do plus and then from the to do signal, we can get all the values. So that's a stream of all the to do entities. And then what we do there is that we uh filter it since we only care about those that are not yet completed. So we get a to

do and we going to say not to do {dot} is done. And then we count all of those. And that's our summary span. And let's add that also to the UI. So now we see a summary. It says right now we have two remaining to dos. Let's add another one just to see that it also updates the count here. So uh after completing to dos, let's do

collaboration also. That's always fun. And now it updated the count to three also. And let's add a space there. let's do the thing about completing to-do so that I can actually keep track of what I have to do still. So, what I want to do is that for each to-do here in the list, I want to have a checkbox that I can do to to toggle that

now it's done or now it's not not So, we're basically going to expand this span to be multiple things. So, let's pull this out. This is kind of the task And then instead of just using a task span as the content in this factory, let's do a horizontal layout so we can put multiple things there. So, a new let's put that there. Shouldn't change anything. No. Let's

also then check create a checkbox. So, new check Uh and that's the done box here for instance. And add that also Uh and now we see that Okay, good. We've got two one checkbox on each line. Uh but nothing happens still because it we haven't done any data binding. So, for the done box, let's bind the kind of we read it. It's just to-dos.map to-do colon colon

is done. the right callback is a little bit more complicated here. So, we we receive a new done value. So, a boolean either true or false. And then what we should do What are you complaining about now? Oh. We should use the to-do signal, not the to-dos signal. Uh We're going to update both the UI state so that we actually see things immediately like updating the count

of remaining things and also save that in the database. And for this one convenient way to do it is to say to the signal that I want to update you. And then we receive the current value, and then we should update and return a new value. So, let's do it. to do.set done, and we got done from the closure. And then we're going to return that to

do. So, in this way now, when I click this, it immediately, like you see, it updates the count. It also updates the database, so if I reload now, then it comes out as as checked also from the beginning. But, I'm not yet fully done. I think no, I'm not done with completing the to do here. Because I also want to visually that which of these are completed,

so it's not just a checkbox. So, what I want to do is to do a strike through on on on this span whenever that span is for a completed to do. Uh and here I'm almost going to cheat. I promised 100% Java. Here I will do be using two CSS styling strings, so you can keep keep your hands in front of your eyes if you think that's

scary. task span get the style, and then we want to bind some style, and the style we want to bind is text decoration, And then we're going to dynamically compute a text decoration value. So, actually let's extract this thing here, because I'm going to reuse it. So, this is a done signal. So, this is just a computed signal now that that I can reuse in multiple places,

because I want to also here in my computation, I want to get that, and if it's true, then I want to use line through as the CSS value, and otherwise null, since I don't want have any special text decoration. So, with that change now, we see that this one, that is already done, it gets the line through uh style. And if I check another one, then it

also immediately gets uh checked uh struck through, I mean. All right, so we're done with completing Let's next do collaboration. So, what do we mean by collaboration? I mean that if we would be multiple users, let's arrange them like these, maybe. So, we've got different users. Now, I need to zoom out a little bit. Uh and if one of them checks this checkbox, then obviously the other

one doesn't notice, but if I now refresh there, then it loads it from the database. But, I want to have it so that immediately when one user updates it, then the other one also sees it. The first thing I need to do there is to go to the application configurator put an @Push annotation. So, this tells Vaadin that should also, in addition to the HTTP requests, it

should always also keep a WebSocket open so that it can push out changes to a browser even when there isn't any any request from that browser. And that's only effective after refreshing, so let's do that right away. Next thing we want to do is to actually make it share these values. So, right now, all the sharing basically happens through the database, through this repo, basically. But, what

we would want to do is to share this part of the view state also between users that are on this view. So, the thing we need to do here is first change this into a shared list signal. So, it's almost the same as the regular list signal, but it's optimized for actually concurrent sharing, so it lets you control like conflicts and things like that. One of the

things it does is that it it does defensive copying of of everything so that you don't you can actually work with these as immutable values, but for that we also need to give the the class literal there. And the next step for sharing this is to turn it into a static variable. You shouldn't do this at home. You should of course have like a singleton bean and

as an instance field in there, but I'm I'm doing the simple way around Uh finally, also we shouldn't now the view state again and again and again every time because now it's preserved between between view instances. So uh we also going to say if to-do's {dot} peek {dot} is empty, only in that case we check to see if there's anything So with that small change, now we

should have everything collaborative here. So now if I check this box, then the view state is shared so that this one was also updated immediately. and again, you probably want to have some access control around that and so on, but the cool thing with this being just server-side Java is that you are fully in control about kind of which users UI do you actually use this signal

with and in that way you you have full control over over what's there. again in the same uh representation here, what we have is that we got the regular loop with HTTP requests when the user itself does but when anything else happens, like another user doing something or you have lazy loaded some slow query from the database or you done with some batch job generating some report

or you get a response from an AI agent or whatever it is, just kind of through through regular mechanism update that UI state and then the framework notices that okay, in this case, we should send the updates to the actual UI in the browser through the websocket instead. And this is also something if you have been using Vaadin in the past, then this is now way way

simpler. Previously, you you needed to take care of kind of locking the whole UI and and these kinds of things. Let's continue a little bit. We have some time still. Continue with the application. I also want to add a remove So that I can do uh basically a button so that I can remove to do's here also. So uh in this same factory let's say we want

a new button. And it's a remove button. And what we want to have here is a Vaadin icon. {dot} trash. And the remove button let's add it to the UI and then the alignment is a little bit off and so on. Let's not care about that right now. Let's just do the actual logic. So remove {dot} add click And here we get a click event again. And

what we're doing there is again kind of the same two steps that we had when we updated the data. So we need to remove it from the database and remove view state and then everything else just updated based on that. So we're going to do repo {dot} delete. And we get the latest instance of the mm entity from the to do signal picking there again. And then

we do to do's And now with this, let's just say that we also had make it pretty here. actually collaboration is done. Uh so we also had of course we want to make it pretty, but we are Java developers and we're running out of time. So let's not make it pretty. Let's just remove that one and yeah, that also works. how we build reactive applications with just

Java and nothing else. I've been doing things very very manually to kind of prove some kind of point and show whether it's easy enough. if you do like I actually said, then just mcp.vaadin.com and from that you have instructions how you tell Claude code and all the other bots how they can use Vaadin in a much better way than than what I'm doing myself. And with that,

I think do we have any questions? I see lots of questions in the app. Cool. So let's have them popularity order. So why is unclean code being showed? There's no separation between UI and design. Shouldn't the Java developers learn learn proper coding practices? Yes, you're absolutely right. I'm taking a little bit of shortcuts here to kind of keep things simple and so on. You should of course

use kind of separation of concerns. So you should have your business logic in some service classes With great power comes great responsibility. I abused it for other reasons, but you shouldn't. can we use Vaadin with Quarkus? Yes, you can. just Google for it and you will find it. We kind of have Spring as the default because that's what most people are using and we don't want to

confuse people who are new to Vaadin who don't know what's Spring, what's Quarkus, what's anything. We want to have just sim- simple choices to get started, but there's definitely Quarkus support there also. What are the technical limits for the number of users on the intranet internet or intranet? Uh the main bottleneck is usually memory because with this kind of architecture for each user there's kind of an

instance of the text field, an instance of the button. All of those are actually Java objects on the heap stored in the servlet session. Typically, we're talking about between 100 kilobytes and 1 megabyte of memory heap memory per concurrent user. Now, you can get like from for instance, Amazon EC2 you can get a machine with like 100 gigabytes of memory for less money than than what your

sal- our salary is. So, uh with that you can have tens of thousands of users without too many problems as long as you kind of avoid pitfalls like loading all memory into all your database into memory for each user and Uh would you consider using pre-coded Git commits to show more? I would consider, but not today. Is it compatible with GraalVM? Yes, it Uh if you go

to the Vaadin GitHub, you can also find a GraalVM something native something starter. So, uh there you have a kind of starting point for that. You can also use it with uh Spring Boot uh GraalVM support for native builds. Uh what dat- database do you use and how is it wired to the application? Uh I used H2, just a basic in-memory database. It was wired using Spring

Data JPA, so I didn't even configure anything. It just magically worked from uh start.spring.io. Uh documentation to the new binding style or how to migrate from the old style. So, okay, this is an existing it's a little bit still working progress to update the documentation, but we're getting there. Oh, more questions. This is good. Uh is it possible to integrate existing JavaScript TypeScript libraries with Vaadin? Yes,

it is. So, I mean, now the whole point was to show 100% Java. So, I completely stayed away from that. But, yeah, if you have anything, especially if it's a web component or a React component, then it's just a couple of lines of JavaScript to do the client-side integration, and then you define a Java class for the component, and then in that way you you can still

keep using it from Java only once you have done that integration. can you show the no-code functionality? We're already out of time, and the no-code functionality is something that we realized was maybe not a good idea because now cloud code functionality is probably better. Uh which version of Vaadin are you using? I'm using the very latest one that I got from start.spring.io. I guess that's Vaadin 25.1.3

unless they released a new one yesterday. And now I guess we're officially out of time. So, thank you very much.

From event

JCON EUROPE

20 Apr 2026 – 23 Apr 2026

All event videos
Back to Watch