Статьи

JSF 2.0, JPA, GlassFish и MySQL

Это приложение Pet Catalog объясняет веб-приложение, которое использует JSF 2.0, JPA, GlassFish и MySQL. Я взял этот пример   GlassFish и MySQL: Часть 2. Создание веб-приложения CRUD с сохранением данных и изменил его для использования некоторых новых функций JSF 2.0. 

На рисунке ниже показана страница списка каталогов, которая позволяет пользователю просматривать список товаров в магазине.

JSF 2.0 Facelets XHTML вместо JSP

Для JSF 2.0 Facelets XHTML является предпочтительным способом объявления веб-страниц JSF. JSP поддерживается для обратной совместимости, но не все функции JSF 2.0 будут доступны для представлений, использующих JSP в качестве языка объявления страниц. В JSF 2.0 Facelets есть несколько приятных функций, таких как создание шаблонов (схожих по функциональности с Tiles) и составных компонентов, о которых я не буду здесь говорить, но вы можете прочитать об этом в этой статье: http://www.ibm.com/developerworks /java/library/j-jsf2fu2/index.html и в этом техническом совете составные компоненты пользовательского интерфейса в JSF 2.0.

Ресурсы приложения Каталог

JSF 2.0 стандартизирует способы определения веб-ресурсов. Ресурсы — это любые артефакты, которые могут понадобиться компоненту для правильной визуализации — файлы изображений, CSS или JavaScript. С JSF 2.0 вы помещаете ресурсы в каталог ресурсов или подкаталог.

На ваших страницах Facelets вы можете получить доступ к файлам css с помощью <h: outputStylesheet>, файлам javascript с помощью <h: outputScript> и изображениям с тегами JSF <h: graphicImage>. List.xhtml использует  тег <h: outputStylesheet для загрузки таблицы стилей styles.css и тег <h: graphicImage для отображения изображений из ресурсов, как показано ниже:

<h:outputStylesheet name="css/styles.css" target="body"/>
<h:graphicImage library="images" name="banner_logo.gif" />

Приложение Каталог использует пакет ресурсов для хранения статического текста и сообщений об ошибках, используемых страницами Facelets. Помещение сообщений в пакет ресурсов облегчает изменение и интернационализацию текста вашего приложения. Сообщения находятся в файле свойств в каталоге пакета java.

Title=Pet Catalog
Next=Next
Previous=Prev
Name=Name

Пакет ресурсов настраивается в файле face-config.xml (вам не нужна никакая другая конфигурация в face-config.xml для JSF 2.0, как будет объяснено позже, вам больше не нужно настраивать управляемые компоненты и навигацию с XML).

 <application>
<resource-bundle>
<base-name>web.WebMessages</base-name>
<var>msgs</var>
</resource-bundle>
</application>

Страница Facelets List.xhtml использует компонент dataSable JSF для отображения списка элементов каталога в HTML-таблице. Компонент dataTable полезен, когда вы хотите отобразить набор результатов в таблице. В приложении JavaServer Faces компонент UIData (суперкласс dataTable) поддерживает привязку к коллекции объектов данных. Он выполняет итерацию по каждой записи в источнике данных. В HTML DataTable визуализации отображает данные в виде HTML — таблицы.

На веб-странице list.xhtml dataTable определен, как показано ниже: (Примечание: красные цвета — для тегов Java EE , кода аннотаций, а зеленый — для моего кода или переменных )

<h:dataTable value='#{catalog.items}' var='row' border="1"
cellpadding="2" cellspacing="0">

Атрибут value тега dataTable ссылается на данные, которые будут включены в таблицу. Атрибут var задает имя, которое используется компонентами в теге dataTable как псевдоним данных, на которые есть ссылка в атрибуте значения dataTable. В теге dataTable со страницы List .jsp атрибут value указывает на список элементов каталога. Атрибут var указывает на один элемент в этом списке. Поскольку компонент dataTable выполняет итерацию по списку, каждая ссылка на dataTableItem указывает на текущий элемент в списке.

Аннотации JSF 2.0 вместо конфигурации XML

Значение dataTable связано с items свойство каталога управляемый боб. В управляемых компонентах JSF 2.0 нет необходимости настраивать файл face-config.xml, вместо этого вы комментируете управляемые компоненты, как показано ниже:

@ManagedBean
@SessionScoped
public class Catalog implements Serializable {

По соглашению имя управляемого компонента совпадает с именем класса, причем первая буква имени класса в нижнем регистре. Чтобы указать имя управляемого компонента, вы можете использовать атрибут name аннотации ManagedBean, например: @ManagedBean (name = «Catalog»).

Этот каталогСвойство ManagedBean items определяется, как показано ниже:

    private DataModel items = null;

public DataModel getItems() {
if (items == null) {
getPagingInfo();
items = new ListDataModel(getNextItems(pagingInfo.getBatchSize(), pagingInfo.getFirstItem()));
}
return items;
}

Метод getItems () переносит список объектов элементов в DataModel . UIData, суперкласс dataTable, поддерживает привязку данных к коллекции объектов данных, представленных экземпляром DataModel . Коллекция данных, лежащая в основе экземпляра DataModel, моделируется как коллекция объектов строк, к которым может обращаться индекс строки. API предоставляют механизмы для позиционирования по указанному индексу строки и для извлечения объекта, который представляет данные, которые соответствуют текущему индексу строки.   

Предмет свойства Name, Фото и
цены
отображаются с
компонентом
столбца :

<h:dataTable var="row" value="#{catalog.items}">
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.Name}"/>
</f:facet>
<h:outputText value="#{row.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.Photo}"/>
</f:facet>
<h:graphicImage library="images" name="#{row.imagethumburl}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.Price}"/>
</f:facet>
<h:outputText value="#{row.price}"/>
</h:column>
</h:dataTable>

The column tags represent columns of data in a UIData component. While the UIData component is iterating over the rows of data, it processes the UIColumn component associated with each column tag for each row in the table.

The UIData component  iterates through the list of items (catalog.items)  and displays the row.price. Each time UIData iterates through the list of items, it renders one cell in each column.

The dataTable and column tags use facet to represent parts of the table that are not repeated or updated. These include headers, footers, and captions.

Using the Java Persistence API (JPA) with JSF

The Catalog ManagedBean uses the Java Persistence API EntityManager Query object to return a list of items. The Catalog ManagedBean annotates the field private EntityManager em;  with @PersistenceUnit , which causes an entity manager factory to be injected when the managed bean is instatiated.

@ManagedBean
@SessionScoped
public class Catalog implements Serializable {

@PersistenceUnit(unitName = "catalogPU")
private EntityManagerFactory emf;

private EntityManager getEntityManager() {
return emf.createEntityManager();
}

public List<Item> getNextItems(int maxResults, int firstResult) {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select object(o) from Item as o");
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
return q.getResultList();
} finally {
em.close();
}
}

The Java Persistence Query APIs are used to create and execute queries that can return a list of results.  The JPA Query interface provides support for pagination via the setFirstResult() and setMaxResults() methods: q.setMaxResults(int maxResult) sets the maximum number of results to retrieve. q.setFirstResult(int startPosition) sets the position of the first result to retrieve.

In the code below, we show the Item entity class which maps to the  ITEM table that stores the item instances. This is a typical Java Persistence entity object. There are two requirements for an entity:

  1. annotating the class with an @Entity annotation.
  2. annotating   the primary key identifier with @Id

Because the fields name, description…. are basic mappings from the object fields to columns of the same name in the database table, they don’t have to be annotated.  The O/R  relationships with Address and Product are also annotated. For more information on defining JPA entities see Pro EJB 3: Java Persistence API book.

@Entity
public class Item implements java.io.Serializable {

@Id
private Integer id;
private String name;
private String description;
private String imageurl;
private String imagethumburl;
private BigDecimal price;
@ManyToOne
private Address address;
@ManyToOne
private Product product;

public Item() { }

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

...
}

The Catalog ManagedBean pages through the list of Items by maintaining the PagingInfo.firstItem and PagingInfo.batchSize attributes and passing these as parameters to the  getNextItems(firstItem, batchSize) method. The catalog‘s scope  is defined with the annotation @SessionScoped, a JSF Managedbean with session scope will be stored in the session meaning that the bean’s properties will stay alive for the life of the Http Session.

A JSF commandButton is  used to provide a button to click on to display the next page of items.  The commandButton tag is used to submit an action event to the application. 

 <h:commandButton action="#{catalog.next}" value="#{msgs.Next}" />   

This commandButton action attribute references the catalog Managed bean next() method which calculates the next page’s first row number  and returns a logical outcome String, which causes the list.xhtml page to display the next page’s list . The catalog next method is defined as shown below:

   public String next() {
if (firstItem + batchSize < itemCount()) {
firstItem += batchSize;
}
return "list";
}

JSF 2.0 Simplified Navigation

The JavaServer Faces 2.0  NavigationHandler convention adds .xhtml to the logical outcome of the action method (in this example list) and loads that file, in this case, it loads the list.xhtml page after this method returns. If the action doesn’t begin with a forward slash (/), JSF assumes that it’s a relative path.  You can specify an absolute path by adding the slash like this «/items/list».

A JSF commandLink is  used to provide a link to click on to display a page with the item details. This commandLink action attribute  references The catalog getDetail() method:

   <h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:commandLink action="#{catalog.getDetail}" value="#{row.name}"/>
</h:column>

The catalog getDetail() method  gets the item data from the current row of the dataModel, and returns a string which causes the detail.xhtml page to display the item details :

public String getDetail() {
item = (Item) model.getRowData();
return "detail";
}

The JavaServer Faces NavigationHandler adds .xhtml to the logical outcome of the action, detail and loads that file. In this case, the JavaServer Faces implementation loads the detail.xhtml page after this method returns.

The detail.xhtml uses the outputText component to display the catalog ManagedBean’s item properties:

    <h:outputText value="#{catalog.item.name}" title="Name" />
<h:outputText value="#{catalog.item.description}" title="Description"/>
<h:graphicImage library="images" name="#{catalog.item.imageurl}" title="Imageurl" />
<h:outputText value="#{catalog.item.price}" title="Price" />
<h:outputText value="#{catalog.item.address.city}" title="Address" />
<h:outputText value="#{catalog.item.contactinfo.email}" title="Address"/>  

Hot Deployment and Session Retention with JSF 2.0 and Glassfish

  • Incremental compile of all JSF 2.0  artifacts when you save.
  • Auto-deploy of all web or Java EE 6 artifacts
  • Session retention: maintain stateful sessions across re-deployments

Conclusion

This concludes the sample application which demonstrates a pet catalog web application which uses JSF 2.0, JPA, GlassFish and MySQL. Next let’s run the application. 

Running the Sample Application

  1. If you haven’t already done so, download and install NetBeans IDE , GlassFish , and MySQL Community Server . You can download and install GlassFish with NetBeans as a single bundle.
  2. Follow these instructions to install JSF Mojarra 2.0.0 Beta2 on GlassFish v2 or Glassfish v3
  3. Download the sample code.

Create the Pet Catalog database

In order to run the sample code you first have to create the Pet Catalog database and fill in  the Item table.

  1. Start NetBeans IDE
  2. Ensure that GlassFish is registered in the NetBeans IDE, as follows:
    • Click the Services tab in the NetBeans IDE.
    • Expand the Servers node. You should see GlassFish v2 in the list of servers. If not, register GlassFish v2 as follows:
      • Right-click the Servers node and select Add Server. This opens an Add Server Instance wizard.
      • Select GlassFish v2 in the server list of the wizard and click the Next button.
      • Enter the location information for the server and click the Next button.
      • Enter the admin name and password and click the Finish button.
  3. Start the MySQL or Java DB database as follows:
    • Click the Services tab in the NetBeans IDE.
    • Expand the databases node. You should see the Java DB database in the list of databases. If you have installed the MySQL server database, you should also see the MySQL database in the list of databases.. Note:  Java DB  comes bundled with Netbeans, you can  download MySQL separately.

    • Right-mouse click on the Java DB or MySQL server database and select Start.
  4. If you installed MySQL, set the properties of the MySQL server database as follows:

  5. Right-click on the MySQL server or Java DB database and select Start.
  6. Create the petcatalog database as follows:
    • Right-mouse click on the Java DB or MySQL server database and select Create Database. This will open a create Database window.
    • Enter the database name catalog for Java DB or petcatalog for MySQL.

      For Java DB enter userid password app app as shown below:


       Click O.K. to accept the displayed settings.

  7. Create the tables in the catalog database as follows:
  8. View the data in the Pet Catalog database Item table as follows:
  9. Follow these instructions to Create a JDBC Connection pool and JDBC resource.Name the  pool mysql_petcatalog_rootPool and the jndi resource jdbc/petcatalog. Note: you do not have to create a JDBC connection pool and resource if you use the Netbeans wizard to generate JPA entities from database tables as described in this article GlassFish and MySQL, Part 2: Building a CRUD Web Application With Data Persistence.

Running the Sample solution:

If you want to run the sample solution, you have to create the catalog database tables first as described above.

  1. If you haven’t already download the sample code and start the NetBeans IDE. Unzip the catalog.zip file which you downloaded, this will create a catalog directory with the project code.
  2. Open the catalog/setup/sun-resources.xml file and verify that the property values it specifies match those of the petcatalog database and jdbc resources you created. Edit the property values as necessary.
  3. Open the catalog project as follows:
    • In NetBeans IDE, click Open Project in the File menu. This opens the Open Project dialog.
    • Navigate in the Open Project dialog to the catalog  directory and click the Open Project button.


    In response, the IDE opens the catalog project.  You can view the logical structure of the project in the Projects window (Ctrl-1).

  4. Run the catalog by right-clicking on the catalog project in the Projects window and selecting Run Project. The NetBeans IDE compiles the application, deploys it on Glassfish, and brings up the default page in your browser.  (at http://localhost:8080/catalog/).

For more information see the following resources: