12Implementing Enumeration Attributes in a Java EE Web App

In this chapter, we show how to build a back-end web application with enumeration attributes, using Java with JPA and JSF. In addition to the topic of enumeration attributes, we also show how to deal with multi-valued attributes.

12.1New Issues

Compared to the Validation App discussed in Chapter 9 we have to deal with the following new issues:

  1. Enumeration datatypes have to be defined in a suitable way as part of the model code.
  2. Enumeration attributes have to be defined in model classes and handled in the user interface with the help of suitable choice widgets.

In terms of coding, the new issues are:

1.In the model code we have to take care of

a.enumerations to be defined in the form of Java enum classes;

b.single-valued enumeration attributes, like Book::originalLanguage, requiring the JPA annotation @Enumerated for defining the conversion between Java enumeration literals and corresponding database table column values;

c.multi-valued enumeration attributes, like Book::publicationForms, requiring the JPA annotation @Convert with suitable arguments defining a JPA custom converter for (de‐)serializing collections of Java enumeration literals;

d.extending the methods Book. create, and Book.update such that they take care of the enumeration attributes.

2.In the user interface code we have to take care of

a.adding new table columns in retrieveAndListAll.xhtml;

b.adding suitable choice widgets in create.xhtml and upate.xhtml;

c.rendering multi-valued enumeration attributes in the table view of retrieveAndListAll.xhtml and in the choice widgets of create.xhtml and upate.xhtml (with the help of an array of JSF SelectItems, each consisting of an enumeration value and its label).

12.2Make an Entity Class Model

Using the information design model shown in Figure 10.2 above as the starting point, we make an entity class model, essentially by adding getters/setters, constraint annotations and CRUD methods, as explained before:

Figure 12.1 A JPA entity class model for the object type Book

12.3Write the Model Code

12.3.1Code the enumerations

Simple enumerations, like BookCategoryEL and PublicationFormEL, are coded in the following way with the help of Java’s enum construct:

Notice how the enumeration literals are defined with capitalized names in a comma-separated list.

For a code list, like LanguageEL, where each enumeration instance consists of a code and a label, we use the codes as enumeration literals and define an attribute label for storing the labels, as well as a private constructor that allows creating enumeration instances consisting of a code and a label. This is possible because in Java, an enum is a special kind of class. Each entry in the list of enumeration literals, auch as EN("English"), represents an invocation of the enum’s constructor:

12.3.2Code the JPA entity class

The entity class Book is coded with the help of JPA annotations for class attributes, as well as the setter and getter methods of every class attribute.

For the case of single-valued enumeration attributes (like originalLanguage and category), the JPA annotation @Enumerated is used for specifying the storage serialization. It takes one of the following two parameter values:

EnumType.STRING means that enumeration literals are converted to strings when they are serialized ( e.g., in the case of the originalLanguage attribute of the Book class, the values saved in the database are one of “EN”, “DE”, “FR” or “ES”) ;

EnumType.ORDINAL means that enumeration literals are converted to their index integer when they are serialized (i. e.,the values saved in the database are 1, 2 ,3 etc.).

We store the collection values of a multi-valued enumeration attribute (like otherAvailableLanguages and publicationForms) in a database table column as serialized arrays in the form of ["value1", "value2", ]. In the case of the originalLanguage attribute, an example of a saved value would be ["EN", "FR", "DE"]. Achieving this behavior is possible with JPA by using custom converters to map database table column values to Java types and vice versa. The @Convert annotation allows specifying a Java converter that is responsible for the mappings.

Also, in the case of a multi-valued enumeration attribute, we use the @Size annotation to specify the minimum, and if required also the maximum, number of elements stored by this attribute. For example, in the case of publicationForms,we use @Size( min=1, message = "At least one publication form is required!"),which enforces to have at least one value for this attribute, otherwise the error message is displayed.

Notice the new methods in the last code block, like getPublicationFormsValues and getPublicationFormsItems, which are used for handling the enumeration attributes in the UI. We discuss each of them in the following subsections.

12.3.3Define a converter for serializing enumeration attribute values

A JPA attribute converter is a special Java class that implements the AttributeConverter interface with the methods convertToDatabaseColumn and convertToEntityAttribute. For the otherAvailableLanguages attribute, we define the following converter class:

An attribute converter class needs to be annotated with @Converter. In our example, the convertToDatabaseColumn method is responsible to convert the entity attribute value (e. g., otherAvailableLanguages) to a JSON array which is stored in the database as a String.

The convertToEntityAttribute method is responsible for de-serializing a table column’s value to the corresponding entity attribute value. In our example, this means to map the JSON array string to a Java Set of enumeration literals of type LanguageEL.

The code above shows the custom attribute converter class for the otherAvailableLanguages attribute. The attribute converter class for the publicationForms attribute is defined in the same way.

12.3.4Code the enumeration attribute setters

Both for single-valued and for multi-valued enumeration attributes an ordinary setter is defined. In the case of a multi-valued enumeration attribute, this setter assigns an entire set of values (in the form of a Java Set) to the attribute.

12.3.5Write a serialization function

The object serialization function now needs to include the values of enumeration attributes:

12.3.6Database schema

As we discussed in Chapter 4, the database schema can be automatically generated by a Java EE server like TomEE. The generated schema for our Book entity class is like so:

For every attribute (like category), a column with the same name but using upper case is created, (e. g., CATEGORY). This is the default naming, which is fine for our example application, but it can be changed, if required, by using the @Column ( name="") annotation, as in @Column( name="book_category").

The single-valued and multi-valued enumeration attributes are by default created as varchar columns with the default maximum length of 255 characters. However, if a longer (or shorter) length is desirable, this can be enforced by using the @Column( length=) annotation.

12.3.7Creating test data

In the test data objects that are created by Book.createTestData,we now have to provide values for single- and multi-valued enumeration attributes:

12.4Write the View Code

The example app’s user interface for creating a new book record with ISBN, title and four enumeration attributes looks as in Figure 12.2 below.

Figure 12.2 The user interface for creating a new book record

12.4.1Selection lists

We use JSF selection lists for rendering the enumeration attributes originalLanguage and otherAvailableLanguages in the code of the facelet files WebContent/views/books/create.xhtml and /update.xhtml:

The JSF element h:selectOneMenu allows creating single selection lists with the HTML select element. The list is populated with language options due to its child element <f:selectItems value="#{book.languageItems}"/>. Using the expression #{book.languageItems} results in calling the method getLanguageItems() on the book object. This method returns a set of SelectItem objects, which are used to populate the selection list. The corresponding method code is as follows:

A multiple selection list, corresponding to an HTML element <select multiple= "multiple" />, is created with the JSF element h:selectManyListbox using the same getLanguageItems method for obtaining the selection list items.

12.4.2Radio button groups and checkbox groups

Since the enumeration attributes category and publicationForms have not more than seven possible values, we can use a radio button group and a checkbox group for rendering them:

The radio button group is obtained by using the JSF element h:selectOneRadio. It renders a set of <input type="radio" /> elements. Using the same technique as for selection lists, the radio button group is populated with a set of SelectItem objects. The corresponding getCategoryItems method from the Book class is similar to getLanguageItems.

The checkbox group, consisting of <input type="checkbox" /> elements, is created with the JSF element h: selectManyCheckbox and populated in the same way as a radio button group or a selection list.

12.5Displaying Value Sets for Multi-Valued Enumeration Attributes

In the case of a multi-valued enumeration attribute like otherAvailableLanguages or publicationForms, the Retrieve/List All view must show a value in the form of a comma-separated list, like “English, German, Spanish”, as shown in the following table:

For this purpose, we define a method that creates the desired serialization of a multivalued attribute and use it in the code of the facelet file retrieveAndListAll. xhtml from WebContent/views/books/. For the publicationForms attribute, the method code is as follows:

Notice that in the case of the publicationForms attribute, the underlying enumeration PublicationFormEL does not have a label property. Instead, we use the enumeration literal name in lowercase as the label.

12.6Run the App and Get the Code

You can run the enumeration app147 on our server or download the code148 as a ZIP archive file.

12.7Practice Projects

In the following practice projects, first make a list of all the constraints that have been defined in this model and express them with validation annotations. Then make an entity class model as a starting for coding the app by following the guidance of this chapter and Chapter 9.

If you have any questions about how to carry out the following projects, you can ask them on our discussion forum149.

12.7.1Project 1Adding ratings and genres as enumeration attributes

The purpose of the app to be built is managing information about movies. The app deals with just one object type, Movie, and with two enumerations, as depicted in the following class diagram.

You can use the sample data shown in Table 11.1 for testing your app.

12.7.2Project 2Adding country codes and religions as enumeration attributes

The purpose of the app to be built is managing information about countries. The app deals with just one object type, Country, and with two enumerations, as depicted in the following class diagram.

Compared to the practice project of our validation tutorial, two attributes have been added: the single-valued enumeration attribute code, which is a “key” attribute (implying a uniqueness constraint), and the multi-valued enumeration attribute religions.

You can use the sample data shown in Table 11.2 for testing your app.

12.8Quiz Questions

If you would like to look up the answers for the following quiz questions, you can check our discussion forum150. If you don’t find an answer in the forum, you may create a post asking for an answer to a particular question.

12.8.1Question 1: JPA custom converter implementation class

Complete the following JPA custom converter class code, such that it serializes a value of type List<GenreEL> to String.:

12.8.2Question 2: Cardinality constraints for enum attributes

Complete the definition of the languages property, such that a minimum of three values are required.

12.8.3Question 3: JPA enum attribute serialization annotation

Use the appropriate JPA annotation, including parameter(s), such that the value of the genre property is serialized and stored as enumeration literal name, i. e., as String, and not as ordinal values (indexes):

12.8.4Question 4: JSF single-valued enum attribute

Which of the following is the name of a JSF element that can be used for rendering a choice widget for a single-valued enumeration attribute?

  1. O selectOneRadio
  2. O selectOnlyOne
  3. O radioGroup
  4. O radioSelect

12.8.5Question 5: JSF multi-valued enum attribute

Complete the following facelet code, such that the resulting HTML code consists of a checkbox group allowing to select multiple languages, when creating a new Book instance::

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset