Articles
Java Platform, Standard Edition
|
| By Ed Ort and Carol McDonald, November 2008 |
|
| |
This is the second article in a series of articles on GlassFish and MySQL.
Part 1 of the series describes the advantages of using GlassFish with MySQL and illustrates why the combination is a perfect choice for developing and deploying web applications. In Part 2, you'll learn how to develop a create, read, update, delete (CRUD) web application that uses GlassFish and MySQL. The application uses the Java Persistence API implemented in GlassFish to manage data persistence.
An important characteristic of both GlassFish and MySQL is that they're easily integrated into popular development tools. For example, plug-ins are available for both GlassFish and MySQL to integrate them into the NetBeans IDE and the Eclipse IDE. In addition, NetBeans IDE 6.1 With GlassFish and MySQL Bundle Download is available that integrates GlassFish v2 Update Release 2 (UR2) and MySQL 5.0 Community Server into NetBeans IDE 6.1. You can also download GlassFish v2UR2 with either NetBeans IDE 6.1 or NetBeans IDE 6.5 in a single bundle. A precursor to the next version of GlassFish, called the GlassFish v3 Prelude, is also available with NetBeans IDE 6.5.
This article shows you how to use the NetBeans IDE with GlassFish and MySQL to create the CRUD application. Specifically, you'll take advantage of features in NetBeans IDE 6.5, GlassFish v2UR2, and MySQL 5.1 Community Server to build and deploy the application.
You can examine the completed CRUD application by downloading and expanding the petcatalog application package.
| - | The Application |
| - | Inside the Application |
| - | Building the Application |
| - | Summary |
| - | For More Information |
| |
The application for this article allows users to search an online catalog of pets. For example, users can search for a specific type of pet, such as medium-sized dogs, and display information about the items of that type in the catalog. Figure 1 shows a page that the application displays with this type of information.
Figure 1.
Medium-Sized Dogs in the Catalog
|
Retrieving information from the catalog represents the read or R capability of the CRUD application. As Figure 2 shows, a user can create a new item and add it to the catalog. This represents the application's create or C capability.
Figure 2.
Creating a New Item
|
A user can also edit an entry in the catalog. This demonstrates the application's update or U capability. A user can also delete an entry. This demonstrates the application's delete or D capability.
| |
Before building the application, let's examine the components of the completed application. If you haven't already done so, download and expand the petcatalog application package.
Central to the application is the catalog, which is contained in a MySQL database named
petcatalog. The
petcatalog database has four tables:
category. Contains information about each item category in the catalog, such as dogs. For each category, the table contains an identification (ID) number, name, description, and URL of a representative image.
product. Contains information about each product type within a category, such as medium dogs or small dogs. For each product, the table contains an ID number, product ID number, name, description, and URL of a representative image.
item. Contains information about each item in the catalog, such as beach dog. For each item, the table contains an ID number, product ID number, name, description, URL of the item's image, URL of the item's thumbnail image, price, and address ID.
address. Contains information about the address of each item in the catalog. The address includes street, city, state, zip code, latitude, and longitude.
For example, here are the contents of the
category table:
+----+----------+-----------------------------+---------------------------+ | id | name | description | imageurl | +----+----------+-----------------------------+---------------------------+ | 1 | Cats | Loving and finicky friends | /images/cats_icon.gif | | 2 | Dogs | Loving and furry friends | /images/dogs_icon.gif | | 3 | Birds | Loving and feathery friends | /images/birds_icon.gif | | 4 | Reptiles | Loving and scaly friends | /images/reptiles_icon.gif | | 5 | Fish | Loving aquatic friends | /images/fish_icon.gif | +----+----------+-----------------------------+---------------------------+ |
You will find a file named
catalog.sql in the
petcatalog application . The file contains the SQL statements that create the tables and fill them with data. For example, here are the SQL statements that create the
category table and fill it with data:
create table category(
id BIGINT NOT NULL,
name VARCHAR(25) NOT NULL,
description VARCHAR(255) NOT NULL,
imageurl VARCHAR(55),
primary key (id)
);
INSERT INTO category VALUES(1, 'Cats', 'Loving and finicky friends', '/images/cats_icon.gif');
INSERT INTO category VALUES(2, 'Dogs', 'Loving and furry friends', '/images/dogs_icon.gif');
INSERT INTO category VALUES(3, 'Birds', 'Loving and feathery friends', '/images/birds_icon.gif');
INSERT INTO category VALUES(4, 'Reptiles', 'Loving and scaly friends', '/images/reptiles_icon.gif');
INSERT INTO category VALUES(5, 'Fish', 'Loving aquatic friends', '/images/fish_icon.gif');
|
|
|
It's easy to manage and query databases in MySQL using SQL.
|
This demonstrates how easy it is in MySQL to create database tables and fill them with content. You manage and query databases in MySQL using ANSI standard SQL, a language that many users find easy to use because of its relatively straightforward syntax.
If you further examine the completed application, you'll notice that it follows the model-view-controller (MVC) design pattern. That is, the application isolates its data, known as the model, from the user interface or view, and from the code that manages the communication between the model and the view, known as the controller. You'll find the model and the controller in the
src/java directory of the application. You'll find the view in the
web directory.
Let's first look at the model for the application.
|
|
One of the advantages of using GlassFish as the application server for this application is that it includes a built-in persistence manager, the Java Persistence API.
|
The model not only represents the data for the application, but it also represents persistent data, that is, data that persists beyond the life of the application. In other words, the model represents an application's persistent business domain objects. One of the advantages of using GlassFish as the application server for this application is that it includes a built-in persistence manager, the Java Persistence API based on Toplink Essentials. Taking advantage of this feature, the application uses the Java Persistence API to manage data persistence.
If you open the
model directory, you will see various Java classes. Four of these classes,
Address,
Category,
Item, and
Product, are entity classes -- typical Java Persistence API entity objects -- for the four tables in the
petcatalog database. In the Java Persistence API, an entity instance, an instance of an entity object, represents a row of data in a database table. For example,
Item is an entity class that maps to the
item table in the
petcatalog database. An instance of the
Item entity represents a row of data in the
item table. Here is part of the source code for the
Item class:
package model;
import java.io.Serializable;
...
@Entity
@Table(name = "item")
public class Item implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "id")
private Long id;
@Basic(optional = false)
@Column(name = "name")
private String name;
@Basic(optional = false)
@Column(name = "description")
private String description;
@Column(name = "imageurl")
private String imageurl;
@Column(name = "imagethumburl")
private String imagethumburl;
@Basic(optional = false)
@Column(name = "price")
private BigDecimal price;
@JoinColumn(name = "address_id", referencedColumnName = "id")
@ManyToOne
private Address address;
@JoinColumn(name = "product_id", referencedColumnName = "id")
@ManyToOne
private Product product;
//getters and setters
...
|
Notice the
@ManyToOne annotations in the
Item class. These specify that the
Item class has a many-to-one relationship with the
Address class and a many-to-one relationship with the
Product class. This means that there can be multiple items in the catalog associated with the same address or with the same product type.
Conversely, the
Address and
Product classes have a one-to-many relationship with the
Address class. This means that an item cannot be associated with multiple addresses or multiple product types. The one-to-many relationship is specified in
@OneToMany annotations in the
Address and
Product entity classes. Here is the one-to-many annotation in the
Address class:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "address") |
Here is the one-to-many annotation in the
Product class:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product") |
|
|
Annotations are an important Java EE 5 usability enhancement that is implemented in GlassFish. Using annotations in the Java Persistence API simplifies the code for entity classes, enabling you to code these objects as Plain Old Java Objects (POJOs).
|
Annotations are an important Java EE 5 usability enhancement that is implemented in GlassFish. The Java Persistence API is only one of the technologies implemented in GlassFish that supports the use of annotations. In the CRUD application, annotations simplify the code for objects such as entity classes, enabling you to code these objects as Plain Old Java Objects (POJOs).
The
model directory also contains controller and converter classes. Each controller class invokes methods in Java Persistence API controller classes to perform operations for a corresponding entity class, such as creating and editing an instance of the entity class. Java Persistence API controller classes are in the
controller layer of the application. For example, the following method in the
ItemController class invokes the
create() method in the
ItemJpaController class to create an instance of the
Item class:
private ItemJpaController jpaController = null;
public String create() {
try {
jpaController.create(item);
JsfUtil.addSuccessMessage("Item was successfully created.");
} catch (Exception e) {
JsfUtil.ensureAddErrorMessage(e, "A persistence error occurred.");
return null;
}
return listSetup();
}
|
The converter classes use
JavaServer Faces technology (often referred to as JSF) to convert instances of the corresponding entity class to
String objects, or the reverse --
String objects to entity classes. For example, the following method in the
ItemConverter class converts an instance of the
Item class to a
String object:
public Object getAsObject(FacesContext facesContext, UIComponent component, String string) {
if (string == null || string.length() == 0) {
return null;
}
Long id = new Long(string);
ItemJpaController controller = (ItemJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "itemJpa");
return controller.findItem(id);
}
|
JavaServer Faces technology also plays an important role in the view layer of the application.
The
controller directory contains Java Persistence API controller classes. Each of these classes uses the Java Persistence API to handle operations for the corresponding entity class, such as creating and editing instances of the entity class. For example, here is part of the
create method in the
ItemJpaController that creates an instance of the
Item entity class:
public void create(Item item) throws PreexistingEntityException, RollbackFailureException, Exception {
EntityManager em = null;
try {
utx.begin();
em = getEntityManager();
Address address = item.getAddress();
if (address != null) {
address = em.getReference(address.getClass(), address.getId());
item.setAddress(address);
}
Product product = item.getProduct();
if (product != null) {
product = em.getReference(product.getClass(), product.getId());
item.setProduct(product);
}
em.persist(item);
if (address != null) {
address.getItemCollection().add(item);
address = em.merge(address);
}
if (product != null) {
product.getItemCollection().add(item);
product = em.merge(product);
}
utx.commit();
...
|
|
|
GlassFish implements Java EE web technologies such as JSP and JavaServer Faces technology that provide simple, consistent mechanisms for extending web applications beyond static web pages.
|
The view layer uses data from domain objects provided by the controller to generate a web page. The view is rendered in the application using JavaServer Pages (JSP) technology and JavaServer Faces technology. JSP enables the dynamic content required by the application, and JavaServer Faces technology provides UI components for the application. These are only two of a number of Java EE web technologies supported by GlassFish that provide simple, consistent mechanisms for extending web applications beyond static web pages.
If you navigate to the
web/product directory in the
petcatalog application, you'll see a file named
List.jsp. This file provides one example of how JSP and JavaServer Faces technology are used in the application.
List.jsp is the JSP page that displays the types of products in the catalog, as shown in
Figure 3.
Figure 3.
Catalog Products Page
Click the image to enlarge it and show an additional column. |
Here is part of the code in
List.jsp:
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<f:view>
<html>
...
<body>
<h:messages errorStyle="color: red" infoStyle="color: green" layout="table"/>
<h1>Catalog Products</h1>
...
<h:dataTable value="#{product.productItems}" var="item1" border="0" cellpadding="2" cellspacing="0" rowClasses="jsfcrud_odd_row,jsfcrud_even_row" rules="all" style="border:solid 1px"gt;
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value=" #{item1.name}"/>
</h:column>
...
|
The tags prefixed by
f or
h are JavaServer Faces technology tags. Notice especially the
dataTable tag. This tag is used to create a table and render it on the page. The tag is useful when you want to show a set of results in a table format. In an application that uses JavaServer Faces technology, the
UIData component, the superclass of
dataTable, supports binding to a collection of data objects. It does the work of iterating over each record in the data source -- in this case, the catalog. The HTML renderer for
dataTable displays the data as an HTML table.
The
value attribute of the
dataTable tag references the data to be included in the table. The
var attribute specifies a name that is used by the components within the
dataTable tag as an alias to the data referenced in the
value attribute. Here, the
value attribute points to a list of items in the
product table in the catalog. The
var attribute points to a single item in that list. As the
UIData component iterates through the list, each reference to
item1 points to the current item in the list.
Notice too that the name, description, photo, and category of each item -- as well as show, edit, and destroy action links -- are displayed with JavaServer Faces technology
column tags. The
column tags represent columns of data in a
UIData component. While the
UIData component iterates 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,
product.productItems, and displays the names, photos, and prices. Each time
UIData iterates through the list of items, it renders one cell in each column.
The
dataTable and
column tags use
facet tags to represent parts of the table that are not repeated or updated. These include headers, footers, and captions.
| |
|
|
A lot of the coding for the CRUD application is automatically generated by the NetBeans IDE.
|
At this point, you might think that the CRUD application is fairly complicated and requires a lot of coding. As you build the application, you'll see that a lot of the coding is automatically generated by the NetBeans IDE.
Here's how to build the application.
Figure 4.
MySQL Server Database in the Database List
|
|
|
The MySQL Connector/J JDBC Driver, which is necessary for communication between Java platforms and the MySQL database protocol, is included in the NetBeans IDE.
|
Figure 5.
MySQL Server Basic Properties
|
localhost as the default server host name and
3306 as the default server port number.
mysqld in the
bin folder of the MySQL installation directory.
mysqladmin in the
bin folder of the MySQL installation directory. If the command is
mysqladmin, in the Arguments field, type
-u root stop to grant root permissions for stopping the server. The Admin Properties tab should look similar to
Figure 6.
Figure 6.
MySQL Server Administration Properties
|
petcatalog database as follows:
petcatalog. This will open a New Database Connection dialog box. Click OK to accept the displayed settings.
petcatalog database in the list of drivers, as shown in
Figure 7.
| Figure 7.
Driver for the
petcatalog Database
|
catalog.sql file
and paste the contents into the SQL editor, as shown in
Figure 8.
Figure 8.
Creating Tables in the Database
|
petcatalog database in the Services window. You should see the database tables under the Tables node. You can expand a table node to see the table columns, indexes, and any foreign keys, as shown in
Figure 9.
Figure 9.
An Expanded Table Node
|
Figure 10.
Viewing the Contents of a Table
|
petcatalog in the Project name field and a project location in the Project Location field. Check the Set as Main Project checkbox. Click the Next button. This opens the Server and Settings page of the New Project window.
src directory to hold the Java source files for the project, a
web directory to hold the JSP and JavaServer Faces technology files for the project, and an
nbproject directory to hold the metadata and build-related files for the project.
images folder from the
web directory in the completed
petcatalog application to the
web directory in the web application that you are building. You should see images in the
web\images folder such as the African spurred tortoise shown in
Figure 11.
Figure 11.
African Spurred Tortoise
|
|
|
One of the powerful features of the NetBeans IDE is that it enables you to quickly create Java Persistence API entity classes from tables in a database.
|
petcatalog project node for the application and select New. Then select Entity Classes from Database. This opens the New Entity Classes from Database wizard.
jdbc/petcatalog in the JNDI Name field and select
jdbc:mysql://localhost:3306/petcatalog from the Database Connection drop-down list. Your entries should look like those in
Figure 12.
Figure 12.
Creating a Data Source
|
petcatalog database appear in the Available Tables listbox, as shown in
Figure 13.
Figure 13.
Selecting Tables to Generate Entity Classes
|
modelin the Package field. Make sure that the checkbox labeled Generate Named Query Annotations for Persistent Fields is selected. The Database Tables page should look as shown in
Figure 14.
Figure 14.
Specifying Tables and Entity Classes
|
petcatalog database. You can see this in the Projects tab of the IDE by expanding the Source Packages node for the
petcatalog project and then expanding the
model node. This is shown in
Figure 15.
Figure 15.
New Entities Generated from Database Tables
|
Address.java, the entity class for the
address table, the
@OneToMany annotation specifies a
MappedTo parameter value of
addressId. In this application, the value needs to be changed to
address. In
Item.java, the entity class for the
item table, the
@ManyToOne annotations specify the parameter
(optional = false). This specifies that a non-null relationship must always exist in the relationship. For this application, let's not make that restriction. You can either change the
@ManyToOne annotations to specify a parameter of
(optional = true) or not declare the
optional parameter because a value of
true is the default.
Address.java
:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "addressId") |
@OneToMany(cascade = CascadeType.ALL, mappedBy = "address") |
Category.java
:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "categoryId") |
@OneToMany(cascade = CascadeType.ALL, mappedBy = "category") |
Item.java
:
@JoinColumn(name = "address_id", referencedColumnName = "id") @ManyToOne(optional = false) private Address addressId; @JoinColumn(name = "product_id", referencedColumnName = "id") @ManyToOne(optional = false) private Product productId; |
@JoinColumn(name = "address_id", referencedColumnName = "id") @ManyToOne private Address address; @JoinColumn(name = "product_id", referencedColumnName = "id") @ManyToOne private Product product; |
public Address getAddressId() {
return addressId;
}
public void setAddressId(Address addressId) {
this.addressId = addressId;
}
public Product getProductId() {
return productId;
}
public void setProductId(Product productId) {
this.productId = productId;
}
|
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
|
Product.java
:
@ManyToOne(optional = false)
private Category categoryId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "productId"
|
@ManyToOne
private Category category;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product")
|
public Category getCategoryId() {
return categoryId;
}
public void setCategoryId(Category categoryId) {
this.categoryId = categoryId;
}
|
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
|
|
|
The NetBeans IDE enables you to easily generate JavaServer Faces technology pages, that is, JSP pages with JavaServer Faces technology components, from entity classes.
|
petcatalog project node in the Projects window and select New. Then select JSF Pages from Entity Classes. This opens the New JSF Pages from Entity Classes wizard, as shown in
Figure 16.
Figure 16.
New JSF Pages From Entity Classes
|
controller in the JPA Controller Package field and ensure that
model is specified in the JSF Classes Package field, as shown in
Figure 17.
Figure 17.
Identifying the Controller and Model
|
controller package and generates Java Persistence API controller classes in that package for each entity class in the
petcatalog project. The IDE also creates a
controller.exceptions package and generates in that package exception classes for entity-related exceptions.
model package. It also creates a
model.util package and generates a number of utility classes such as a JSF Expression Language resolver in that package .
petcatalog project to see the new classes. This is shown in
Figure 18.
Figure 18.
Entity and Controller Classes
|
petcatalog application.
faces-config.xml file in the XML editor as shown in
Figure 19, you'll see that the IDE inserted
<managed-bean> and
<converter> elements for each of the controller and converter classes. The IDE also inserted a
<navigation-rule> element for each JSP page, indicating the outcome that causes the application to navigate to that JSP page.
Figure 19.
The
faces-config.xml File
|
Detail.jsp,
Edit.jsp,
List.jsp, and
New.jsp. The IDE also modified the
welcomeJSF.jsp file by inserting links to each of the
List.jsp pages. The IDE also created a Script file,
jsfcrud.js, and a CSS file,
jsfcrud.css. The Script file is used primarily to handle Ajax-related actions if you selected the Ajax-enable generated pages checkbox in the New JSF Pages from Entity Classes wizard. The CSS file controls the style attributes, such as color and font, used in the web pages.
welcomeJSF.jsp page will display the heading "JavaServer Faces." You want it to display "Pet Catalog." In addition, the
Detail.jsp and
List.jsp pages in the entity classes folders do not currently display the exact set of columns to be displayed.
welcomeJSF.jsp page:
<title>JSP Page</title> <h1><h:outputText value="JavaServer Faces" /></h1> |
<title>Pet Catalog</title> <h1><h:outputText value="Pet Catalog" /></h1> |
Detail.jsp and
List.jsp pages in each of the entity class folders with their equivalents in the finished
petcatalog application to identify the required changes. For example, here are the changes to make to the
List.jsp file in the
Item folder:
<title>Listing Item Items</title>
<h1>Listing Item Items</h1>
<h:column>
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText value=" #{item1.id}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value=" #{item1.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:outputText value=" #{item1.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Imageurl"/>
</f:facet>
<h:outputText value=" #{item1.imageurl}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Imagethumburl"/>
</f:facet>
<h:outputText value=" #{item1.imagethumburl}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Price"/>
</f:facet>
<h:outputText value=" #{item1.price}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Address"/>
</f:facet>
<h:outputText value=" #{item1.address}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Product"/>
</f:facet>
<h:outputText value=" #{item1.product}"/>
</h:column>
|
<title>Pet Catalog Items</title>
<h1>Pet Catalog Items</h1>
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value=" #{item1.name}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Photo"/>
</f:facet>
<h:outputText value=" #{item1.imagethumburl}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Price"/>
</f:facet>
<h:outputText value=" #{item1.price}"/>
</h:column>
|
petcatalog project and then selecting Run. You can also click the Run Main Project (F6) icon
http://localhost:8080/petcatalog/ and displays the Pet Catalog welcome page as shown in
Figure 20.
Figure 20.
Pet Catalog Welcome Page
|
| |
GlassFish fully supports Java EE 5 web technologies, including dynamic web technologies such as JSP and JavaServer Faces technology. In addition, GlassFish has a built-in persistence manager, the Java Persistence API, and supports ease-of-use features such as annotations. These capabilities, combined with the simplicity of querying and manipulating MySQL databases, make it easy to build a web application with data persistence that accesses a MySQL database and deploy it on a GlassFish application server. The NetBeans IDE, which integrates MySQL and GlassFish, makes building these applications even easier.
In the next article in this series, you'll see how easy it is to create a web application that accesses a web service through GlassFish's support for the Metro web services stack and updates a MySQL database.
| |