This use case corresponds to the "Retrieve/Read" from the four basic data management use cases Create-Retrieve-Update-Delete (CRUD).
First of all, for the list objects use case we have to
add a method in the controller class (src/pl/ctrl/BookController.java
file), which
reads all the 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 2.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 3.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
listAll.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="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>
<h:button value="Main menu" outcome="index" />
</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
JSF element allows to create redirect buttons. The value of the
outcome
attribute specifies a name of a JSF view file by omitting the
.xhtml
extension (i.e. the view file name is index.xhtml
).