Docs

Documentation versions (currently viewingVaadin 24)

Add a Service

Learn how to add an application service to a Vaadin application.

In a Vaadin application, the application layer contains the business, the data, and any integrations to external systems. The application layer exposes an API that the presentation layer (i.e., the views) can call:

A diagram of the presentation layer calling the application layer through an API

This API is implemented by application services. In practice, application services are Spring beans that you can call from Vaadin Flow and Hilla views.

Design Guidelines

You can design application services according to your preferred architectural style, but following these best practices helps prevent common issues:

  • The application services should be stateless.

  • Application services should initiate and complete database transactions before returning results.

  • The application services should be secure.

  • Views should invoke application services, but application services should not have dependencies on views.

Note
Application services can use Vaadin’s non-UI-related utilities and interfaces, but should not be tightly coupled to UI components.

An application service could look like this:

@Service 1
@PreAuthorize("isAuthenticated()") 2
public class OrderCreationService {

    private final Validator validator;
    private final OrderRepository orderRepository;
    private final ApplicationEventPublisher eventPublisher;

    OrderCreationService(Validator validator,
            OrderRepository orderRepository,
            ApplicationEventPublisher eventPublisher) {
        this.validator = validator;
        this.orderRepository = orderRepository;
        this.eventPublisher = eventPublisher;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW) 3
    public OrderId createOrder(OrderForm orderForm) {
        var validationErrors = validator.validate(orderForm);
        if (!validationErrors.isEmpty()) {
            throw new ConstraintViolationException(validationErrors);
        }
        var order = orderRepository.saveAndFlush(createOrderFromForm(orderForm));
        eventPublisher.publishEvent(new OrderCreatedEvent(order)); // Notify other
                                                                   // components of
                                                                   // the new order
        return order.orderId();
    }

    private Order createOrderFromForm(OrderForm orderForm) {
        // ...
    }
}
  1. Makes the service into a Spring bean.

  2. Protects the service from unauthorized access. See Protect Services for details.

  3. Runs the method inside a database transaction.

If you want to read more about application service design the Vaadin Way, see the Application Services Deep Dive.

Service Naming

Since services form the API of your application, choosing clear and meaningful names is essential. A good service name should be easy to understand and locate in the code.

Vaadin does not enforce a specific naming convention for application services. While the Service suffix is common, it is optional. If you need inspiration, consider these guidelines:

  • CRUD services: Use the entity name (e.g., CustomerService, OrderService, ProductService)

  • Use-case-specific services: Name them according to their function (e.g., CustomerCreationService, SalaryPaymentService)

  • Verb-based names: If noun-based names feel awkward, use verbs (e.g., CreatingCustomersService, PayingSalariesService)

Package Naming

For Java packages containing services, the recommended naming convention is [feature].service, where [feature] represents the full-stack feature the service belongs to.

For example, services related to "customer relationship management" would be placed in: com.example.application.crm.service

This structure keeps services well-organized, easy to find, and clearly associated with their purpose.

Calling from Views

You can call an application service both from Flow and Hilla. When calling an application service from a Hilla view, it must be browser-callable, which introduces certain design constraints. These constraints do not apply when calling the service from a Flow view.

The following guides teach you how to call application services in Flow and Hilla: