You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/building-apps/ai/quickstart-guide.adoc
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ section-nav: badge-flow
8
8
---
9
9
10
10
11
-
= Quick Start-Guide: Add an AI Chat Bot to a Vaadin + Spring Boot Application [badge-flow]#Flow#
11
+
= Quick Start-Guide: Add an AI Chat Bot to a Vaadin + Spring Boot Application [badge-flow]#Flow#
12
12
13
13
This guide shows how to connect a Large Language Model (LLM) into a Vaadin application using Spring AI and Spring Boot. You'll build a minimal chat UI with Vaadin provided components **MessageList** and **MessageInput**, stream responses token-by-token, and keep a conversational tone in the dialog with the AI.
Copy file name to clipboardExpand all lines: articles/building-apps/architecture/packages.adoc
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ When you package by layer, you put all classes that belong to the same architect
36
36
37
37
This paradigm groups classes with similar responsibilities together. This leads to a *clear separation of concerns*. A class with too many responsibilities doesn't fit into any of the packages. This gives a natural inclination to split the class into smaller parts.
38
38
39
-
One drawback of this approach is that most classes need to be public. This means classes across layers can directly access each other, potentially violating architectural boundaries. However, the architectural style often dictates a specific dependency flow, such as `ui` -> `service` -> `domain`. You'd have to use something like https://www.archunit.org/[ArchUnit] to ensure the dependencies between classes are according to your architectural style, or put each layer into a <<project-structure/multi-module#,separate JAR file>>. Public visibility also makes it more difficult to separate <<api-spi#,APIs and SPIs>> from internal classes.
39
+
One drawback of this approach is that most classes need to be public. This means classes across layers can directly access each other, potentially violating architectural boundaries. However, the architectural style often dictates a specific dependency flow, such as `ui` -> `service` -> `domain`. You'd have to use something like https://www.archunit.org/[ArchUnit] to ensure the dependencies between classes are according to your architectural style, or put each layer into a <<project-structure/multi-module#,separate JAR file>>. Public visibility also makes it more difficult to separate <<api-spi#,APIs and SPIs>> from internal classes.
40
40
41
41
Another drawback is that feature cohesion suffers. In the example above, all Customer-related code is spread across multiple packages, making it harder to understand the complete feature. This also has an impact on testing: you can't easily mock or isolate a complete feature. You often end up testing dependencies across multiple layers rather than testing a cohesive feature in isolation.
42
42
@@ -66,7 +66,7 @@ When you package by feature, you put all classes that implement the same feature
66
66
├── com.example.application.util
67
67
│ └── + StringUtils
68
68
└── com.example.application
69
-
└── + Application
69
+
└── + Application
70
70
----
71
71
72
72
Compared to package by layer, this leads to higher feature cohesion and modularity. The classes that implement the same feature or functionality are grouped together. If you need to make a change to a feature, you only need to touch one package. Your tests can focus on one feature and test it in isolation. And if you need to split your application into modules or microservices, you can do that.
@@ -98,7 +98,7 @@ com.example.application
98
98
├── Application
99
99
├── CustomerDTO
100
100
├── CustomerRestClient
101
-
└── CustomerView
101
+
└── CustomerView
102
102
----
103
103
104
104
=== Layers Inside Features
@@ -117,7 +117,7 @@ Features can grow quite big, which introduces the risk of the code inside the fe
117
117
│ ├── - CustomerForm
118
118
│ └── - CustomerView
119
119
└── com.example.application
120
-
└── + Application
120
+
└── + Application
121
121
----
122
122
123
123
Now, the UI-related classes is in a separate `ui` package. The classes can have package visibility since they are only called by the web browser, not by other feature packages. They call the API of the root feature package, which has public visibility.
@@ -136,7 +136,7 @@ If you use JPA inheritance and end up moving some entities into a separate appli
136
136
137
137
== Final Thoughts
138
138
139
-
Package structure plays a big role in the readability and maintainability of your application. You know your package structure is right when you find classes where you expected them to be, and have no problems deciding where to put new classes.
139
+
Package structure plays a big role in the readability and maintainability of your application. You know your package structure is right when you find classes where you expected them to be, and have no problems deciding where to put new classes.
140
140
141
141
When you package by layer, classes that belong to the same architectural layer (like "UI", "Service", "Domain") end up in the same package. When you package by feature, classes that belong to the same feature (like "Customer Onboarding", "Dashboard", "Order Processing") end up in the same package.
Copy file name to clipboardExpand all lines: articles/building-apps/architecture/project-structure/index.adoc
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ Whenever you build a web application with Spring Boot, you have to decide whethe
23
23
24
24
=== JAR File Packaging
25
25
26
-
Packaging a Vaadin application as a JAR file is the recommended choice. It contains everything needed to run an application, except for the Java Virtual Machine. The web server -- like https://tomcat.apache.org/[Tomcat], https://jetty.org/index.html[Jetty], or https://undertow.io/[Undertow] -- is embedded. Therefore, you can start an application by running this command:
26
+
Packaging a Vaadin application as a JAR file is the recommended choice. It contains everything needed to run an application, except for the Java Virtual Machine. The web server -- like https://tomcat.apache.org/[Tomcat], https://jetty.org/index.html[Jetty], or https://undertow.io/[Undertow] -- is embedded. Therefore, you can start an application by running this command:
27
27
28
28
[source,terminal]
29
29
----
@@ -37,7 +37,7 @@ This makes the deployment simple and with a few options. To deploy an applicatio
37
37
38
38
// TODO Mention GraalVM
39
39
40
-
Another advantage to packaging an application as a JAR file is that it'll run inside its own Java Virtual Machine, and therefore its own operating system process. This allow you to configure and restart it without affecting other applications. Plus, if the application is compromised or crashes, other applications running on the same physical server are better protected since they run in their own processes. This feature, though, comes with a cost.
40
+
Another advantage to packaging an application as a JAR file is that it'll run inside its own Java Virtual Machine, and therefore its own operating system process. This allow you to configure and restart it without affecting other applications. Plus, if the application is compromised or crashes, other applications running on the same physical server are better protected since they run in their own processes. This feature, though, comes with a cost.
41
41
42
42
Since every application runs an embedded web server, they consume more memory and disk space than a traditional Java web application. However, since memory and disk space are quite cheap, the cost is usually well worth the benefits.
43
43
@@ -53,6 +53,6 @@ You should only consider WAR packaging if you already have a web application ser
53
53
54
54
== Multi vs. Single-Module
55
55
56
-
You can build your Vaadin applications as single-module Maven projects, or as multi-module Maven projects. Both options have advantages and disadvantages. You should familiarize yourself with them before making a decision.
56
+
You can build your Vaadin applications as single-module Maven projects, or as multi-module Maven projects. Both options have advantages and disadvantages. You should familiarize yourself with them before making a decision.
57
57
58
58
You can find more information on the <<single-module#,Single-Module Projects>>, and the <<multi-module#,Multi-Module Projects>> documentation pages.
A multi-module project consists of multiple directories, each with its own POM file and source directory. The modules can depend on each other; Maven builds them in the correct order.
14
+
A multi-module project consists of multiple directories, each with its own POM file and source directory. The modules can depend on each other; Maven builds them in the correct order.
15
15
16
16
[IMPORTANT]
17
17
Even though the project consists of many modules, it is still a single application and is packaged into a single JAR file or WAR file.
@@ -92,7 +92,7 @@ To be able to use basic Spring features such as dependency injection, all module
92
92
<dependency>
93
93
<groupId>org.springframework</groupId>
94
94
<artifactId>spring-context</artifactId>
95
-
</dependency>
95
+
</dependency>
96
96
</dependencies>
97
97
----
98
98
@@ -148,7 +148,7 @@ Below is how a fully configured POM file for an empty multi-module Vaadin applic
148
148
<dependency>
149
149
<groupId>org.springframework</groupId>
150
150
<artifactId>spring-context</artifactId>
151
-
</dependency>
151
+
</dependency>
152
152
</dependencies>
153
153
154
154
<modules>
@@ -364,11 +364,11 @@ You'll need to add the Vaadin Maven plugin somewhere in your multi-module projec
364
364
</plugins>
365
365
</build>
366
366
</profile>
367
-
</profiles>
367
+
</profiles>
368
368
</project>
369
369
----
370
370
371
-
Store frontend sources, such as CSS files and JavaScript, in the `src/main/frontend` directory of the UI module. Store other resources, such as images, in `src/main/resources/META-INF/resources`.
371
+
Store frontend sources, such as CSS files and JavaScript, in the `src/main/frontend` directory of the UI module. Store other resources, such as images, in `src/main/resources/META-INF/resources`.
372
372
373
373
374
374
=== Multiple UI Modules
@@ -420,7 +420,7 @@ The application module is an ordinary Maven module that contains at least the `A
420
420
<groupId>${project.groupId}</groupId>
421
421
<artifactId>util</artifactId>
422
422
<version>${project.version}</version>
423
-
</dependency>
423
+
</dependency>
424
424
</dependencies>
425
425
426
426
<build>
@@ -472,7 +472,7 @@ If you're using package by feature, the POM-file would also include the Vaadin M
472
472
<groupId>${project.groupId}</groupId>
473
473
<artifactId>shopping-cart</artifactId>
474
474
<version>${project.version}</version>
475
-
</dependency>
475
+
</dependency>
476
476
</dependencies>
477
477
478
478
<build>
@@ -492,7 +492,7 @@ If you're using package by feature, the POM-file would also include the Vaadin M
492
492
</goals>
493
493
</execution>
494
494
</executions>
495
-
</plugin>
495
+
</plugin>
496
496
</plugins>
497
497
</build>
498
498
@@ -529,7 +529,7 @@ If you're using package by feature, the POM-file would also include the Vaadin M
Copy file name to clipboardExpand all lines: articles/building-apps/architecture/project-structure/single-module.adoc
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -123,11 +123,11 @@ Next, to build your project, you'll need to add two more Maven plugins:
123
123
124
124
The `spring-boot-maven-plugin` does plenty, but for now think of it as the plugin that packages a project into a single, executable JAR file. For more information about this plugin, see the https://docs.spring.io/spring-boot/maven-plugin[Spring Boot documentation].
125
125
126
-
The `vaadin-maven-plugin` also does plenty. The `prepare-frontend` goal checks that you have sufficiently recent versions of the `node` and `npm` tools. It installs them if they're missing. It also reviews all of the resources used by the application, generates some missing source files, and moves them into the correct locations.
126
+
The `vaadin-maven-plugin` also does plenty. The `prepare-frontend` goal checks that you have sufficiently recent versions of the `node` and `npm` tools. It installs them if they're missing. It also reviews all of the resources used by the application, generates some missing source files, and moves them into the correct locations.
127
127
128
128
Depending on how much the plugin has to do, the first execution of this goal may take some time. However, later executions are often fast. Therefore, include this goal in every build. For more information, see <<{articles}/flow/production/production-build#,Production Build>> and <<{articles}/flow/configuration/maven#,Maven Configuration Properties>>.
129
129
130
-
After you've executed `prepare-frontend`, you're ready to run your application in <<{articles}/flow/configuration/development-mode#,development mode>>.
130
+
After you've executed `prepare-frontend`, you're ready to run your application in <<{articles}/flow/configuration/development-mode#,development mode>>.
Copy file name to clipboardExpand all lines: articles/building-apps/business-logic/add-service.adoc
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
title: Add a Service
3
-
page-title: How to add an application service to a Vaadin application
3
+
page-title: How to add an application service to a Vaadin application
4
4
description: Learn how to add an application service to a Vaadin application.
5
5
meta-description: Learn how to design and implement application services in Vaadin. This guide covers best practices, security, naming conventions, and calling services from Vaadin views.
6
6
order: 5
@@ -14,13 +14,13 @@ In a Vaadin application, the _application layer_ contains the business, the data
14
14
15
15
image::images/application-layer-api.png[A diagram of the UI layer calling the application layer through an API]
16
16
17
-
This API is implemented by _application services_. In practice, application services are *Spring beans* that you can call from Vaadin views.
17
+
This API is implemented by _application services_. In practice, application services are *Spring beans* that you can call from Vaadin views.
18
18
19
19
20
20
== Design Guidelines
21
21
22
22
You can design application services according to your preferred architectural style, but following these best practices helps prevent common issues:
23
-
23
+
24
24
* The application services should have *high cohesion*. This means that all the methods in your service should relate to the same thing.
25
25
* The application services should be *stateless*.
26
26
* Application services should *initiate and complete <<../forms-data/consistency/transactions#,database transactions>>* before returning results.
@@ -43,8 +43,8 @@ public class OrderCreationService {
43
43
private final OrderRepository orderRepository;
44
44
private final ApplicationEventPublisher eventPublisher;
45
45
46
-
OrderCreationService(Validator validator,
47
-
OrderRepository orderRepository,
46
+
OrderCreationService(Validator validator,
47
+
OrderRepository orderRepository,
48
48
ApplicationEventPublisher eventPublisher) {
49
49
this.validator = validator;
50
50
this.orderRepository = orderRepository;
@@ -58,7 +58,7 @@ public class OrderCreationService {
58
58
throw new ConstraintViolationException(validationErrors);
59
59
}
60
60
var order = orderRepository.saveAndFlush(createOrderFromForm(orderForm));
61
-
eventPublisher.publishEvent(new OrderCreatedEvent(order)); // Notify other
61
+
eventPublisher.publishEvent(new OrderCreatedEvent(order)); // Notify other
62
62
// components of
63
63
// the new order
64
64
return order.orderId();
@@ -247,7 +247,7 @@ public class CustomerOnboardingView extends Main {
Copy file name to clipboardExpand all lines: articles/building-apps/business-logic/background-jobs/index.adoc
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ order: 35
8
8
---
9
9
10
10
11
-
= Background Jobs [badge-deep-dive]#Deep Dive#
11
+
= Background Jobs [badge-deep-dive]#Deep Dive#
12
12
13
13
Many business applications need to perform in background threads. These tasks might be long-running operations triggered by the user, or scheduled jobs that run at specific times or intervals.
14
14
@@ -42,7 +42,7 @@ To use virtual threads, you can enable them by setting the `spring.threads.virtu
42
42
43
43
You can interact with the `TaskExecutor` either directly, or declaratively through annotations.
44
44
45
-
When interacting with it directly, you would inject an instance of `TaskExecutor` into your code, and submit work to it.
45
+
When interacting with it directly, you would inject an instance of `TaskExecutor` into your code, and submit work to it.
46
46
47
47
Here is an example of a class that uses the `TaskExecutor`:
48
48
@@ -70,7 +70,7 @@ public class MyWorker {
70
70
[IMPORTANT]
71
71
When you inject the `TaskExecutor`, you have to name the parameter `taskExecutor`. The application context may contain more than one bean that implements the `TaskExecutor` interface. If the parameter name doesn't match the name of the bean, Spring doesn't know which instance to inject.
72
72
73
-
If you want to use annotations, you have to enable them first. Do this by adding the `@EnableAsync` annotation to your main application class, or any other `@Configuration` class.
73
+
If you want to use annotations, you have to enable them first. Do this by adding the `@EnableAsync` annotation to your main application class, or any other `@Configuration` class.
74
74
75
75
Here's an example that adds the annotation to the main application class:
Copy file name to clipboardExpand all lines: articles/building-apps/business-logic/background-jobs/interaction/callbacks.adoc
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,14 +1,14 @@
1
1
---
2
2
title: Callbacks
3
-
page-title: How to use callbacks to interact with your UI | Vaadin
3
+
page-title: How to use callbacks to interact with your UI | Vaadin
4
4
description: How to use callbacks to interact with the user interface.
5
5
meta-description: When using a Flow user interface, the simplest way of allowing background jobs to interact with it is through callbacks. Learn more here.
6
6
order: 10
7
7
section-nav: badge-flow
8
8
---
9
9
10
10
11
-
= Callbacks [badge-flow]#Flow#
11
+
= Callbacks [badge-flow]#Flow#
12
12
13
13
When using a Flow user interface, the simplest way of allowing background jobs to interact with it is through callbacks. You can use `Consumer`, `Runnable`, and `Supplier` as callback interfaces, depending on how you want to interact with the background job.
14
14
@@ -41,7 +41,7 @@ A background job that returns a string or an exception could be implemented like
41
41
[source,java]
42
42
----
43
43
@Async
44
-
public void startBackgroundJob(Consumer<String> onComplete,
44
+
public void startBackgroundJob(Consumer<String> onComplete,
45
45
Consumer<Exception> onError) {
46
46
try {
47
47
var result = doSomethingThatTakesALongTime();
@@ -60,8 +60,8 @@ When the background job is also reporting its progress, for instance as a percen
60
60
[source,java]
61
61
----
62
62
@Async
63
-
public void startBackgroundJob(Consumer<String> onComplete,
64
-
Consumer<Double> onProgress,
63
+
public void startBackgroundJob(Consumer<String> onComplete,
64
+
Consumer<Double> onProgress,
65
65
Consumer<Exception> onError) {
66
66
try {
67
67
onProgress.apply(0.0);
@@ -93,8 +93,8 @@ A job can be cancelled. To do that, it would look like this:
93
93
[source,java]
94
94
----
95
95
@Async
96
-
public void startBackgroundJob(Consumer<String> onComplete,
97
-
Consumer<Double> onProgress,
96
+
public void startBackgroundJob(Consumer<String> onComplete,
97
+
Consumer<Double> onProgress,
98
98
Consumer<Exception> onError,
99
99
Supplier<Boolean> isCancelled) {
100
100
try {
@@ -150,7 +150,7 @@ Next, implement the service method like this:
150
150
151
151
[source,java]
152
152
----
153
-
public CancellableJob startBackgroundJob(Consumer<String> onComplete,
153
+
public CancellableJob startBackgroundJob(Consumer<String> onComplete,
0 commit comments