Like for Create, for the
Update use case also a controller
action method is defined in the BookController
class:
public class BookController { ... public String update( String isbn, String title, int year) { try { Book.update( em, ut, isbn, title, year); } catch ( Exception e) { e.printStackTrace(); } return "update"; } ... }
The Book.update
takes care of saving property value
changes for a book object identified by its isbn
value as
shown below:
public class Book { ... public static void update( EntityManager em, UserTransaction ut, String isbn, String title, int year) throws Exception { ut.begin(); Book book = em.find( Book.class, isbn); if (title != null && !title.equals( book.title)) { book.setTitle( title); } if (year != book.year) { book.setYear( year); } ut.commit(); } ... }
Now, we create the view where a Book
can be selected so
the user can edit the title
and year
properties,
and then save the changes. The code for this view is stored in the
WebContent/views/books/update.xhtml
file which has
the following content:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="..." xmlns:h="..." xmlns:f="..." xmlns:p="..."> <ui:composition template="/WEB-INF/templates/page.xhtml"> <ui:define name="headerTitle"> <h1>Update a book record</h1> </ui:define> <ui:define name="main"> <h:form id="updateBookForm"> <div><h:outputLabel for="selectBook" value="Select book: "> <h:selectOneMenu id="selectBook" value="#{book.isbn}"> <f:selectItem itemValue="" itemLabel="---"/> <f:selectItems value="#{bookCtrl.books}" var="b" itemValue="#{b.isbn}" itemLabel="#{b.title}"/> <f:ajax listener="#{bookCtrl.refreshObject( book)}" render="isbn title year" /> </h:selectOneMenu> </h:outputLabel></div> <div><h:outputLabel for="isbn" value="ISBN: "> <h:outputText id="isbn" value="#{book.isbn}"/> </h:outputLabel></div> <div><h:outputLabel for="title" value="Title: "> <h:inputText id="title" value="#{book.title}"/> </h:outputLabel></div> <div><h:outputLabel for="year" value="Year: "> <h:inputText id="year" p:type="number" value="#{book.year}"/> </h:outputLabel></div> <div><h:commandButton value="Save Changes" action="#{bookCtrl.update( book.isbn, book.title, book.year)}"/> </div> </h:form> </ui:define> </ui:composition> </html>
In this facelet template, a single selection list (that is, a
single-select
HTML element) is created with the help of the
JSF element h:selectOneMenu
, where the selection list items
(the HTML option
elements) are defined by the JSF elements
f:selectItem
or f:selectItems
. The
value
attribute of h:selectOneMenu
binds
book.isbn
to the value of the selected item (or
option
element). The selection list is populated with book
records with the help of a f:selectItems
element bound to
bookCtrl.books
. The attributes itemLabel
and
itemValue
define the option
elements' text and
value.
In the update view, when the user selects a book from the selection
list, the form fields are filled with the (ISBN, title and year) property
values of the selected book. While the ISBN is immediately available in
the view (on the front-end) as the value of the selected
option
element, the values of the title
and
year
properties have to be fetched from the back-end
database. This can be done with the help of the JSF element
f:ajax
, which sends an HTTP request message for invoking a
remote method, bookCtrl.refreshObject
, on the back-end using
XHR. This method takes the managed book
bean, and
updates its title
and year
properties with the
current values retrieved from the database. Its code is the
following:
public class BookController { ... public void refreshObject( Book book) { Book foundBook = Book.retrieve( em, book.getIsbn()); book.setTitle( foundBook.getTitle()); book.setYear( foundBook.getYear()); } ... }
To enforce a refresh of the HTML form after the user's selection,
such that it displays the values of isbn
, title
and year
, the f:ajax
element allows specifying
form fields to be updated with the render
attribute like, in
our case, render="isbn title year"
.
Finally, the h:commandButton
element is used for
invoking the update
action method of the
BookController
with the parameters isbn
,
title
and year
, for making the changes
persistent.