The JPAContainer FieldFactory
is an implementation of
the FormFieldFactory
and
TableFieldFactory
interfaces that can generate
fields based on JPA annotations in a POJO. It goes further than the
DefaultFieldFactory
, which only creates simple fields
for the basic data types. This way, you can easily create forms to input
entities or enable editing in tables.
The result is bit similar to what you can achieve with Spring Roo, as described in Section 14.4, “Creating Vaadin Application and CRUD Views”. However, the form views are generated dynamically at run-time, whereas Roo generates static form views.
The generated defaults are as follows:
Annotation | Class Mapping |
---|---|
|
|
| Nested |
|
|
| Selectable |
The field factory is recusive, so that you can edit a complex object tree with one form.
The FieldFactory
is highly configurable with
various configuration settings and by extending. You need to make the
configuration before
The setMultiSelectType()
and
setSingleSelectType()
allow you to specify a
selection component that is used instead of the default for a field with
@ManyToMany
and @ManyToOne
annotation, respectively. The first parameter is the class type of the
field, and the second parameter is the class type of a selection
component. It must be a sub-class of
AbstractSelect
.
The setVisibleProperties()
controls which
properties (fields) are visible in generated forms, subforms, and
tables. The first paramater is the class type for which the setting should
be made, followed by the IDs of the visible properties.
The configuration should be done before binding the form to a data source as that is when the field generation is done.
Further configuration must be done by extending the many protected methods. Please see the API documentation for the complete list.
The most basic use case for the JPAContainer
FieldFactory
is with a Form
bound to a container item:
// Have a persistent container final JPAContainer<Country> countries = JPAContainerFactory.make(Country.class, "book-examples"); // For selecting an item to edit final Select countrySelect = new Select("Select a Country", countries); countrySelect.setItemCaptionMode(Select.ITEM_CAPTION_MODE_PROPERTY); countrySelect.setItemCaptionPropertyId("name"); // Country Editor final Form countryForm = new Form(); countryForm.setCaption("Country Editor"); countryForm.addStyleName("bordered"); // Custom style countryForm.setWidth("420px"); countryForm.setWriteThrough(false); // Enable buffering countryForm.setEnabled(false); // When an item is selected from the list... countrySelect.addListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { // Get the item to edit in the form Item countryItem = countries.getItem(event.getProperty().getValue()); // Use a JPAContainer field factory // - no configuration is needed here final FieldFactory fieldFactory = new FieldFactory(); countryForm.setFormFieldFactory(fieldFactory); // Edit the item in the form countryForm.setItemDataSource(countryItem); countryForm.setEnabled(true); // Handle saves on the form final Button save = new Button("Save"); countryForm.getFooter().removeAllComponents(); countryForm.getFooter().addComponent(save); save.addListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { try { countryForm.commit(); countryForm.setEnabled(false); } catch (InvalidValueException e) { } } }); } }); countrySelect.setImmediate(true); countrySelect.setNullSelectionAllowed(false);
This would create a form shown in Figure 18.6, “Using FieldFactory with One-to-Many Relationship”.
If you use Hibernate, you also need to pass an
EntityManagerPerRequestHelper
, either for the
constructor or with
setEntityManagerPerRequestHelper()
, as described
in Section 18.9.2, “The EntityManager-Per-Request pattern”.
The MasterDetailEditor
is a field component that
allows editing an item property that has one-to-many relationship. The
item can be a row in a table or bound to a form. It displays the
referenced collection as an editable Table
and
allows adding and removing items in it.
You can use the MasterDetailEditor
manually, or
perhaps more commonly use a JPAContainer
FieldFactory
to create it automatically. As shown
in the example in Figure 18.6, “Using FieldFactory with One-to-Many Relationship”, the factory creates a
MasterDetailEditor
for all properties with a
@OneToMany
or an @ElementCollection
annotation.