A
Practical Introduction into Java Enterprise Edition 6 (with Sample
Application)
August 2, 2009 · Robert Söding
Preface
While in the past Java Enterprise Edition had a reputation of
being overly complex (while being rock-stable), developers'
productivity has greatly improved with Java EE 6 (and EE 5,
before). Even Rod Johnson, founder of the - much more agile -
Spring Framework, came out in support of Java EE 6, remarking that
"Java EE 6 gets it right".
This article introduces into Java EE 6, discussing basic and
new (and really cool) features of EJB (Enterprise Java Beans) 3.1,
JPA (Java Persistence API) 2.0, and JSF (JavaServer Faces) 2.0 from
a mostly practical and only partially didactical ("things to
remember") perspective.
The associated sample application should - hopefully - work
out-of-the-box for anyone importing it.
Studying the article and application is recommended for
developers with basic or intermediate skills in the technologies
covered.
Feedback is welcome and may be directed to .
Prerequisites
Java Version
The sample application has been developed using Sun Java
1.6.
Both versions offered at that site, Java EE 6
SDK Preview and Java EE 6 Web Profile SDK Preview,
should do for the sample application, however, the former contains
more features, in general.
When installing, keep a note of
GlassFish's installation path, as well notice the administrator
user name / password combination. This information is needed in the
step described in chapter Adding the GlassFish Server
Adapter.
Eclipse WTP (Web Tools Platform) provides
several means to support developing the presentation-side code of
JSF (JavaServer Faces). However, these features appear to be
specifically bound to JSF 1.1 and 1.2.
Most fortunately, however, this
article's sample application does provide the JSF 2.0 tag libraries
(even when the JSF 2.0 distribution still ships the 1.2 taglibs).
See chapter Facelet Tags Do Not
Have a Tag Library (TLD) Anymore for more information.
At the time of writing, Sun's GlassFish server probably is the
only application server supporting Java EE 6 out-of-the-box.
To add the GlassFish Server Adapter to the Eclipse IDE,
normally, one would complete the following steps:
Click Window --> Show View --> Other -->
Servers
In the Servers view, right-click, and click New
--> Server
In the New Server dialog, click Download
additional server adapters
In the Install New Extension dialog, select
GlassFish Java EE 5, Java EE 6. Complete this step by
clicking Next and Finish.
However, there is a common bug (with this
GlassFish version - using Eclipse 3.4 as well as 3.5), telling, "An
error occurred while collecting items to be installed" (the error
message is included to be potentially indexed by search
engines).
As a workaround, one can install the server adapter as
follows:
In Eclipse 3.5, click the menu Help --> Install New
Software
Select GlassFish Java EE 5, Java EE 6 and complete the
operation
The following image displays the corresponding dialog:
After having installed GlassFish via jMaki plugin, set up a
server adaptor in Eclipse by completing the following steps:
Click Window --> Show View --> Other -->
Servers
In the Servers view, right-click, and click New
--> Server
Select GlassFish v3 Java EE 6
Choose the Application Server Directory - which is the
folder glassfish within the folder you have chosen in the
step described in chapter Installing Java EE 6
and the GlassFish Server
Enter administrator ID and password - as chosen in the step
described in chapter Installing Java EE 6
and the GlassFish Server. Adapt the setting Use
Anonymous Connection for Admin Commands to your situation.
Leave the other settings as they come by default
Adding the Maven m2eclipse Plugin
Maven is a Java project management and build tool, including
management of dependant libraries. The m2eclipse plugin provides
graphical support for the Eclipse IDE.
Add Maven Integration for Eclipse (in Eclipse 3.5,
click the menu Help --> Install New Software, and add a
new update site).
There is a bug with the Maven plugin that
removes Eclipse's virtual Web Resources folder from web
projects. Thus, firstly, do not necessarily install the plugin into
your production copy of Eclipse, and secondly, please find the
project's web root as indicated in the image below:
In Eclipse, click File --> Import --> Maven
Projects and select the folder created when unzipping.
Running the Application
Start the Derby database by typing ...
sh $GLASSFISH_HOME/bin/asadmin start-database
... in a shell (asadmin.bat on Windows).
$GLASSFISH_HOME should be replaced by GlassFish's
actual install path.
In Eclipse, right-click the project's root node and select
Run As --> Run on Server. Choose the GlassFish server
previously set up or follow the Eclipse wizard to set it up.
A customer test account has been pre-configured with a user
name / password combination of customer /
password.
Use Cases in the Sample Application
There are two user roles in the sample application, customer
and vendor.
Customer Use Cases
A customer can perform actions that are described in the
following sections.
Common Use Cases
The following screenshot displays a region that is included in
almost any page:
A customer can ...
change the user interface language
login
register
when logged in, view a personal greeting
from satellite pages, navigate back to the home page
Use Cases at the Pizzas Page
The following screenshot displays the Pizzas page:
At the Pizzas page, a customer can ...
view the list of available pizzas
add pizzas to her shopping cart
change the quantity of selected pizzas
choose additional ingredients for the selected pizzas
view her selected additional ingredients per selected
pizza
remove a selected pizza from the cart
view the number of selected pizzas and the total amount
finally, place an order
after having placed an order, view a confirmation message
Use Cases at the Pizza Ingredients Page
The following screenshot displays the Pizza Ingredients
page:
At the Pizza Ingredients page, a customer can ...
view the list of selected ingredients per pizza
select additional ingredients
deselect previously chosen ingredients
Use Cases at the Edit Account Page
The following screenshot displays the Edit Account page:
At the Edit Account page, depending on her login status, a
customer can either create a new account or edit an existing one.
There, a customer can ...
provide a new user name / password combination
change an existing password
insert or update her address
in case of validation errors, review the data provided
Vendor Use Cases
When a customer places an order, the vendor will receive a
notification via the vendor's web service endpoint.
Data Access Layer
The application currently uses Apache Derby as DBMS (Database
Management System) as it ships with the GlassFish application
server by default. It has also been tested with PostgreSQL 8.3, and
should work with any other common DBMS, out-of-the-box.
To start the Derby database, in a shell, type:
$GLASSFISH_HOME/bin/asadmin start-database
$GLASSFISH_HOME should be replaced by the
installation path of the GlassFish distribution.
The data access layer defined by the Java EE 6 specification
is the Java Persistence API 2.0 (JPA), where
entities - plain old Java objects (POJOS) - are mapped to
the relational database tables. This kind of mapping is usually
referred to as Object Relation Mapping (in short,
ORM or O/RM).
Basically, these entities have getter and setter methods that
each correspond to a database table column or relation (a foreign
key).
Mappings can be configured either in XML files (i.e., in
persistence.xml) or inline, by Java annotations. - In the
sample application, annotations are used.
This article does not provide a conceptual or
even didactical view on Java EE 6' data access technologies. It is
rather meant to help the reader understand the usage of Java EE 6
technologies in the sample application's context.
Data Source Setup
In the /META-INF/persistence.xml file, the database
connection is defined.
It points to a data source with the JNDI name
"jdbc/__default". This is a pre-configured data source pointing to
an Apache Derby DBMS that ships with the GlassFish server.
Additional data sources can be set up within the GlassFish
administrative console (http://localhost:4848 by default), in the
section JDBC.
The database used by the sample application gets
created on application startup, and dropped on shutdown (search for
"create" and "drop" in the persistence.xml file). The
custom DatabaseInitializer class is used to populate
the database with sample data.
Entities
The entities (AKA domain or model objects)
used in the sample application are located in the
model and model.base Java packages.
The following class diagram shows their structure:
A Login represents a user name / password
combination, and it has-an associated
Customer.
The Login, in this case, also has a
repeatedPassord and a loggedIn property.
These are not persisted to the database (as indicated by a
@Transient annotation, see chapter Annotations Related to Java
Persistence). They are solely used for business flow
logic. - In another strategy, it might be regarded cleaner (more
cohesive) to use a wrapper on the Login class that
separates these concerns.
There is another issue of potential bad
design: The Login object is of a more common type than
the Customer it refers to. I.e., as the application
evolves, it could get a Vendor,
Administrator, etc. Thus, the design would be more
extensible when the Customer would refer to the
Login instead.
A Customerhas-a name and an
Adress. In this case, the Customer is
supposed to have one address only, so the Address can
be embedded (see @Embedded in chapter Annotations Related to Java
Persistence) into the Customer's database
table.
Again, it would be more extensible to define
an address in its own table.
An Adress has a number of well-known
properties.
A Pizza has a name and a price, and consists of a
number of Ingredients, which have a name.
The formattedPrice property, BTW,
is at the client-side layer by now ;-).
Not shown in the class diagram (and not related to the
database) is the PizzaLineItem wrapper, that,
additionally, has a quantity, and user-configurable, optional and
additional, Ingredients list.
All entities have an
id and name property. Thus, they derive
from the AbstractIdentifyable and
AbstractNameable types in the model.base
package. See chapter Generic
Data Access Objects for information on the intention of that
pattern.
Annotations Used in the Model Layer
There are two types of annotations used
on the entities: Annotations related to Java Persistence (JPA) (in
the javax.persistence namespace) and annotations
related to the Bean Validation Framework (in the
javax.validation.constraints namespace).
Annotations Related to Java Persistence
These annotations map the entities and their properties to
database tables, fields, relations (i.e., foreign keys) and other
objects (i.e., indexes).
First-off, every entity needs to be annotated with
@Entity, at the type level. By default, the
corresponding table name equals the type name. This can be changed
by using the @Entity's name attribute, or
by adding a @Table annotation.
By default, any Java property is mapped to a database table
field. The field name equals the Java property name. Using the
@Column annotation on a Java property, additional
definitions can be set, including the database column name,
nullability, or a unique constraint. Properties annotated
with @Transient are not mapped to database
columns.
Every entity needs to have a property annotated with
@Id, which maps to a table's primary key.
Primary keys in databases are usually auto-incremented, which is
expressed by the @GeneratedValue annotation on the
corresponding property.
Entities that do not map to their own database table (and also
are not annotated with @Entity) may be
@Embeddable into other entities (and, in consequence,
into the latters' corresponding tables), which, in turn, do embed
their dependencies by annotating the corresponding property with
@Embedded.
There are one-to-one, one-to-many,
many-to-many and many-to-onerelationships, most of them referring to Java
Collections. In the sample application, a
@OneToMany relation ist used.
See chapter Relations for more general
information.
Annotations Related to the Bean Validation Framework
This article's author's knowledge of Bean
Validation currently is shallow, so information on the usage of
this framework may be somewhat inaccurate in portions. See JSR 303:
Bean Validation for the specification.
The sample application uses Bean Validation annotations, along
with a JSF BeanValidator and the corresponding tag
f:validateBean to validate HTML form field values
against the constraints of a targeted backing bean.
Bean Validation annotations used in the sample application
include @NotNull (which is pretty useless in the
context of JSF form field validation), @Pattern (i.e.,
@Pattern(regexp = "[\\w-]+@([\\w-]+\\.)+[\\w-]+") for
validating an email address) (there would be an alternative,
corresponding, JSF tag, f:validateRegex), and
@Size (i.e. @Size(min = 5, max = 255))
(there would be an alternative, corresponding, JSF tag,
f:validateLength).
Note that Bean Validation constraints do not get
applied, automatically, i.e., when using JPA to persist an entity.
The Validation API needs to be invoked, explicitely.
Data Access Objects
Data Access Objects (DAOs) are used to retrieve, persist, or
delete, entities.
In the sample application, related classes are organized into
Java interfaces (in the packages dao.interfaces and
dao.interfaces.base) and (JPA) implementations (in
package dao.impl.jpa and
dao.impl.jpa.base).
Referring to the DAO layer via interfaces instead
of concrete implementations makes sense for the purpose of
interchanging the data access layer. In contrast, the entities
themselves are not guarded by interfaces in the sample application:
Semantically, they do act as interfaces, theirselves: They do not
have inline code, and if their definition should change, their
(potential) interfaces would need to change, too.
The DAOs in the sample application are
exposed as EJBs. See chapter Enterprise JavaBeans (EJBs) for
information on that aspect.
Generic Data Access Objects
This section is not specifically related to the
Java Persistence API (JPA), but to OR/M, in general.
Most common data access operations - retrieving, inserting,
updating and deleting instances - are based on the entities' id or
name property, solely, - or (find all) even based on no property at
all.
Of course, there are more complex cases, when the search
criteria comprise of other properties - potentially of other,
related, JOINed, entities. Nevertheless, there is a number of
common operations that apply to any entity. The following
code snippet shows a DAO base class:
public class GenericAbstractIdentifiableDaoImpl<T extends AbstractIdentifiable>
implements GenericAbstractIdentifiableDAO<T> {
@PersistenceContext
protected EntityManager entityManager;
protected Class<T> tClass;
public GenericAbstractIdentifiableDaoImpl(Class<T> clazz) {
tClass = clazz;
}
public void remove(T entity) {
entityManager.remove(entity);
}
public T get(long id) {
return entityManager.find(tClass, id);
}
public T save(T entity) {
return entityManager.merge(entity);
}
@SuppressWarnings("unchecked")
public List<T> getAll() {
return (List<T>) entityManager.createQuery(
"select x from " + tClass.getSimpleName() + " x")
.getResultList();
}
}
The above class handles common data access operations for all
entities that inherit from AbstractIdentifyable (which
has no more than an id property).
Obviously, this pattern is not directly related
to Java EE, but to data access, in general.
In the method annotated with
@SuppressWarnings("unchecked"), normally, we would use
the overloaded, generic, version of the
EntityManager.createQuery(.., Class<T>) method.
At runtime, however, when the javax.persistence-XXX.jar is
used that GlassFish provides, a NoSuchMethod exception
will be thrown (with the author's current version), indicating that
the API is not stable yet.
Data Access APIs
The data access APIs - as used in the sample application - are
pretty simple.
The EntityManager provides several methods,
including find(..), remove(..),
merge(..) and createQuery(..). With the
createQuery(..) method, the PQL (Persistence Query
Language) is used, which is quite similar to SQL.
For more information, see chapter 3.8, Query
API, chapter 4, Query Language and chapter 6,
Criteria API (where the latter is, BTW, overly complex
compared to other data access frameworks) of the JPA 2.0
specification.
Service Layer
Any business logic that - finally - relates the data model to
the (user interface) views may be regarded a Service Layer
module.
JSF managed beans, however, contain both business logic and
logic for controlling views' task flow. In more complex
applications, they would rather be assigned to the presentation
layer.
Enterprise JavaBeans (EJBs)
In the sample application, the Data Access Objects (DAOs) (in
the package dao.impl.jpa), along with their interfaces
(in the package dao.interfaces) are exposed as
stateless EJBs (Enterprise JavaBeans).
Development before version 3.0 has been unnecessarily complex
(i.e., compared to using the Spring Framework or Seam
Framework). EJB 3.1 further improves the handling by adding
features including those listed below:
EJBs don't need a declared interface anymore
EJBs can be simply dependency-injected into other (EJB or JSF)
beans, using the @EJB annotation
EJBs can now packaged directly into WAR files (before, EAR
packaging was mandantory)
There are singletons now and application startup and shutdown
callbacks
Additional features, i.e., an improved Timer and JMS API, are
not covered by this article
As mentioned, in the sample application, the DAOs are exposed
as EJBs. The following code snippet shows how to expose an EJB by
simply annotating a class with @Stateless:
@Stateless
public class PizzaDaoImpl extends GenericAbstractNameableDaoImpl<Pizza>
implements PizzaDAO {
}
While - as of EJB 3.1 - this is no more mandantory, the EJB
does implement an interface. That interface is annotated
with @Local:
@Local
public interface PizzaDAO extends GenericAbstractNameableDAO<Pizza> {
}
Programming against interfaces is - almost -
almost advisable, causing classes to be loosely
coupeled.
The interface - or implementation, alternatively - can now be
dependency-injected into other classes:
@EJB
private PizzaDAO pizzaDAO;
In the sample application, @EJB
annotations are used by the JSF managed beans, in the
facade package.
JavaServer Faces (JSF) Managed Beans
JSF managed beans act as controllers for JSF views (see
chapter Model-View-Controller (MVC) Pattern in my
article on the Spring Framework). Tasks that JSF managed
beans perform include ...
providing the views with model data
validating forms
deciding which view to display next
In the sample application, the JSF managed beans
are located in the facade package. Related classes are
located in the util.jsf package.
Most elements - except the navigation-rules - are
optional. Managed beans for example can now be defined via
annotations (as is done with the sample application).
First, there is a resource-bundle and a
message-bundle, as well as a
locale-config. See chapter Internationalization for more
information. The view-handler, in this case, is also
related to internationalization. See chapter Switching the Locale for a
discussion.
The phase-listener is currently not used in the
sample application, as its functionality is implemented by the view
handler. See chapter Switching the
Locale for more information on this specific functionality. See
chapter JavaServer Faces
Lifecycle for a discussion of lifecycle-related concepts.
There are no more
navigation-rule (see chapter Handling Views) and managed-bean
(see chapter Bean Declaration
and Scope) declarations in the sample application's
faces-config.xml as these settings can be configured less
verbose by using annotations.
Bean Declaration and Scope
JSF managed beans in the sample application - in the
facade package - are annotated as in the following
code snippet:
@ManagedBean@SessionScoped
public class PizzasBean {
...
The @ManagedBean optionally takes a
name parameter. By default, the bean name is set to
the class name, with a lower-case first letter.
There are different bean scopes (in the
javax.faces.bean package), corresponding to the
managed-bean-scope element in XML configuration.
"Scope" refers to the life span of a bean, in practice that means,
how long the bean can be used with the same state (particularly,
instance fields' values). The following scopes exist:
@NoneScoped
@ApplicationScoped
@SessionScoped
@ViewScoped
@RequestScoped
Managed beans can - reasonably - only
access other beans, whose life span is the same or longer as the
calling bean. Consider the above scopes list ordered: Only
@RequestScoped beans should access beans of all other
scopes.
There are also implications on built-in
objects (see chapter Implicit Objects Available with
JSF) that scoped managed beans can reasonably access. - I.e.,
it makes no sense letting an @ApplicationScoped bean
access request parameters. See chapter 5.3, The
Managed Bean Facility, in the JSF
2.0 specification for more information.
Providing Model Data to Views
Views access their backing beans' via bean getter and setter
methods. These can take or return Java objects of any type,
commonly, including primitives and their wrappers,
Collections and, to be used in tables, JSF's
DataModel.
Basically, there are two ways of implementing validation
functionality in JSF Java components: using validator methods or
implementing the Validator interface. In both cases, a
method with the following signature is implemented:
The ValidatorException is an unchecked
RuntimeException and does not actually need to be
declared. The FacesContext refers to the context in
which the current request gets processed, the
UIComponent the component to be validated, and the
Object the component's value, typically.
When the validator method finds that the value should be
rejected, it should set setValid(false) on the
component, optionally, setValidatorMessage("some
message") on a UIInput component, and finally,
throw a ValidatorException. The
ValidatorException may contain a
FacesMessage to be queued for processing.
For sample code, see
facade.CustomerBean and other beans in that
package.
JSF provides a number of built-in Validators (and
corresponding f:validate* tags). The following image
lists the built-in validators JSF provides:
The BindingValidator and
MethodBindingValidator listed above are used for more
internal purposes by JSF.
Handling Views
In JSF, there is the notion of actions - as
attributes of the h:commandButton and
h:commandLink tags as well as form-backing beans'
action methods. These methods must have the signature
public String methodName().
Actions return an outcome - as string - which will,
finally, be passed to a JSF NavigationHandler to
determine which view to render.
Traditionally, outcomes have been mapped
to view ids in the faces-config.xml file, using
navigation-case elements. Since JSF 2.0, it is
possible to directly return a view id, like in the action method in
the following code snippet:
public String editAccount() {
return "/editAccount.xhtml"; // instead of "editAccount"
}
When decorating JSF actions with the
f:ajax tag, action outcomes are considered not at
all.
The sample application, at first, has been
developed without using AJAX, at all. At a later stage, the views
have been amended to use AJAX. - When switching back to non-AJAX
navigation, all action outcomes would have to be reviewed.
Actions always result in an HTTP POST request. As a negative
side effect, the resulting view cannot be reloaded by the user
without re-sending data (which is annoying to the user and as well
jeopardizes the application's data integrity).
Appending the request parameter
faces-redirect=true to the outcome (i.e.,
somePage.xhtml?faces-redirect=true) will cause JSF to
conduct a redirect on the page, which, subsequently, can be
reloaded by the user as normal.
All action outcomes in the sample
application instruct a redirection.
Using string values to control business flows is
inherently unsafe. For instance, the target might not exist because
the value expression is misspelled. This problem exists with action
outcomes, as well as with session attributes, request parameters,
and message keys used for localization. Thus, there is a central
application.common.Constants class in the sample
application that holds these definitions in Java enums
to provide at least a minimum of secureness at compile time.
JavaServer Faces Lifecycle
See chapter 2, Request Processing
Lifecycle in the JSF
2.0 specification for a more in-depth discussion.
The following image (borrowed from the JSF
2.0 specification, thanks) shows the JSF Render and Execute
lifecycle:
In JSF, there is a component tree of UIComponent
subclasses (represented by the corresponding tag -
UIComponentELTag - before being rendered). The tree's
root component is a UIViewRoot.
In the Restore View phase, after loading - a
new or POSTed page -, this component tree gets built from the JSF
page elements, the components being initialized with the
corresponding tag attribute values.
In the Apply Request Values phase, any
request parameters are applied by recursively calling
processDecodes(FacesContext) on
UIViewRoot and its children, finally causing the
decode(..) method to be called on each
Renderer.
After the Apply Request Values
phase has finalized, a component's getValue() method
will not yet hold the value that matches the corresponding
request parameter. In contrast, getSubmittedValue()
will do.
At this stage, normally, the Process
Validations phase would begin, causing all components in the
view to be validated. At times, this is not desirable. I.e., the
sample application's "list pizzas" page contains two forms for
letting the user edit her shopping card and for letting the user
login, respectively. Logging in would not be possible when the
shopping cart's form contained errors.
Therefor, the login form's h:commandButton contains an
immediate="true" attribute, causing the related
component to bring registered listeners, converters and validators
forward, leaving unrelated components unaffected.
In the Process Validations phase - starting
at the component tree's root, again -, firstly,
Converters are used to convert the string represention
of the submitted value to the object representation of the model
(i.e., a date string to a Date object). Next, any
registered Validators or validator methods get
applied.
In case of conversion or validation errors, the next phases
will be skipped and the Render Response phase be
selected.
Converter error messages will be choked
if there is no h:messages tag on the view.
Conversion in the Process Validation phase means that
the components local values are set, but not the backing beans'
properties.
In the Update Model Values phase, in
contrast, the backing bean's properties are set. If
conversion errors occur in this phase, the next phase will be
skipped and the Render Response phase selected.
In the Invoke Application phase, registered
action methods get executed, i.e., h:commandButton
action="#{loginBean.login}".
In the Render Response phase, finally, the
UIComponent.encodeAll(FacesContext) method gets
called, being recursively called on any child component, and
causing the component to generate the (HTML) output.
JAX-WS WebService
When a customer places an order in the sample application, a
corresponding vendor is notified via a web service she
supplies.
This chapter is kept short, intentionally. For
further information, see chapter 11, Building Web Services with
JAX-WS, in The Java EE 6 Tutorial.
Web Service Endpoint
The following code snippet shows the vendor's web service
endpoint (in package vendor.service:
@Stateless@WebService(serviceName = "orderService")
@SOAPBinding(style = Style.RPC)
public class OrderServiceEndpoint {
@WebMethod(operationName = "add-order")
@WebResult(name = "order-placed")
public boolean addOrder(@WebParam(name = "order") Order order) {
System.out.println("processing order ...");
return true;
}
}
Only the @Stateless, @WebService,
and @WebMethod, annotations are mandantory.
At the client side, the JDK tool wsimport can be
used to generate supporting classes (into package
service.vendorclient) (shell script
WSIMPORT_ORDERSERVICE.sh):
The resulting OrderService class extends
javax.xml.ws.Service and contains hard-coded strings
referencing server properties, including the location of the WSDL
document. The endpoint's contract (in this case, a class, but that
could also be an interface) has been exported as an interface
(OrderServiceEndpoint). Of any other type that may be
passed through the web service (objects passed as method parameters
or method return values, as well as dependant objects of those) a
class stub has been exported - being annotated with interfaces from
the javax.xml.bind.annotation namespace.
Working Around wsimport Limitations
As the XML Binding annotations, that the wsimport
tool adds, are hard to maintain, manually, it has been decided to
keep the generated classes as a copy of the original ones. In other
words, both a model.Customer class and a
service.vendorclient.Customer class exist.
To "translate" the model.wrappers.Order, the
application is working with, to the
service.vendorclient.Order class, the
OrderServiceEndpoint expects, the - general purpose -
BeanAdapter class has been written, that translates
the object trees using Java reflection.
See the BeanAdapter's source code
for more information.
Furthermore, the wsimport tool, as already
indicated, queries the web service's resulting WSDL document to
generate stubs. The WSDL document, in turn, does not provide
information on bean setters not needed for processing the
corresponding web service method.
In the use case currently bespoken, setter methods in the
generated Order and PizzaLineItem classes
are missing.
Thus, wrappers around the aforementioned classes have been
written, adding these missing setter methods.
Presentation Layer
New features of JavaServer Faces (JSF) 2.0 include:
Annotations for managed
beans, alternatively to using the faces-config.xmlmanaged-bean tags
Facelets, an XHTML display technology,
replacing JSP
Facelet Tags Do Not Have a Tag Library (TLD) Anymore
In a simplified view, Facelets are the
h:outputText and f:validator (etc.) tags
defined in /META_INF/html_basic.tld and
/META_INF/jsf_core.tld, within jsf-impl.jar.
Because of the taglibs, there is code completion support in common
IDEs.
The above statement is not true. Actually, Facelets
do not use tag libraries (in the common TLD format), at
all. It only happens that Facelets technology does support
these tags.
The reason why, in your IDE, you get code
completion for the h:commandButton tag (that already
existed with JSF 1.2), but not for the new h:button
tag, is: The freaking JSF 2.0 JARs do ship the old taglibs.
So, the old tags are still supported, however there are new
tags, for which no taglibs exist.
I have not dived too deep into the code, however, apparently,
the tags are hard-coded in JSF Java code. I.e., the following code
snippet is from the HtmlLibrary:
package com.sun.faces.facelets.tag.jsf.html;
public final class HtmlLibrary extends AbstractHtmlLibrary {
public final static String Namespace = "http://java.sun.com/jsf/html";
public final static HtmlLibrary Instance = new HtmlLibrary();
public HtmlLibrary() {
super(Namespace);
this.addHtmlComponent("body", "javax.faces.Output",
"javax.faces.Body");
this.addHtmlComponent("button", "javax.faces.HtmlOutcomeTargetButton",
"javax.faces.Button");
this.addHtmlComponent("column", "javax.faces.Column", null);
this.addHtmlComponent("commandButton", "javax.faces.HtmlCommandButton",
"javax.faces.Button");
this.addHtmlComponent("commandLink", "javax.faces.HtmlCommandLink",
"javax.faces.Link");
...
Related tag libraries are listed in the following image:
Obviously, these classes are always created, and created
without any additional configuration (in class
ApplicationAssociate).
Anyways, it is too bad that there are no more
(matching) tag libraries. It is really hard to develop, and
impossible to validate, code in an IDE that way.
While Sun's current JSF 2.0 Reference
Implementation does ship the JSF 1.2 taglibs, the sample
application contains the *whoohoo* JSF 2.0 taglibs for JSF
HTML, JSF Core, and Composite Components.
These TLDs are located in the /WEB-INF/tld folder of the
sample application.
As for the ui (core Facelets)
portion of the issue, a corresponding TLD file (as of 2005) is also
contained. That one has been taken from here.
Facelets vs. JavaServer Pages (JSP)
Facelets are not JSPs - and not compiled to Servlets - but
representations of a JSF components tree. Such a components tree
might be represented by the following code snippet:
It is recommended to read the article Improving JSF by Dumping JSP that illustrates
the different - even concurrent - rendering strategies of JSF and
JSP.
While both technologies support compositing (by
including files), templating (by overwriting pre-defined
variables or areas) is supported by Facelets, only.
The syntax is quite simple. Model objects
are accessed by name. A generalized [] operator can be used to
access maps, lists, arrays of objects and properties of a JavaBeans
object; the operator can be nested arbitrarily. The . operator can
be used as a convenient shorthand for property access when the
property name follows the conventions of Java identifiers, but the
[] operator allows for more generalized access.
Relational comparisons are allowed using the
standard Java relational operators. Comparisons may be made against
other values, or against boolean (for equality comparisons only),
string, integer, or floating point literals. Arithmetic operators
can be used to compute integer and floating point values. Logical
operators are available.
The EL features a flexible architecture
where the resolution of model objects (and their associated
properties), functions, and variables are all performed through a
pluggable API, making the EL easily adaptable to various
environments.
The succeeding Unified Expression Language -
#{...} (actually, # and $
being exchangeable) - additionally accounts for the JavaServer
Faces nature, featuring
The above expression
#{pizzasBean.selectedPizza.name} gets evaluated
equally to #{pizzasBean[selectedPizza][name]}. The
latter notation, however, allows for evaluating nested statements,
i.e.,
#{i18n.languageName[sessionBean.currentLanguageCode]}.
It is possible to plug in custom ELResolvers,
which is regularly done by several Java frameworks. The following
image shows the ELResolvers used with JSF:
Additionally to managed bean properties (and methods),
several, basic, implicit objects can be accessed:
applicationScope, sessionScope, and
requestScope - Maps of attributes (called
parameters in this context)
facesContext - the current
FacesContext instance - and view - the
root UIComponent
initParam - Map of web.xmlcontext-parameters
cookie - Map of cookie values
header and headerValues,
param and paramValues - Maps
of HTTP header and HTTP request values, respectively. Using the
*Values variant is used to access properties that have
multiple values, i.e.,
paramValues.foodSelection[0]
Since JSF 2.0, there is a new resource implicit
object available. See chapter Handling
Resources for more information.
From within a composite component, there is an
additional cc implicit object available. There are the
attributes cc.attrs and cc.parent. See
chapter Composite User Interface
Component for more information.
Tag Libraries Supported by Facelets
JSF HTML Tag Library
The JSF HTML tag library contains components for all
UIComponent / HTML RenderKitRenderer combinations of the default renderkit.
The namespace is http://java.sun.com/jsf/html,
common prefix is h:.
Tag names (i.e., h:inputSecret) are normally
composed by a designator referring to a UIComponent,
followed by on referring to the Renderer. For
instance, a h:inputText can also be rendered as an
h:inputSecret, displaying asteriks (*) in place of the
string value (h:inputSecret being used as password
input text box).
There are
h:input* tags
h:select* tags to select one or multiple elements
from a list
a h:form tag, which encloses h:input*
and h:select* tags
h:commandButton and
h:commandLink
h:output* tags
h:panelGrid and h:dataTable,
rendering an HTML table, each having h:columns
structural HTML tags, including h:head,
h:body (both new with JSF 2.0), and
h:panelGrid
h:message and h:messages to render
FacesMessages
h:graphicImage
Common tag attributes include
id (will be generated if not specified)
the boolean immediate - causes converters and
validators that have registered for the related command action to
be already applied in the Apply Request phase of the
JSF lifecycle (in other
words, other parts of the form don't get evaluated in the context
of the current action even if they contain errors)
the boolean rendered
style and styleClass, related to CSS
decoration
value and binding, usually bound to
backing bean properties, the former editable
Introduced with JSF 2.0, the h:button and
h:link tags allow for bookmarkability. Other new tags
are h:outputScript and
h:outputStylesheet.
The new h:outputScript and
h:outputStylesheet tags have a library
attribute (as well as h:graphicImage has this
attribute), referring to a library of a resource.
See chapter Handling Resources for
more information.
other tags, including f:attribute (add an
attribute to a parent tag), f:param (add a parameter
to an URL - with h:commandLink - or parametrized text
- with h:outputFormat), f:loadBundle
(which is not necessary when defining a message-bundle
in web.xml), and f:verbatim (containing
children not being saved in the component tree)
Since JSF 2.0, there is the f:ajax tag, used to
execute server-side code and rendering the results at the client
side, without reloading the page. See chapter Adding AJAX Support for a
discussion.
The JSF UI tag library is used for templating. This is the
Facelets core tag library.
The namespace is
http://java.sun.com/jsf/facelets, common prefix is
ui:.
In templating there are relationship between
templates and template clients.
UI tags to be used in templates include
ui:component and ui:fragment - the
root of all child components in the component tree. Using
ui:component - in contrast to ui:fragment
-, any code outside that tag will not be rendered.
ui:insert - to define a replaceable
region. That region can overwritten by ui:define in a
template client. There is an optional attribute name.
Using the ui:insert tag without the
name attribute is quite useless.
UI tags to be used in template clients include
ui:composition and ui:decorate - a
set of components to be used as template client to a
template. Usally, these tags are used with the
template attribute, pointing to the location of a
template file. - Using ui:composition - in contrast to
ui:decorate -, any code outside that tag will
not be rendered.
ui:define - overwriting a named region
defined *sigh* by the template's ui:insert.
There is a mandantory attribute name.
UI tags to be used in both templating roles include
ui:debug - on pressure of a hotkey,
opening a window with debug information. There are the optional
attributes hotkey (defaulting to
Ctrl-Shift-D) and the boolean rendered.
ui:include - to include another file. There is the
mandantory attribute src.
ui:param - used with ui:include, to
pass parameters to the included page. There are the mandantory
attributes name and value.
ui:remove - to remove portions of the component,
to be used for testing purposes.
ui:repeat - to iterate over a list and render the
child components repeatedly (like with c:forEach).
There are the mandantory attributes value and
var.
There is also the jsfc attribute to
convert plain HTML tags to JSF UI components, i.e.,
Composite tags can be used to create custom tags from a
combination of other tags, faciliating component reuse.
The namespace is
http://java.sun.com/jsf/composite, common prefix is
composite:.
Composite user interface components are components made of the
common JSF tags (HTML Basic, JSF Core, etc.), being reusable within
a JSF application. Components development and use is accomplished
purely by using markup tags, Java code is not required. (Custom)
tag libraries are not involved.
At runtime, a composite component will be treated as an
instance of UIComponent.
JSF 2.0 has a new notion of resources, which
basically means regarding the $WEBAPP_ROOT/resources
folder as a "special place". In the sample application for example,
the composite components are placed within the
$WEBAPP_ROOT/resources/components.
Composite components consist of a
composite:interface and a
composite:implementation. In the following paragraphs
the changeLanguageLink component from the sample
application is discussed. That component displays a link that
allows a user for changing the UI language, where that link should
not be clickable when that language is already selected in
her session.
As always, the namespaces need to be declared:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">
<h:head>
<title>This will not be present in rendered output</title>
</h:head>
<h:body>
...
Note that in the the page (or component) that uses that
component, only the markup within
composite:implementation will be rendered.
The composite:interface in this case defines
three attributes:
<h:body>
components:changeLanguageLink
-------------------------------------------------------
Display a link that will change the UI language.
If that UI language is already selected (see attribute "clickable")
that link should not be clickable.
-------------------------------------------------------
<composite:interface>
<composite:attributename="languageDisplayName" required="true"
type="java.lang.String" shortDescription="Language display name."
targets="" />
<composite:attribute name="languageCode" required="true"
type="java.lang.String" shortDescription="2-char language code."
targets="" />
<composite:attribute name="clickable" required="true"
type="java.lang.Boolean"
shortDescription="Whether to display a link or just the text."
targets="" />
</composite:interface>
The composite:implementation consists of a
h:commandLink and h:outputText that are
selectively rendered:
Note the ccimplicit object that is
always available within a composite component's implementation
section. There is its attrs property, pointing to the
composite:attributes defined in the interface portion,
and also there is a parent property, to access the
parent UIComponent.
That's it for the component. - Using it - in
changeLanguagePanel.xhtml in the sample application -
starts with declaring the matching namespace:
The components part therein points to the
$WEBAPP_ROOT/resources/components folder. So, resource
folders can be accessed via matching namespaces. (The "components"
portion in xmlns:components of course could be any
other designator.)
The components itself are referenced as in the following code
snippet:
The component's properties match those declared by the
composite:interface's
composite:attributes.
There would be more to say on composite user
interface components. As they are UIComponents,
validators, converters and action listeners can be assigned to
them. See the article True Abstraction: Composite UI Components in
JSF 2.0 -- Part 2 for a sample of assigning an
f:actionListener to a
composite:actionSource.
The h:selectManyCheckbox' value holds a
Collection of selected items. This property
is read-write and will be written back to the backing bean.
The f:selectItems's value holds the list of
all available items.
Both tags' value attribute can take a
Collection, Map, or array
reference.
The behavior is similar to the
h:selectManyListbox and h:selectManyMenu
tag's behavior.
See chapter Rendering Components for
Selecting Multiple Values in The Java EE 6 Tutorial.
Validating Forms (using JSF Core and HTML Tags)
JSF provides a number of standard validators in the JSF Core Tag Library, including
f:validateBean
f:validateDoubleRange and
f:validateLongRange
f:validateLength
f:validateRegex
f:validateRequired
f:validator
f:validateBean relates to model objects' (or
entities') annotated properties the user interface component to be
validated is bound to. See chapter Annotations
Related to the Bean Validation Framework for more
information.
Firstly, that input component named password has a
maxlength attribute, which does not allow for
inserting more than the given number of characters - checked by the
web browser, JSF not being invoked.
There is an h:message container that displays any
potential conversion or validation error messages.
There is a required constraint and an associated
requiredMessage to be displayed when the matching
check fails.
The f:validateBeanValidator
reference is nested within the h:inputSecret tag. When
the matching check fails, the associated
validatorMessage will go into the
h:message container.
For more information see chapter Using the
Standard Validators in The Java EE 6 Tutorial.
Handling Resources
Since JSF 2.0, there is the notion of managed
resources.
A resource identifier consists of the following segments
(expressions in brackets - [] - being optional):
<ui:composite ...
xmlns:components="http://java.sun.com/jsf/composite/components"
... (where components in the namespace URI refers
to a resource library folder)
With resource, there is a new implicit object avaiable in
EL.
UIComponents and Renderers may
declare a @ResourceDependency annotation at the type
level, i.e., @ResourceDependency(library="corporate",
name="colorAndMedia.css").
It is commonly considered sensible to place
resources (including custom components) within the
/WEB-INF folder of a web application - where they cannot
be directly read from outside (then not having a certain context
needed, etc.). This intention has not been pursued with
JSF's resources concept.
Most actions that do not forward to other pages
are "ajaxified" in the sample application.
Using the f:ajax tag is fairly
straight-forward.
The f:ajax tag can either enclose other
components (i.e., a view, or group of related components) or be
nested as a child tag into a component (i.e., a
h:commandButton). If there are both outer and inner
tags, referring to the same actions, the outermost tag will be
executed, only.
The following code snippet shows one possible usage case. The
h:commandButton shall execute a single method and then
re-render a region.
The optional execute attribute takes a -
space-separated - list of component IDs to process.
@this is the default value and refers to the parent
component. Other pre-defined values are @all,
@form, and @none.
The - likewise - optional render attribute can
take the same values and is used to specify which components to
re-render after processing. The default is
@none.
The event attribute, too, is optional. The
default value is action for ActionSource
components and valueChange for
EditableValueHolder components. Other possible values
are those defined as attributes of the corresponding HTML elements,
however, onblur is blur in this
case.
render="@all" may not work with
multiple forms.
f:ajax' onerror
attribute - that takes the name of a JavaScript function - is not
well documented. I.e., it is unclear whether and how the underlying
error message can be accessed. Moreover, the JavaScript function
passed does not get called when an error occurs. - With or without
using the onerror attribute, errors are currently
swallowed in the sample application. - Although the
AjaxExceptionHandlerImpl does write out the error
information as partial response, that information is not going to
land in a h:messages sink.
Currently exceptions in the sample application's action methods are
handling by queuing a FacesMessage.
Normally, the string outcomes of action methods
determine which view to display next. In AJAX mode, the outcomes
are not evaluated at all.
There are more attributes on the
f:ajax tag. See chapter 10.4.1.1,
<f:ajax>, in the JavaServer Faces 2.0 specification for further
information.
Internationalization
See the blog article JSF and I18N for a basic introduction on
internationalization in JSF.
While by Expression Language, in the
views, messages of message-bundles defined in
faces-config.xml can be accessed, JSF's
MessageFactory - that creates
FacesMessages - will not use that resource.
To enable localized (or otherwise externalized) messages for the
JSF backend, a resource-bundle needs to be set up in
faces-config.xml (optionally, pointing to the same
.properties file).
Unfortunately, the .properties files are interpreted by a
java.util.ResourceBundle, which supposes them to be
ISO-8859-1-encoded (see PropertyResourceBundle's
JavaDoc). In applications that use Unicode (Java internally does,
and web applications should do, throughout), problems
arise whenever there are non-ASCII charactes.
Java's generic solution to this issue is the JDK's
native2ascii tool that converts any offending characters
to their Unicode representation, i.e., "ö" to "\u00F6". The sample
application comes with a script (NATIVE2ASCII.sh) that
converts all files matching a given pattern.
Alternatives include the .properties file editor that ships
with the JBoss Tools Eclipse plugins, as well as a Maven
plugin / goal and an Ant task.
Switching the Locale
For a glance of most of areas involved, see this article.
The Locale of the current JSF lifecycle can
(could) be changed by the following code:
This setting, however, does not get persisted across
requests.
Therefor, in the sample application, a custom
LocaleChangerViewHandler extends a JSF
ViewHandler, overwriting the Locale
calculateLocale(FacesContext context) method. In that
method, it first tries to derive a valid locale from a custom
request parameter, and if that is null, tries to locate a locale
that might have been stored in the HttpSession,
previously. Only if no locale is found by these methods, the super
class' locale is used.
Alternatively, a custom PhaseListener can be used
in a similar way.
In the sample application, the current
locale is determined by evaluation a request parameter and / or
HTTP session attribute. Alternatively, the locale could be
determined by portions of a view's URL, providing benefits
regarding bookmarkeability and search engines support.