For the Retrieve use case we have
to add a method in the controller class
(src/pl/c/BookController.java
file), which reads all
Book
records from the books
database table and
then delivers this information to the view. The controller action method
code is shown below:
public class BookController { ... public List<Book> getBooks() { return Book.retrieveAll( em); } ... }
The getBooks
method returns a list of Book
instances which are obtained by calling the static
retrieveAll
method of the Book
model class. The
code of the Book.retrieveAll
method is:
public class Book { ... public static List<Book> retrieveAll( EntityManager em) { Query query = em.createQuery( "SELECT b FROM Book b"); List<Book> books = query.getResultList(); return books; } ... }
The code is simple, and as already discussed in Section 3.3, it uses a
JPQL statement to retrieve the Book
records from
the books
table and create the corresponding
Book
instances. The EntityManager
object
required for being able to perform the JPQL query is passed to
Book.retrieveAll
from the BookController
object
as discussed in Section 4.1 section.
Now it is the time to define the facelet template for displaying a
table with all book records found in the database. The view template files
corresponding to the model classes of our app are located in model class
subfolders of the WebContent/views/
folder. For the Retrieve/list all books use case, we create a
file named retrieveAndListAll.xhtml
in
WebContent/views/books/
with the following
content:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="..." xmlns:h="..." xmlns:f="..."> <ui:composition template="/WEB-INF/templates/page.xhtml"> <ui:define name="headerTitle"> <h1>Retrieve and list all book records</h1> </ui:define> <ui:define name="main"> <h:dataTable value="#{bookCtrl.books}" var="b"> <h:column> <f:facet name="header">ISBN</f:facet> #{b.isbn} </h:column> <h:column> <f:facet name="header">Title</f:facet> #{b.title} </h:column> <h:column> <f:facet name="header">Year</f:facet> #{b.year} </h:column> </h:dataTable> </ui:define> </ui:composition> </html>
The ui:composition
element specifies which template is
applied (i.e. template="/WEB-INF/templates/page.xhtml"
) and
which view block (<ui:define name="main">
) is replaced
by this facelet at render time.
The h:dataTable
element defines a table view for a set
of records, which is then rendered as an HTML table. Its
value
attribute defines a data binding to a record
collection, while the var
attribute defines a variable name
for iteratively accessing records from this collection. The expression
provided in the value
attribute normally specifies a
collection-valued property (here: books
) which is accessed
via a corresponding getter (here: getBooks
) as defined in the
controller class BookController
. In this particular case it
is just sufficient to define the getBooks
method since there
is no need of a books
property in the controller class. In
any case, value
does not allow to invoke a method, so we
cannot call getBooks
directly. Instead we have to use the
(possibly virtual) property books
, which internally evaluates
to a call of getBooks
without checking if a
books
property really exists.
The h:button
element allows to create redirect buttons.
The value of the outcome
attribute specifies a name of a
facelet file (omitting the .xhtml
extension, such
that, in the example, the file name is
index.xhtml
).