Data Management
Categories of Data Sources¶
Within a web application you need to manage data by reading it from or/and writing it to “somewhere”. Conceptually, there are the following categories of data sources:
- Webservices, called with a request/response pattern
- Messaging systems, called with a publish/subscribe pattern
- Databases, called through a persistence layer, e.g. with the help of the Java Persistence Architecture (JPA) or the jOOQ framework
- Business logic, typically implemented in Enterprise Java Beans (EJB)
EJBs that implement business logic often access webservices, messaging systems and databases. You can wrap the access to webservices, messaging systems and databases by means of additional EJBs. This gives you the advantages of a unified exception handling and an improved testability by easy mocking.
The generated [layout-name]Bean.java is the place where you want to access data sources.
You inject interfaces by means of @EJB
or @Inject
.
The implementation of EJBs, persistence layers, webservice and messaging clients is beyond the scope of this documentation.
Datatypes¶
Even when EJBs are being used to access data sources, it is technically possible and sometimes desirable to directly use datatypes that are being used in webservice or messaging clients. When you retrieve data through a webservice/messaging client, it often makes sense to keep that data available for the lifetime of a user session or at least of a web page. Doing so prevents you from the need to call the service again to retrieve the same data that you were retrieving by a previous call.
Data Mapping¶
Binding data to web pages is done with generated Java classes (we call them ‘DTO’). In XHTML files the classes’ properties are being referenced by means of expressions like this:value=#{beanName.propertyName}
.
It is the generator DTOs for UI
that generates the Java classes. A UI model is taken as input.
Data mapping is the act of bringing data from a data source to the DTOs and vice versa. Data mapping can be done in [layout-name]Bean.java or delegated to a separate Java class. Delegating the mapping to a separate Java class is one of the means to keep the size of [layout-name]Bean.java under control. The data mapper class will be placed in the same JAR file as [layout-name]Bean.java.
Any DTO object initialization should be implemented in the generated method initDtos()
in [layout-name]Bean.java.
When you want to make calls to EJBs or other objects to do the initialization, make those calls from that method.
Normally, you call the method initDtos()
from the method initApplication()
and from event handlers.
Info
In future versions of the JSF generators, there will also be data mapping code generated.
Data Conversion¶
On a web page, data is always displayed and edited as text. Data in programing languages is more diverse, though. There you can have numbers, dates, bytes, booleans, enumerations. In order to convert from one to the other and vice versa, JSF provides some default converters. Those converters are implicitely applied, depending on the type of the bound DTO field. Explicitely adding such a converter in the XHTML file makes sense in a few cases:
- when displaying a date as pure text and you want to control the formatting of the date, e.g. suppressing the display of the time portion
- when displaying a number as pure text and you want to control the formatting of the number, e.g. to use a thousands separator or not
- when displaying a boolean as pure text and you want to control the formatting, e.g. showing a more expressive text than ‘true’ or ‘false’
The generator does not generate the usage of such converters. You have to add them manually if you want to use them.
Also, you can always manually develop your own converter class and assign it to a UI component by using the converter
attribute.
You find an example for this in the PrimeFaces showcase SelectOneMenu.
The code for the custom converter, a theme converter, can be found on GitHub.
Data Selection¶
For every component that is used to select one or more items from a master list of data items (e.g. <p:selectOneMenu>
), the generator creates the following in [layout-Name]Bean.java:
- a property with name “items[component-Name][display-Name]” and the type
ArrayList<SelectItem>
. - an individual converter class (as a static inner class)
Normally, the initialization of the items...
property is done within initApplication()
.
If you want to provide select items in a more dynamic way, you can re-initialize the array list in other places, e.g. in an event handlers action...()
.
The converter class implements javax.faces.converter.Converter
and gets a converter-id defined for it.
The converter-id follows this naming convention:
“[layout-name]Bean[display-Name][component-Name]Converter”.
The default implementation of the converter class assumes that the value
property of the instances of javax.faces.model.SelectItem
is of type String
.
You need to manually change the default implementation when you use objects of different types when doing the initializaiton of the select items.
Note
Every generated converter class has a property where the managed bean [layout-Name]Bean.java is injected. This is required to be able to access the collections of select items.
Data Validation¶
There are four types of validation that occur when using a web page:
- JSF standard validators:
<f:validateBean>
(is used implicitly),<f:validateDoubleRange>
,<f:validateLength>
,<f:validateLongRange>
,<f:validateRegEx>
,<f:validateRequired>
(is used implicitly by means ofrequired="true"
) - Bean validation (JSR 303), you can internationalize the validation messages by adding a
ValidationMessages
resource bundle - Validation method in a managed bean
- Custom validator classes, implementing
javax.faces.validator.Validator
Note
Normally, you will never have to explicitely add a tag <f:validateBean>
or <f:validateRequired>
.
Only when you want to fine-tune the validation functionality that comes with those tags, you might add them.
Currently, the generator does not create anything else than required="#{...}"
when a UI component has DataEntryRequired set to true.
PrimeFaces Client Side Validation¶
PrimeFaces provides the functionality “Client Side Validation” which uses JavaScript to validate before an HTTP request is sent. To enable this, you have to set the following in a web.xml or web-fragment.xml:
<context-param>
<param-name>primefaces.CLIENT_SIDE_VALIDATION</param-name>
<param-value>true</param-value>
</context-param>
For a PrimeFaces component you then enable this feature by setting an attribute: validateClient=true
.
Test Data for Mocking¶
By providing another set of classes that implement the same interfaces as the EJB classes that serve as data sources, web pages can be
tested without accessing databases, webservices or messaging systems. This mocking mechanism uses CDI and will only work when you use the @Inject
annotation instead of @EJB
.
Or more commonly said: “Contexts and Dependency Injection” (CDI) allows you to mock data sources.