5. Step 4 - Implement the Create Use Case

The CRUD use case Create involves creating a new object in main memory and then saving it to persistent storage with the help of the create method.

The corresponding create action method code from the src/pl/c/BookController.java is shown below:

public class BookController {
  ...
  public String create( String isbn, String title, int year) {
    try {
      Book.create( em, ut, isbn, title, year);
      // clear the form after saving the Book record
      FacesContext fContext = FacesContext.getCurrentInstance();
      fContext.getExternalContext().getRequestMap().remove("book");
    } catch ( Exception e) {
      e.printStackTrace();
    } 
    return "create";
  }
}

The BookController::create action method invokes the Book.create model class method for creating and saving a Book instance. It returns the name of the view file found in the same folder as the view that triggered the action. This file (create.xhtml in our case) will be displayed after executing the action. Using the FacesContext object, the form is cleared after creating a Book instance. The code of the create method in src/pl/m/Book.java is the following:

public class Book {
  ...
  public static void create( EntityManager em, UserTransaction ut,
      String isbn, String title, int year) throws Exception {
    ut.begin();
    Book book = new Book( isbn, title, year);
    em.persist( book);
    ut.commit();
  }
}

Now we need to create the facelet template for the view of the Create use case, WebContent/views/books/create.xhtml. Such a facelet template essentially defines an HTML form with data binding and action binding.

Data binding refers to the binding of model class properties to form (input or output) fields. For instance, in the following facelet code fragment, the entity property book.isbn is bound to the form input field "isbn":

<h:outputLabel for="isbn" value="ISBN: ">
  <h:inputText id="isbn" value="#{book.isbn}" />
</h:outputLabel>

In JSF, for the inputText elements of a form, the id attribute is used with a given value, e.g., id="isbn". The rendered HTML5 input elements have both, the id and the name attributes, and their values are obtained by using the form id and element id values separated by a colon, i.e., id="createBookForm:isbn" and name="createBookForm:isbn".

We can also see a first example of an expression in the Java EE Expression Language (EL), where an expression starts with # and is enclosed in curly brackets, like #{expression}. Such an expression allows reading the value of a property of, or invoking a method on, a Java bean or a context object. The value of the expression is assigned to the value attribute of the generated HTML input element. The example in our JSF code above is the expression #{book.isbn}, which retrieves the value of the isbn property of the book bean.

Action binding refers to the binding of method invocation expressions to actionable UI elements, where the invoked methods typically are controller action methods, and the actionable UI elements typically are form buttons. For instance, in the following facelet code fragment, the method invocation expression bookCtrl.create(...) is bound to the form's submit button:

<h:commandButton value="Create" 
    action="#{bookCtrl.create( book.isbn, book.title, book.year)}"/>

After discussing data binding and action binding, it's time to look at the complete code of the facelet:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="..." xmlns:h="..." xmlns:p="...">
 <ui:composition template="/WEB-INF/templates/page.xhtml">
  <ui:define name="headerTitle">
   <h1>Create a new book record</h1>
  </ui:define>
  <ui:define name="main">
   <h:form id="createBookForm">
    <div><h:outputLabel for="isbn" value="ISBN: ">
      <h:inputText 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" 
         action="#{bookCtrl.create( 
             book.isbn, book.title, book.year)}" />
    </div>
   </h:form>
  </ui:define>
 </ui:composition>
</html>

This facelet replaces the main region of the template defined in page.xhtml, because the name attribute of the ui:define element has been set to "main", but it also replaces the headerTitle region of the template, which is part of the header and displays the current operations allowed by the page.

h:outputLabel elements can be used for creating form field labels, while h:inputText elements are used for creating HTML input elements. It is possible to specify a HTML5 type of an input element by using a special namespace prefix (xmlns:p = "http://xmlns.jcp.org/jsf/passthrough") for the type attribute, enforcing it to be 'passed through'. In this way the year input field can be defined with type number, so it's rendered by the corresponding number widget in the browser.

The h:commandButton element allows creating submit buttons rendered as a input elements with type="submit", and binding them to an action to be performed when the button is clicked. The value of the action attribute is a method invocation expression. In our Create use case we want that, when the button is clicked, a Book instance with the property values provided by corresponding form fields is created and saved.