Aplicativo de exemplo com Spring Boot e Vaadin

Aplicativo de exemplo com Spring Boot e Vaadin

1. Visão geral

Vaadin é umserver-side Java framework for creating web user interfaces.

Neste tutorial, vamos explorar como usar umVaadin based UI on a Spring Boot based backend. Para obter uma introdução ao Vaadin, consulte o tutorialthis.

2. Configuração

Vamos começar adicionando dependências Maven a um aplicativo Spring Boot padrão:


    com.vaadin
    vaadin-spring-boot-starter

Vaadin também é uma dependência reconhecida peloSpring Initializer.

Este tutorial usa uma versão mais recente do Vaadin que a padrão trazida pelo módulo inicial. Para usar a versão mais recente, basta definir a Lista de materiais (BOM) do Vaadin assim:


    
        
            com.vaadin
            vaadin-bom
            10.0.11
            pom
            import
        
    

3. Serviço de back-end

Usaremos uma entidadeEmployee com as propriedadesfirstNameelastName para realizar operações CRUD nela:

@Entity
public class Employee {

    @Id
    @GeneratedValue
    private Long id;

    private String firstName;
    private String lastName;
}

Aqui está o repositório Spring Data simples e correspondente - para gerenciar as operações CRUD:

public interface EmployeeRepository extends JpaRepository {
    List findByLastNameStartsWithIgnoreCase(String lastName);
}

Declaramos o método de consultafindByLastNameStartsWithIgnoreCase na interfaceEmployeeRepository. Ele retornará a lista deEmployees correspondendo alastName.

Vamos também preencher previamente o banco de dados com algunsEmployees de amostra:

@Bean
public CommandLineRunner loadData(EmployeeRepository repository) {
    return (args) -> {
        repository.save(new Employee("Bill", "Gates"));
        repository.save(new Employee("Mark", "Zuckerberg"));
        repository.save(new Employee("Sundar", "Pichai"));
        repository.save(new Employee("Jeff", "Bezos"));
    };
}

4. IU Vaadin

4.1. ClasseMainView

A classeMainView é o ponto de entrada para a lógica da IU do Vaadin. Annotation @Route tells Spring Boot to automatically pick it up and show at the root of the web app:

@Route
public class MainView extends VerticalLayout {
    private EmployeeRepository employeeRepository;
    private EmployeeEditor editor;
    Grid grid;
    TextField filter;
    private Button addNewBtn;
}

Podemos personalizar a URL onde a visualização é mostrada, dando um parâmetro para a anotação@Route:

@Route(value="myhome")

A classe usa os seguintes componentes da interface do usuário para serem exibidos na página:

EmployeeEditor editor - mostra o formulárioEmployee usado para fornecer informações do funcionário para criar e editar.

Grid<Employee> grid - gire para exibir a lista deEmployees

TextField filter - campo de texto para inserir o sobrenome com base no qual a cinta será filtrada

Button addNewBtn - botão para adicionar um novoEmployee. Exibe o editorEmployeeEditor.

Ele usa internamente oemployeeRepository para realizar as operações CRUD.

4.2. Fiação dos componentes juntos

MainView estendeVerticalLayout. VerticalLayout is a component container, which shows the subcomponents in the order of their addition (verticalmente).

Em seguida, inicializamos e adicionamos os componentes.

Fornecemos um rótulo ao botão com um ícone +.

this.grid = new Grid<>(Employee.class);
this.filter = new TextField();
this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create());

UsamosHorizontalLayout para organizar horizontalmente o campo de texto do filtro e o botão. Em seguida, adicione este layout, gird e editor no layout vertical pai:

HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn);
add(actions, grid, editor);

Forneça a altura da cintura e os nomes das colunas. Também adicionamos texto de ajuda no campo de texto:

grid.setHeight("200px");
grid.setColumns("id", "firstName", "lastName");
grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0);

filter.setPlaceholder("Filter by last name");

Na inicialização do aplicativo, a interface do usuário ficaria assim:

image

4.3. Adicionando lógica aos componentes

DefiniremosValueChangeMode.EAGER para o campo de textofilter. This syncs the value to the server each time it’s changed on the client.

Também definimos um ouvinte para o evento de mudança de valor, que retorna a lista filtrada de funcionários com base no texto fornecido emfilter:

filter.setValueChangeMode(ValueChangeMode.EAGER);
filter.addValueChangeListener(e -> listEmployees(e.getValue()));

Ao selecionar uma linha dentro da cinta, mostraríamos o formulárioEmployee, permitindo ao usuário editar o nome e o sobrenome:

grid.asSingleSelect().addValueChangeListener(e -> {
    editor.editEmployee(e.getValue());
});

Ao clicar no botão Adicionar novo funcionário, mostraríamos o formulárioEmployee em branco:

addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", "")));

Por fim, ouvimos as alterações feitas pelo editor e atualizamos a grade com dados do back-end:

editor.setChangeHandler(() -> {
    editor.setVisible(false);
    listEmployees(filter.getValue());
});

A funçãolistEmployees obtém a lista filtrada deEmployees e atualiza a grade:

void listEmployees(String filterText) {
    if (StringUtils.isEmpty(filterText)) {
        grid.setItems(employeeRepository.findAll());
    } else {
        grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText));
    }
}

4.4. Criando o formulário

Usaremos um formulário simples para o usuário adicionar / editar um funcionário:

@SpringComponent
@UIScope
public class EmployeeEditor extends VerticalLayout implements KeyNotifier {

    private EmployeeRepository repository;
    private Employee employee;

    TextField firstName = new TextField("First name");
    TextField lastName = new TextField("Last name");

    Button save = new Button("Save", VaadinIcon.CHECK.create());
    Button cancel = new Button("Cancel");
    Button delete = new Button("Delete", VaadinIcon.TRASH.create());

    HorizontalLayout actions = new HorizontalLayout(save, cancel, delete);
    Binder binder = new Binder<>(Employee.class);
    private ChangeHandler changeHandler;
}

The @SpringComponent is just an alias to Springs @Component annotation para evitar conflitos com a classe VaadinsComponent.

O@UIScope vincula o bean à IU atual do Vaadin.

Atualmente,Employee editado é armazenado na variável de membroemployee. Capturamos as propriedadesEmployee por meio dos campos de textofirstNameelastName.

O formulário tem três botões -save,canceledelete.

Depois que todos os componentes estiverem conectados, o formulário parecerá abaixo para uma seleção de linha:

image

Usamos umBinder which binds the form fields with the Employee properties using the naming convention:

binder.bindInstanceFields(this);

Chamamos o método EmployeeRepositor apropriado com base nas operações do usuário:

void delete() {
    repository.delete(employee);
    changeHandler.onChange();
}

void save() {
    repository.save(employee);
    changeHandler.onChange();
}

5. Conclusão

Neste artigo, escrevemos um aplicativo de interface do usuário CRUD com todos os recursos usando o Spring Boot e o Spring Data JPA para persistência.

Como de costume, o código está disponívelover on GitHub.