{"id":693,"date":"2026-06-16T23:30:37","date_gmt":"2026-06-16T22:30:37","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=693"},"modified":"2026-07-07T23:31:20","modified_gmt":"2026-07-07T22:31:20","slug":"vaadin-flow-25-moderne-full-stack-webentwicklung-rein-in-java","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=693","title":{"rendered":"Vaadin Flow 25 \u2013 Moderne Full-Stack-Webentwicklung rein in Java"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Stell dir vor, du k\u00f6nntest eine moderne Single-Page-Application schreiben, ohne eine Zeile JavaScript, HTML oder CSS \u2014 nur mit Java. Genau das erm\u00f6glicht Vaadin Flow: Serverseitige UI-Komponenten, die im Browser als Web Components gerendert werden. Vaadin 25 bringt diesen Ansatz auf den neuesten Stand mit Spring-Boot-Integration, virtueller Scroll-Liste und fl\u00fcssigem Daten-Binding.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Artikel f\u00fchrt dich durch die Erstellung einer vollst\u00e4ndigen Todo-App mit Vaadin Flow 25 und Spring Boot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Was ist Vaadin Flow?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vaadin Flow ist ein serverseitiges UI-Framework: Du schreibst Java-Klassen, die UI-Komponenten wie Buttons, Textfelder und Grids repr\u00e4sentieren. Die Kommunikation zwischen Server und Browser l\u00e4uft automatisch \u00fcber WebSockets. Du interagierst nie direkt mit dem DOM \u2014 Vaadin \u00fcbernimmt das Rendering und Event-Handling vollst\u00e4ndig.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die aktuelle Version&nbsp;<strong>25.2.1<\/strong>&nbsp;(Juni 2026) l\u00e4uft mit Spring Boot 4.0+ und Java 21+.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Projekt-Setup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Maven \u2014 Spring Boot + Vaadin BOM:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">parent<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.boot<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-boot-starter-parent<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>4.0.4<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">parent<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">properties<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">java.version<\/span>&gt;<\/span>21<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">java.version<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">vaadin.version<\/span>&gt;<\/span>25.2.1<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">vaadin.version<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">properties<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencyManagement<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>com.vaadin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>vaadin-bom<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>${vaadin.version}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">type<\/span>&gt;<\/span>pom<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">type<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>import<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependencyManagement<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>com.vaadin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>vaadin-spring-boot-starter<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Das Datenmodell und der Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Zun\u00e4chst das Domain-Objekt und eine In-Memory-Service-Schicht:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.util.concurrent.CopyOnWriteArrayList;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Todo<\/span> <\/span>{\n    private Long id;\n    private <span class=\"hljs-built_in\">String<\/span> task;\n    private boolean done;\n\n    public Todo() {}\n\n    public Todo(Long id, <span class=\"hljs-built_in\">String<\/span> task) {\n        <span class=\"hljs-keyword\">this<\/span>.id = id;\n        <span class=\"hljs-keyword\">this<\/span>.task = task;\n    }\n\n    public Long getId() { <span class=\"hljs-keyword\">return<\/span> id; }\n    public <span class=\"hljs-keyword\">void<\/span> setId(Long id) { <span class=\"hljs-keyword\">this<\/span>.id = id; }\n    public <span class=\"hljs-built_in\">String<\/span> getTask() { <span class=\"hljs-keyword\">return<\/span> task; }\n    public <span class=\"hljs-keyword\">void<\/span> setTask(<span class=\"hljs-built_in\">String<\/span> task) { <span class=\"hljs-keyword\">this<\/span>.task = task; }\n    public boolean isDone() { <span class=\"hljs-keyword\">return<\/span> done; }\n    public <span class=\"hljs-keyword\">void<\/span> setDone(boolean done) { <span class=\"hljs-keyword\">this<\/span>.done = done; }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">import org.springframework.stereotype.Service;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicLong;\n\n@Service\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TodoService<\/span> <\/span>{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">List<\/span>&lt;Todo&gt; todos = <span class=\"hljs-keyword\">new<\/span> CopyOnWriteArrayList&lt;&gt;();\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> AtomicLong counter = <span class=\"hljs-keyword\">new<\/span> AtomicLong(<span class=\"hljs-number\">1<\/span>);\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">List<\/span>&lt;Todo&gt; findAll() {\n        <span class=\"hljs-keyword\">return<\/span> Collections.unmodifiableList(todos);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> Todo add(String task) {\n        Todo todo = <span class=\"hljs-keyword\">new<\/span> Todo(counter.getAndIncrement(), task);\n        todos.add(todo);\n        <span class=\"hljs-keyword\">return<\/span> todo;\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> void remove(Todo todo) {\n        todos.remove(todo);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> void toggle(Todo todo) {\n        todo.setDone(!todo.isDone());\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Die Haupt-View mit @Route<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vaadin Views werden mit&nbsp;<code>@Route<\/code>&nbsp;annotiert. Das folgende&nbsp;<code>TodoView<\/code>&nbsp;baut eine komplette Benutzeroberfl\u00e4che aus Java-Komponenten zusammen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.Key;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.button.Button;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.button.ButtonVariant;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.grid.Grid;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.icon.VaadinIcon;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.orderedlayout.HorizontalLayout;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.orderedlayout.VerticalLayout;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.textfield.TextField;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.router.PageTitle;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.router.Route;\n\n@Route(<span class=\"hljs-string\">\"\"<\/span>)\n@PageTitle(<span class=\"hljs-string\">\"Todo App\"<\/span>)\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TodoView<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">VerticalLayout<\/span> <\/span>{\n\n    private final TodoService service;\n    private final Grid&lt;Todo&gt; grid = <span class=\"hljs-keyword\">new<\/span> Grid&lt;&gt;(Todo.class, <span class=\"hljs-literal\">false<\/span>);\n    private final TextField taskField = <span class=\"hljs-keyword\">new<\/span> TextField();\n\n    public TodoView(TodoService service) {\n        <span class=\"hljs-keyword\">this<\/span>.service = service;\n\n        taskField.setPlaceholder(<span class=\"hljs-string\">\"Neue Aufgabe eingeben...\"<\/span>);\n        taskField.setClearButtonVisible(<span class=\"hljs-literal\">true<\/span>);\n\n        Button addButton = <span class=\"hljs-keyword\">new<\/span> Button(<span class=\"hljs-string\">\"Hinzuf\u00fcgen\"<\/span>, VaadinIcon.PLUS.create());\n        addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);\n        addButton.addClickListener(e -&gt; addTodo());\n        addButton.addClickShortcut(Key.ENTER);\n\n        grid.addColumn(Todo::getId).setHeader(<span class=\"hljs-string\">\"ID\"<\/span>).setWidth(<span class=\"hljs-string\">\"80px\"<\/span>);\n        grid.addColumn(Todo::getTask).setHeader(<span class=\"hljs-string\">\"Aufgabe\"<\/span>).setAutoWidth(<span class=\"hljs-literal\">true<\/span>);\n\n        grid.addComponentColumn(todo -&gt; {\n            Button doneBtn = <span class=\"hljs-keyword\">new<\/span> Button(\n                todo.isDone() ? <span class=\"hljs-string\">\"\u2705\"<\/span> : <span class=\"hljs-string\">\"\u2b1c\"<\/span>,\n                e -&gt; { service.toggle(todo); refreshGrid(); }\n            );\n            <span class=\"hljs-keyword\">return<\/span> doneBtn;\n        }).setHeader(<span class=\"hljs-string\">\"Status\"<\/span>).setWidth(<span class=\"hljs-string\">\"80px\"<\/span>);\n\n        grid.addComponentColumn(todo -&gt; {\n            Button deleteBtn = <span class=\"hljs-keyword\">new<\/span> Button(<span class=\"hljs-string\">\"L\u00f6schen\"<\/span>, VaadinIcon.TRASH.create());\n            deleteBtn.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_SMALL);\n            deleteBtn.addClickListener(e -&gt; {\n                service.remove(todo);\n                refreshGrid();\n            });\n            <span class=\"hljs-keyword\">return<\/span> deleteBtn;\n        }).setWidth(<span class=\"hljs-string\">\"120px\"<\/span>);\n\n        HorizontalLayout toolbar = <span class=\"hljs-keyword\">new<\/span> HorizontalLayout(taskField, addButton);\n        toolbar.setDefaultVerticalComponentAlignment(Alignment.BASELINE);\n        toolbar.setWidthFull();\n\n        add(toolbar, grid);\n        refreshGrid();\n    }\n\n    private <span class=\"hljs-keyword\">void<\/span> addTodo() {\n        <span class=\"hljs-built_in\">String<\/span> task = taskField.getValue().trim();\n        <span class=\"hljs-keyword\">if<\/span> (!task.isEmpty()) {\n            service.add(task);\n            taskField.clear();\n            refreshGrid();\n        }\n    }\n\n    private <span class=\"hljs-keyword\">void<\/span> refreshGrid() {\n        grid.setItems(service.findAll());\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Routing: Mehrseitige Apps mit @Route<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vaadin Flow bietet ein volles Routing-System mit Parameter-Support und verschachtelten Layouts:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">&lt;em&gt;<span class=\"hljs-comment\">\/\/ Haupt-Layout mit Navigationsleiste&lt;\/em&gt;<\/span>\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MainLayout<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">AppLayout<\/span> <span class=\"hljs-title\">implements<\/span> <span class=\"hljs-title\">RouterLayout<\/span> <\/span>{\n    public MainLayout() {\n        DrawerToggle toggle = <span class=\"hljs-keyword\">new<\/span> DrawerToggle();\n        H1 title = <span class=\"hljs-keyword\">new<\/span> H1(<span class=\"hljs-string\">\"Meine App\"<\/span>);\n        addToNavbar(toggle, title);\n\n        VerticalLayout drawer = <span class=\"hljs-keyword\">new<\/span> VerticalLayout(\n            <span class=\"hljs-keyword\">new<\/span> RouterLink(<span class=\"hljs-string\">\"Todos\"<\/span>, TodoView.class),\n            <span class=\"hljs-keyword\">new<\/span> RouterLink(<span class=\"hljs-string\">\"Statistik\"<\/span>, StatsView.class)\n        );\n        addToDrawer(drawer);\n    }\n}\n\n&lt;em&gt;<span class=\"hljs-comment\">\/\/ View mit Pfad-Parameter&lt;\/em&gt;<\/span>\n@Route(value = <span class=\"hljs-string\">\"todo\/:todoId\"<\/span>, layout = MainLayout.class)\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TodoDetailView<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">VerticalLayout<\/span>\n        <span class=\"hljs-title\">implements<\/span> <span class=\"hljs-title\">BeforeEnterObserver<\/span> <\/span>{\n    @Override\n    public <span class=\"hljs-keyword\">void<\/span> beforeEnter(BeforeEnterEvent event) {\n        <span class=\"hljs-built_in\">String<\/span> todoId = event.getRouteParameters().get(<span class=\"hljs-string\">\"todoId\"<\/span>)\n            .orElse(<span class=\"hljs-string\">\"unbekannt\"<\/span>);\n        add(<span class=\"hljs-keyword\">new<\/span> H2(<span class=\"hljs-string\">\"Todo #\"<\/span> + todoId));\n    }\n}\n\n&lt;em&gt;<span class=\"hljs-comment\">\/\/ Programmgesteuerte Navigation&lt;\/em&gt;<\/span>\ngetUI().ifPresent(ui -&gt; ui.navigate(<span class=\"hljs-string\">\"todo\/\"<\/span> + someId));\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Formular-Validierung mit dem Binder<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vaadin&#8217;s&nbsp;<code>Binder&lt;T&gt;<\/code>-Klasse erm\u00f6glicht typsichere Zwei-Wege-Datenbindung zwischen UI-Komponenten und Beans:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.data.binder.Binder;\n<span class=\"hljs-keyword\">import<\/span> com.vaadin.flow.component.checkbox.Checkbox;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TodoEditor<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">VerticalLayout<\/span> <\/span>{\n    private final Binder&lt;Todo&gt; binder = <span class=\"hljs-keyword\">new<\/span> Binder&lt;&gt;(Todo.class);\n    private final TextField task = <span class=\"hljs-keyword\">new<\/span> TextField(<span class=\"hljs-string\">\"Aufgabe\"<\/span>);\n    private final Checkbox done = <span class=\"hljs-keyword\">new<\/span> Checkbox(<span class=\"hljs-string\">\"Erledigt\"<\/span>);\n    private Todo currentTodo;\n\n    public TodoEditor() {\n        binder.forField(task)\n            .asRequired(<span class=\"hljs-string\">\"Aufgabe darf nicht leer sein\"<\/span>)\n            .withValidator(t -&gt; t.length() &gt;= <span class=\"hljs-number\">3<\/span>,\n                <span class=\"hljs-string\">\"Mindestens 3 Zeichen erforderlich\"<\/span>)\n            .bind(<span class=\"hljs-string\">\"task\"<\/span>);\n\n        binder.forField(done).bind(<span class=\"hljs-string\">\"done\"<\/span>);\n\n        Button save = <span class=\"hljs-keyword\">new<\/span> Button(<span class=\"hljs-string\">\"Speichern\"<\/span>, e -&gt; {\n            <span class=\"hljs-keyword\">if<\/span> (binder.writeBeanIfValid(currentTodo)) {\n                Notification.show(<span class=\"hljs-string\">\"Gespeichert!\"<\/span>);\n            }\n        });\n\n        add(task, done, save);\n    }\n\n    public <span class=\"hljs-keyword\">void<\/span> edit(Todo todo) {\n        <span class=\"hljs-keyword\">this<\/span>.currentTodo = todo;\n        binder.readBean(todo);\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vaadin Flow ist kein Framework f\u00fcr jede Anwendung \u2014 aber f\u00fcr datenintensive Business-Apps mit komplexen CRUD-Formularen ist es unschlagbar produktiv. Der Verzicht auf eine separate Frontend-Codebase bedeutet weniger Context-Switching, weniger Schnittstellen und schnellere Entwicklung.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit Vaadin 25, Spring Boot 4.0 und der nahtlosen Binder-API schreibst du Full-Stack-Apps in reinem Java \u2014 und der Browser raunzt nie, weil kein JavaScript fehlt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stell dir vor, du k\u00f6nntest eine moderne Single-Page-Application schreiben, ohne eine Zeile JavaScript, HTML oder CSS \u2014 nur mit Java. Genau das erm\u00f6glicht Vaadin Flow: Serverseitige UI-Komponenten, die im Browser als Web Components gerendert werden. Vaadin 25 bringt diesen Ansatz auf den neuesten Stand mit Spring-Boot-Integration, virtueller Scroll-Liste und fl\u00fcssigem Daten-Binding. Dieser Artikel f\u00fchrt dich [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-693","post","type-post","status-publish","format-standard","hentry","category-spring"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/693","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=693"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/693\/revisions"}],"predecessor-version":[{"id":694,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/693\/revisions\/694"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}