This demo shows how you can extend your data entities to auto-generate Grids and Forms.
Based on:
Use this annotation to let the GenericView auto-render your Grid. Use the annotaion properties to configure the behavior of each column.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface GridColumn {
String header() default "";
int order() default 999;
boolean sortable() default true;
String dateTimeFormat() default "";
}
Use this annotation to define, which Entity.Property will show up to edit and how it behaves.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FormField {
String label() default "";
int order() default 999;
boolean required() default false;
}
This demo provides two entity types:
@Data
@AllArgsConstructor
public class Person implements BaseEntity {
@GridColumn(header = "ID", order = 0)
private Long personId;
@GridColumn(header = "First Name", order = 1)
@FormField(label = "First Name", required = true, order = 1)
private String firstName;
@GridColumn(header = "Last Name", order = 2)
@FormField(label = "Last Name", required = true, order = 2)
private String lastName;
@GridColumn(header = "Email", order = 3, sortable = false)
@FormField(label = "Email", required = true, order = 3)
private String email;
@GridColumn(header = "Is Active", order = 4)
@FormField(label = "Is Active", required = true, order = 4)
private Boolean isActive;
@GridColumn(header = "Birthday", order = 5, dateTimeFormat = "dd.MM.yyyy")
@FormField(label = "Birthday", required = true)
private LocalDate birthday;
@GridColumn(header = "Age", order = 6)
public int getAge() {
if (birthday == null) return 0;
return Period.between(birthday.atStartOfDay().toLocalDate(), LocalDate.now()).getYears();
}
}
This view demonstrates how to bootstrap components or views using autogenerated Grids and Forms.
@PageTitle("PERSONS")
@Menu(order = 0, icon = "line-awesome/svg/home-solid.svg")
@Route(value = "", layout = MainLayout.class)
public class PersonView extends GenericView<Person> {
private final DataService dataService;
public PersonView(DataService dataService) {
super(Person.class);
this.dataService = dataService;
refreshGrid();
}
@Override
protected void saveEntity(Person entity) {
}
@Override
protected List<Person> loadEntities() {
return dataService.findAllPersons();
}
}
The GenericView is a type-safe, annotation-driven generic CRUD (Create, Read, Update, Delete) implementation for Vaadin applications that automatically generates Grid views and edit forms based on entity definitions. It minimizes boilerplate code while maintaining flexibility and extensibility.
Java Reflection API
Custom Annotations
@GridColumn
: Configures grid column properties and formatting@FormField
: Defines form field properties and validationVaadin Components
Design Patterns
<T extends BaseEntity>
Presentation Layer
Data Binding Layer
Metadata Layer
Reduced Boilerplate
Type Safety
Maintainability
Flexibility