Académique Documents
Professionnel Documents
Culture Documents
ENTERPRISE EDITION
http://www.supinfo.com
of
Java
http://www.supinfo.com
Enterprise
Edition
1. Course
1.1. Introduction
Do you need to set up distributed applications? Which more is, with a simple, powerful, and easily maintainable
architecture? EJB will certainly answer your waiting. Moreover, behind this name, there are several
technologies: one allowing managing the conversation on the network, another to supervise the data base... and
well of others still. The common point between them is that you externalize on an application server logic trade
of an application. Thus, as this part treated, you will have to write the "frontal" part of your application (see
architecture Java EE).
To help you to conceptualize this technology, we advise you to compare this technology with a brain, because
its the central place of the application. Lobes fill of the distinct functions: memories, reflexion, communication,
etc. the same way, there is EJB various parts which fill the different roles.
methods called checkInventoryLevel() and orderProduct(). By calling upon these methods, the distant customers
can reach the services of inventory provided by the application.
As we will see at the time of EJB practical application, it is necessary to have an application server in order to
lodge an application based on EJB. Indeed, this one must provide many mechanisms making it possible to
manage the authorities of EJB, to make secure, share the application on a grid of calculation... etc.
At the moment, well base ourselves only on the specifications of EJB. The specifications are texts produced by
expert groups from companies like Sun, IBM, Oracle... etc, in order to define bases common to all application
servers.
The application must be easy to update. To adapt to an increasingly significant number of users, you can need
to distribute the components of an application through multiple machines. The enterprise beans of an
application can operate on various machines, but also their localization will remain transparent for the
customers
The application must be transactional. EJB support the transactions, the mechanisms which control the access
convergent to the shared objects
4
http://www.supinfo.com
The application will have different kinds of customers. With only some lines of code, the distant customers
can easily locate EJB. These customers can be light, various and numerous.
Goal
Session
Entity
Message
Timer
Well have in this essential only about Beans of type Session, Message and Entity because they are usually used.
Those of Timer type will be seen in a more advanced course on EJB.
Simplification of the definition of the interfaces, suppression of a good number of necessary points in version
2.1 (more need to inherit a super interface or class)
Simplification of API for the access to the environment of Bean: definition by simple dependent injection
Introduction of the use of the annotations as Java who are used in the place of the descriptor of deployment
Entity Beans are simple POJOs annotated. The mapping relational-object can be declared in the form of
annotations.
Entity beans have greatly been improved during its third version. The specification defines that a bean written
with API EJB3 must be able to be a client with a component writes with the API 2.1 (2 & 1 also). That has of
course like objective to facilitate the migration of the existing applications or simply the use of those in the new
applications.
Knowing that EJB version 3 go back to semi-2006, it acts of a still young technology, which begins only its
phase of adoption with industry. EJB 2 is still used even if that is not a doubt that they will migrate gradually
towards the new specifications.
1.3. Concepts
We will approach, in this part, the whole of EJB concepts. We will explain the various types of existing EJB but
also their differences and their uses.
5
http://www.supinfo.com
In this architecture, EJB are located in the third "applicative logical". EJB implement logic trade of the
application (for the Session part) and represent an abstraction of the access to the data base (for the Entity part).
However, architecture EJB is before a whole evolutionary architecture. It is then possible to make evolve a
simple application EJB to an application directed Business To Business being connected towards other systems
of company.
In this architecture, EJB are located in the third "applicative logical". EJB implement logic trade of the
application (for the Session part) and represent an abstraction of the access to the data base (for the Entity part).
However, architecture EJB is before a whole evolutionary architecture. It is then possible to make evolve a
simple application EJB to an application directed Business To Business being connected towards other systems
of company.
The preceding diagram is the structure of an EJB server. Even if the container has the most important role, its
the server which switches the whole of the requests and manages the whole of the containers and services. The
server must manage, moreover, one whole of services of infrastructure common to the whole of the containers
or the services. The specification Java EE obliges the server to offer a service of directory JNDI and a service of
transaction. Of course, application servers generally provide other services as a data base integrated or the
security management. The goal is to facility the development, the deployment, etc... We can compare server
EJB as an orchestra. The role of this server is to be the leader. It is him which directs the whole of the services
and their cycle of life (starting, stop, pause...). Each part of the orchestra corresponds to a service (EJB,
Transaction, Base data...). They all are independent, but they work together to produce a common result.
1.3.1.1. EJB server
EJB server manages whole of the services systems for EJB, and also manages the containers which authorities
of EJB (called "beans") are carried out.
1.3.1.2. EJB container
A container, it is before all a "block box" which manages:
6
http://www.supinfo.com
The main role of container EJB is, however, to manage the cycle of life of the applications EJB which are
associated for him. It is him which deploys them, stops them and redeploys them, while managing their
conformity with the specifications of the server. It also makes it possible to control the components which are
with its load.
Even if the container is the central point of the execution of EJB, the developers do not have to be worried
some; it is a "block box" which, according to the specification, is carried out according to certain well defined
events.
To continue the metaphor of the orchestra, the container is the person who prepares the instruments, the
partitions and the environment necessary to the musicians (represented by EJB).
7
http://www.supinfo.com
application calls a method of a Bean Session, this one carries out the method and turns over possibly the result.
The execution is not worried what could be made before or what could be made afterwards. This type of
execution is typically the same one as that of protocol HTTP (mode offline).
Stateless Session Beans tend to being general in order to be able to be re-used in other contexts. The advantage
of the Stateless type is its capacity to be gone up in load. Indeed, several customers use the same authority of
EJB in a concurrent way.
In the case of Statefull, each customer is related to an authority of EJB (fig. 3.2). This type of Bean Session thus
consumes more memory that the Stateless type. Moreover, the work and the maintenance of association
constitute an important additional task for the container. It results from it a worse rise in load and sometimes
degradation from the performances when an application uses the Statefull type wrongly and without reason.
As we detailed at the beginning of this part, each authority of Statefull Session Bean is associated to a single
customer. This type of component maintains the state conversational with the customer, the variables of
authorities of this component are then related to the customer and their values preserved of a call of method at
another.
However, that doesnt mean that in any case that Statefull Session Bean is persistent. The server of application
can use a system of plug ("swap") for preoccupations with an optimization of memory (concept of passivation)
Statefull Session Bean is usually used to manage a process being carried out in several stages (purchases on a
going site, to reserve a travel, to send a newsletter...).
Let us take the example of a site of trade online. The basket can be modeled thanks to Statefull Session Bean. A
sale is carried out after several stages:
8
http://www.supinfo.com
Payment
transmitted any more by reference. It is then more possible only one customer modifies the same object of
another customer, and it is thus easier to delimit the various fields of safety.
On the other hand, the use of a distant sight has also disadvantages. The objects having to be "transportable"
remotely, the container owes serialize/unserialize these objects to transmit them via the network. It results from
it from the higher processing times compared to the local calls.
1.3.2.2.3. Web services visibility
The webservices are spread more and more on Internet, because they make it possible to use any service starting
from any language.
It is possible to specify the visibility of your EJB with the webservice type so that it can be used with the
manner of a webservice. However, this choice is restricted with EJB of the type Stateless Session Bean.
This technology misses maturity however and must for the moment to remain on the level of the concerns of
technological survey.
1.3.2.2.4. How to choose your connection?
The adoption of a local or distant sight decides at the time of the creation of EJB. It is completely possible
simultaneously to consider the use of these two sights, but it will be necessary to take into account the fact that
they are not completely equivalent (in particular on the level of safety with the passages by reference/valor).
The principal difference between these two types is undoubtedly the local access or the remote access. If the
customer application is carried out within the same virtual machine then the local sight certainly will be adapted
and conversely for the remote sight. The choice should not be generic, but must be made compared to the needs
for the application. It is however possible to support the local accesses while placing an intermediary (the
container Web) between EJB and the distant customer.
The sight webservice, as for it, is to be used when the customer is not written as Java or when you wish to
render your service most open possible. Typically, if you wish to give the possibility to your purchasers of
consulting your catalogue of products in any manner, it can be judicious to give them the access to such a Web
Service.
To compare this concept with an orchestra, the local side would be that of a spectator present in the room and
the remote side that of a spectator listening to on his radio the repeat broadcast placed at the disposal by the
orchestra. The side webservice would be that of an external TV channel, downloading the recording in the
complete concert, placed at the disposal by the orchestra (" Business to Business ").
1.3.2.3. When to use a Session Bean ?
Here some conditions concerning the use of the Beans Session in a system of company:
At any moment, only one customer has access to the authority of the Bean Session.
The state of Bean is not persistent, it exists only for one short duration (approximately a few hours).
The state of Bean represents the interaction between Bean and a particular customer.
Bean must store the information concerning the customer during the execution of the methods.
10
http://www.supinfo.com
Bean makes the connection between the customer and other components of the application, presenting a sight
simplified at the customer.
In slide, Bean controls the workflow of several Beans Company (it is thus a frontage).
To improve performances, you can choose to use Stateless Session Bean if it has one of these characteristics:
In only one call of method, Bean achieves a generic task for all the customers. For example, to send an email
confirms an order on line.
Bean recovers of a data base a unit of data in reading alone which are often used by the customers. Such
Bean, for example, could recover the lines of a table which represent the products which are on sale this
month.
The choice of the type of Bean Session is not always obvious. However, in a large majority of the cases, the
services offered are static, i.e. independent of the customer who calls them. In such cases, prefer the Stateless
type by defect.
11
http://www.supinfo.com
a supplier
consumer
messages
destinations
Thus, a supplieris the element has the load of the delivery of the messages between the various speakers. He
occupies himself of treating the sendings and making so that they are received.
A customer is an application or intervening component of application at the time of the exchanges. He sends or
receives the messages.
A message is, as its name indicates it, the element which will forward via a communication between the
customers. A supplier is always used as intermediary; one thus does not send them directly customer to another.
The destinations are objects configured on the level of the supplier which are at disposal of the customers and
who will be used by the latter for the sending and the reception of the messages. To schematize, one can say that
they are " letter boxes " in which the messages are placed while waiting for that a customer comes to claim
them.
1.3.3.3. When use it?
An important point in this architecture is that it allows a communication slightly coupled between the
customers: a customer is not worried identity of sound or his correspondents not of their possible state.
Moreover, this system can work in heterogeneous environment (C++ application, Java...).
1.3.3.4. Message transmission facility
JMS offers two models of transport: pointtopoint and publication/subscription. In a simple way, the pointtopoint
model represents a relation One to One between a message and a recipient whereas the model publication/
subscription is represented by a connection One to Many.
1.3.3.4.1. Peer to Peer (P2P)
The pointtopoint model makes it possible to connect the customer applications between them via a queue (tail).
It is exactly like the principle of a pile. The messages are sent and piled up. When a customer application
(consuming) is free, it then receives the piled up messages.
12
http://www.supinfo.com
This model can be assimilated to a hub (material physique of network). Each new message is broadcast towards
each registered consumer. The producer is independent owing to the fact that the message was received by the
consumers.
There are two types of subscription: temporary and durable. In the temporary case, the consumers receive the
messages as long as they are connected to the subject. In the case of a durable subscription, one obliges the
supplier to record the messages at the time of a disconnection, and to send them at the time of the new
connection of the consumer.
1.3.3.4.3. Which mode to choose?
A common problem for the architects is of knowing which model to use. Indeed, after some reflections, it
proves that it is possible to make the same thing whatever the model used. However, each of the two models has
interesting characteristics.
JMS provides an access on these two types of models bus to its development, certain companies used the pointtopoint model and others used the model of subscription.
In the majority of the cases, the selected model depends on the use which one wishes to make. The pointtopoint
model will be preferred when it be wished that only one milked recipient the message and to be sure that it is
treated. Conversely, the model of subscription is less restrictive and is used more particularly for the flow of
information which can be used by any customer.
13
http://www.supinfo.com
Entity Beans were created to simplify the management of the data on the level of an application, but also to
facilitate the safeguard in data base. More concretely, these Entity Beans enable you to deal with the persistence
of the data of your application in one or more data sources, while keeping the relations between those. These
components thus establish the relation between your application and your data bases. Contrary to the Beans
Session, the data of Entity Bean are preserved, even after the stop of the application.
The application data are typically: users, invoices, products, addresses... In the Java world, and more generally
in the world object, it is common to use classes for each type of objects used. One often speaks about trade
object or entity (English Entity) to represent the characteristics of these objects.
The connection between the data and the application by an object is called the mapping(to connect). The figure
above presents the mapping between the table User and User classifies it. One speaks about Mapping
Object/Relational when one connects, in this manner, a relational database with an Object application.
Warning
The use of Entity Beans makes it possible to represent an entity of the application and not functionality.
For example, User would be Entity Bean, but User Subscription would be a Bean Session; a user being
dedicated to remain persistent, whereas the inscription of the user is a service.
Contrary to the Beans Session, the data of Entity Beans generally have a long lifespan; they are recorded and
stored in systems of persistence (bases data).
The concept is older in EJB, but it starts to appear in the applications Java SE, with the appearance of container
lighter.
1.3.4.1. Persistence
While shortening, it is possible to say that the object to be made persistent, via Mapping Objet/ Relational,
corresponds to a table. Each property of this object is related to a field of the table. Each authority of this object
generally represents a recording of the table. However, it is possible that Entity Bean is distributed on several
tables.
Conversely, a table in a data base gathers a whole of fields. These fields represent either of information directly
related to the table, or of the bonds towards other tables. All this information is not therefore the direct
properties of the object in question.
Entity Bean follows the same principle and must all have a single identifier (key primary education). Entity
Bean AccountInfo, for example, can be identified starting from its account number accountId. This single
identifier makes it possible the application to find the data of Entity Bean associated.
Entity Bean User, for example, is characterized by properties such as: " name ", " first name ", " email ", "
telephone "... These properties are called: persistent fields. These properties are ampped (dependent) with the
fields of the associated table. During the execution of the program, container EJB automatically synchronizes
the state of these properties with the data base.
Like a table, Entity Bean has relational fields. However, a great difference exists. A relational field is
represented, in Entity Bean, by a property whose type is another Entity Bean (fig. 4.2). One speaks about
aggregation, in programming object. With the opposite, a table is related to another table by a foreign key (fig.
4.3).
14
http://www.supinfo.com
One To Many (with several) and Many To One (several with one):
A user can have several wallets whereas a wallet is held by only one user. The relation between Wallet and
User is of type Many To One and the relation between User and Wallet is of type One To Many.
In the application of example, a user has several wallets of actions. This connection is represented by a relation
One To Many.
1.3.4.4. Heritage
An entity can inherit another, knowing that an entity can as well be an abstract class (see the key word
abstract) that a concrete class (notabstract).
To illustrate this concept, we can see above the diagram of the entities of the application. Indeed, the class
FinancialProduct is abstract. Then, Stock and Jump inherit this class. Indeed, in our software of manager
15
http://www.supinfo.com
of financial products, those can as well be actions sides out of purse (English stock), or obligations (English
jump).
There are 3 strategies of mapping:
Strategy consisting in separating the specific fields from a class girl in a table separated compared to the table
containing the data of the table relationship. A junction is then made for instantiate the class girl.
We will study the advantages and the disadvantages of each one of these choices later, but retain for the moment
which that will have of importance only on the level of the performances.
1.3.4.5. Shared access
The entity beans can be divided by multiple customers. As the customers could want to change the same data, it
is important that the entity beans work inside transactions. Typically, the container of EJB provides the
management of transaction. In this case, you specify the attributes of the transaction in the descriptor of
deployment of the bean. You do not need to code the limits of the transaction in the bean; the container defines
the limits for you.
1.3.4.6. Persistence unit
Integral part of the framework Java EE 5, the unit of persistence is it limps black which makes it possible to
return persisting Entity Beans. More than one simple supplier of persistence, this one will make it possible the
developers to optimize their applications according to the management of their Entity Beans.
The unit of persistence is the key element of the management of Entity Beans within an application.
1.3.4.6.1. Database connection
The specification defines a file which gathers the whole of information of persistence. You must name this file:
persistence.xml and to place this file in repertory METAINF, with the root of the project.
This file will be read by container EJB at the time of the deployment of the application. The container then
creates an authority of the supplier of persistence with the required parameters.
Warning
You must name correctly the file persistence.xml. If the name does not correspond, the container will
not associate any context of persistence in the application.
A unit of persistence (Persistence Links) is characterized by the following points:
A supplier of persistence, because various manufacturers propose their implementation of the engine of
persistence. For JBoss it acts of Hibernate, and Oracle proposes TopLink.
A data source, like Oracle, PostGreSQL, MySQL, SQL Server... or Derby (a base of data functional, very
light, and written as Java).
1.3.4.7. Persistence Manager
16
http://www.supinfo.com
It acts of a device managing persistence between the data and the unit of persistence.
Entity Manager being an interface, the class of implementation is different according to the supplier used
(defined in the file persistence.xml with the beacon < provider >).
By defect, it is the container which will instantiate EntityManager and which will manage its cycle of life.
1.3.4.8. When to use Entity Beans?
Entity Beans are carried out in the container EJB, which brings to the developers of many services.
The principal service is, of course, the management of the persistence which manages the whole of the access to
the data in the memory or the data sources. The use of this service, and thus of Entity Beans, gets multiple
comparative advantages with the direct access to the data base. This solution brings a simple mechanism for the
access and the modification of the data. Indeed, it is easier, to modify the first name of a user within your
application, to call the method User.setFirstName() to carry out a rough request SQL. Moreover, Entity Beans
being standardized, your code is clear and more easily reusable (the definition of a user is found, for example, in
the majority of the applications).
Entity Bean being an EJB, it inherits the services such as the management of the transactions, of safety... as well
as many development tools optimized for their creation.
The client is the public which listens to the concert. The client made the request to return in the room and paid
his ticket with case (RMI), by a retailer (HTTP, Services Web...) or by small advertisements (JMS).
EJB being components server, a customer must obligatorily be set up to be able to communicate with those.
These customers can take several forms:
An applet
17
http://www.supinfo.com
A EJB
Note
You can also call a EJB in a page JSP. Nevertheless, this technique is misadvised because it does not
respect the good principles of the pattern MVC (Model Seen Controller). This model requires that the
access to the Model (service) be done since the Controller (a servlet for example) and not starting from
Sight (JSP).
Knowing that, EJB components are divided by directories. Then the customer locates them via the API JNDI
and their name JNDI. The deployed components are recorded in the directory of the server. Only JNDI pilot
(called service provider) changes one implementation to another.
The calls of distant methods are done by RMI (Remote Method Invocation) whereas the calls of local methods
are done directly in the JVM of the server.
The customer recovers a reference (implementing the interface trade) EJB which it wishes to use. This one can
then call the methods of the object recovered without worrying about the constraints of communication. Indeed,
the call of a method is automatically transmitted to the authority of EJB in the container (generally by a system
of proxy). This authority treats the method and turns over the result to the customer. The creation of the proxy is
with the load of the container and remains completely transparent for the customer.
1.4. Theory
In this part,we are going to study the various components that we must provide for a EJB. We will describe in a
generic way all the rules to be respected. We will observe these rules in the next chapter.
18
http://www.supinfo.com
It can work on a different machine and a different Java Virtual Machine (JVM) from the entreprise bean
which it reach
They must be deployed together, in the same EAR (equivalent of the JAR for the entreprise applications)
1.4.1.1.3. Client of the WebService type
The Services Web are spread more and more on Internet, because they allow to use any service independently of
the platform or the language.
It is possible to specify the visibility of your EJB with the webservice type so that it can be used as a Service
Web. However, this choice is restricted with the EJB of the type Stateless Session Bean.
1.4.1.1.4. To choose between a distant and local access
The main difference between these two types is undoubtedly the local access or the remote access. If the client
application is executed in the same virtual machine then the local view will be more adapted. The choice should
not be generic, but must for the needs of the application. It is however possible to support the local accesses
while placing an intermediary (the container Web) between the EJB and the distant customer.
Note
In Local mode, the parameters are passed by reference, and in Remote mode, they are passed by value
The webservice view is to be used when the client is not written in Java or when you wish to publish your
service most open possible. Typically, if you wish to give the possibility to your purchasers of consulting your
catalogue of products in any manner, it can be judicious to give them the access this Service Web.
To take again our comparison with an orchestra, the local view would be the spectator in the room and the
distant view, would be an spectator listening on his radio the repeat broadcast placed at the disposal by the
orchestra. The webservice view would be an external chain TV, downloading the recording in the complete
concert, placed at the disposal by the orchestra (Business to Business).
1.4.1.2. Bean Class (implementation)
The bean class of an EJB is the class of execution of the Bean Session. Indeed, it is in this class that you must
program logic trade. The whole of the methods declared in the interfaces (distant/local) will have to be
implemented in this class.
1.4.1.3. Annotations
The annotations are marks in the Java code, which make it possible to configure the application. In the case
of Stateless Bean Sessions, we will place @Stateless on the level of the class of implementation. For Stateful
Bean Session, it is about @Stateful. We will study them in detail when we write our own EJB.
1.4.1.4. Descriptors of deployment
19
http://www.supinfo.com
application.xml
being used to declare the whole of the modules integrated in a file .ear. You must specify your archive of
persistence in your file application.xml with the following lines:
[CODE:xml]<application xmlns="http://java.sun.com/xml/ns/j2ee" version="1.4"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://java.sun.com /xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">
<displayname>StockManager</displayname>
<description>Demo application</description>
<module>
<ejb>StockManagerEJB.jar</ejb>
</module>
<module>
<web>
<weburi>StockManagerWAR.war</weburi>
<contextroot>/stockmanager</contextroot>
</web>
</module>
</application>
ejb-jar.xml
configure the EJB in a module of a .jar file (optional if the descriptors of deployment related to the
applications servers are specific and depend only of them)
Sun Application Server uses the files sunapplication.xml (ear), sunejb.xml (jar), sunweb.xml (war).
JBoss uses the files jbossapplication.xml (ear), jboss.xml and jbosscmpjdbc.xml (jar), jbossweb.xml (war).
These files make it possible to use advanced functionalities of the server of applications which are not integrated
into the specifications.
Warning
The use of nonstandard functionalities (except specification) involves problems of portability of a
server of applications towards another
1.4.1.5. Assemblage (ou Packaging)
To deliver an application Java EE 5 you must create an enterprive archival file (EAR). It is a standard archival
file with the extension .ear which gathers a lots of modules EJB, Web, Application client... like showed the
following diagram (2.5).
20
http://www.supinfo.com
Each archival file (ear, war, jar or rar) contains a descriptor of deployment organized and structured on model
XML. This one makes it possible to define the parameters of deployment of an application (ear) or a module.
1.4.1.6. Deployment
The step of deployment for the developer is generally very simple. It is enough to place the packaged file in a
special repertory of the server of application or to use the administration of this one.
JBoss requires simply that the file is put in the folder deploy of the current configuration ($ {jboss.home}
/server/ {configuration} /deploy
Glassfish allows the deployment by the interface of administration Web or the administration command line or
by a folder autodeploy.
The task is however more difficult for the server of application. This one must read the contents of the archive,
scan the classes (in order to detect the annotated components), mapper Entity Bean at the database, to lay down
the policy of security (if it is declared), generate the classes (proxy,etc.) according to specificities of the
supplier.
We will more develop the subject of the servers of application in the final chapter
1.4.1.7. Client
Let us start by remember that the EJB are distributed objects. They thus are in a system of naming and relation
client/server. The client must carry out various steps:
To recover, with the URL, the stub one corresponding to the class Home of EJB (JNDI/RMI)
Syntax
Exemple
<name>Bean
AccountBean
EJB JAR
<name>JAR
AccountJAR
<name>Bean
AccountBean
Interface
<name>
Account
Abstract shema
<name>
Account
21
http://www.supinfo.com
In this example, the class is annotated with @Stateful in order to declare it as Stateful Session Bean. The
annotation @Remote makes it possible to specify the distant interfaces usable by clients.
1.4.2.2. Cycle of life
1.4.2.2.1. Stateless
Since a stateless session bean is never passivated, its cycle of life has only two states: does not exist and
ready for the call of methods trades:
@PostConstruct
The method on which this annotation is put is called when all the dependences of injection carried out by the
container and before the first call of the method trade.
@PreDestroy
The method on which this annotation is put is called at the time when the instance of Bean is destroyed
(during the suppression of Bean or with the stop of the application).
1.4.2.2.2. Stateful
The diagram below illustrates the differents steps for a Bean Session of the Stateful type during its life.
The session bean support the following callback event:
22
http://www.supinfo.com
Allows to specify a method which will be called by container EJB when Bean was inactive and it was
considered to pass this one in a serialized state. This method must be sure that the resources maintained in
instance are released or serializables. We speaks about passivation. The interest of this principle is to
release the memory employed by unutilised Stateful for the moment. The container then can serialize the
instance on an external medium (hard disk...).
Its the reverses of @PrePassivate. This annotation allow to specify the method which will be called by the
container when a Bean must be reactivated from its state of passivation. Bean will have to find an operational
state by recovering the resources released during passivation. We speaks about activation.
The passivated state is reserved for Stateful Session Beans because they are the only ones to share a state with
the customer. The life cycle of this component starts with the first call of a business method. The container then
creates an instance with the Class.newInstance method (). It injects the dependences and calls the methods
annotated with @PostConstruct. The great difference with the Stateless type is that Stateful integrates the
concept of passivation. The implementation of this concept is specific to the container and can vary from one
client to another. In all the cases, the container calls the methods annotated with @PrePassivate and
@PostActivate at the time of the passivation and the activation of the component.
The instance is removed when the customer calls a method annotated with @Remove or when the time assigned
for the session is exceeded (timeout).
1.4.2.3. Exemple
Here a very simple example of SessionBean (stateless type). The interface should of course be defined that our
bean will implement. Here we define simply the Remote interface which contains only one method: getHello ().
Moreover let us annotate it with the annotation @Remote in order to declare it like distant interface.
Here the code of the distant interface (Remote):
[CODE:java]import javax.ejb.Remote;
@Remote
public interface RemoteHello {
public String getHello();
}
The bean class implements the preceding interface and is annotated by @Stateless in order to declared it as
Session Bean Stateless.
Here the code of this class:
[CODE:java]import javax.ejb.Stateless;
23
http://www.supinfo.com
import com.society.testejb3.interfaces.RemoteHello;
@Stateless
public class HelloBean implements RemoteHello {
public String getHello() {
return "Hello world";
}
}
The RichClientServiceBean class defines a variable of instance commonService whose type is CommonService (the
business interface related to the EJB). With the annotation @EJB positioned on this property, the container
automatically injects an instance of the EJB (CommonServiceBean) when the instanciation of the EJB
RichClientServiceBean. I.e. it makes, in your place, JNDI research and the automatic initialization of the
dependence towards this EJB.
For certain more complex cases, the annotation @EJB admits attributes which allow to specify the localization
of the EJB.
beanName
Specify the name of the EJB (specified by the attribute name of the annotations @Stateless, @Stateful or in
the descriptor of deployment with the markup <ejbname>).
beanInterface
Specify the business interface that we wish to use. This attribute is mainly indicated when you use an
interface related of the business interface implemented by Bean. The default interface is used by the variable
which is subject to the injection
mappedBy
Warning
the annotation @EJB in a rich customer application (console or graph) is available only when this one
is launched in the Application Container Client (AAC). The installation of this type of application is
explained hereafter.
24
http://www.supinfo.com
API EJB Client. While JNDI is used to locate and reach the EJB in a transparent way, API EJB Client is a whole
of interfaces and classes which the developer uses to work with the beans.
We will see in this chapter several small examples of code allowing to locate/reach/work with the beans. You
will find a complete code in the chapter: EJB with practice. JNDI is a standard in java. It allow to standardize
connection to a service of directory, like does it JDBC for databases. There are many suppliers of directory, each
one of them must provide its own driver for its type of directory (LDAP, File system, EJB...).
1.4.3.1. Localization of bean with JNDI
Here an example allowing a client to recover a reference towards the Session Bean RichClientServiceBean.
[CODE:java]try {
Context ctx = new InitialContext();
ctx.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
ctx.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
ctx.put("java.naming.provider.url","127.0.0.1:1099");
// le nom JNDI par dfaut est
// "Nom du fichier EAR/Nom de la classe du bean/type accs : local/remote"
richClientService = (RichClientService)
ctx.lookup("StockManager/RichClientServiceBean/remote");
} catch (NamingException e) {
// gestion des erreurs
}
The object Context allow to initialize the parameters of connection to the directory to communicate with its.
Among the parameters of the example, we finds in particular the URL of the register, here with the 127.0.0.1
address. Thus when the server of application is not on the same machine that the client, this adresse IP should be
modified. Moreover, the first two parameters are specific to JBoss and the values correspond to objects located
in the bookshops client of this server.
The principle is the same for a client in a Web application, an application console or another EJB.
The other element to recover is the destination. It represents the place on which the application wishes to work
(sending or reception of message). We will see in the following part that there are two types of destinations:
topics and tails.
1.4.4.2. Connection and Session
The ConnectionFactory object makes it possible to create a connection with supplier JMS. Once connection
created, it is used to create a session.
[CODE:java]Connection cnx = connectionFactory.createConnection();
Session session = cnx.createSession(true, 0);
The session is used to group the operations of sendings and receptions of messages. In the majority of the cases,
a single session is sufficient. The creation of several sessions is useful only in the case of multithread
application which produce and receive messages at the same time. Indeed, the Session object is threadsafe, i.e.
its methods do not authorize the concurent access. Generally, the thread which creates the Session object uses
the producer and the consumer of this session.
25
http://www.supinfo.com
However, the specification indicates that the value of these arguments is ignored within container EJB. Indeed,
this one manages the transactions and the acknowledgements of delivery according to the parameters of
deployment.
Warning
Certain suppliers do not adhere completely to the specification and are not unaware of the parameters.
The good practices of development encourage to close connections once the work is completed.
[CODE:java]Connection cnx = connectionFactory.createConnection();
// [...]
cnx.close();
Each method takes in parameter the destination on which the object is connected.
1.4.4.4. Type of Message
In JMS, a message is a Java object made up of a heading and a body. The heading is composed of information
of destination, expiry, priority... The body of the message contains data being able to be various types:
Two other types of messages are available to treat array of bytes and the primitive types, which are
26
http://www.supinfo.com
We find the whole of the components quoted previously ( ConnectionFactory, Destination, Session ...).
The properties for the creation of Context JNDI are dependent on supplier JMS used. Here values used for
GlassFish:
[CODE:java]Hashtable hashtable = new Hashtable();
hashtable.put("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
hashtable.put("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
hashtable.put("java.naming.provider.url", "iiop://localhost:1050/");
Context jndiContext = new InitialContext(hashtable);
Note
These data are as an indication and can change according to the evolution of the various versions of
these server of application.
Here a summary table of the specific interfaces which can be used for a message of the pointto point type:
Table 1.3. Correspondence between the generic interfaces and those specific to the
pointtopoint transport
Generic
ConnectionFactory
QueueConnectionFactory
Destination
Queue
Session
QueueSession
MessageProducer
QueueSender
Here a summary table of the specific interfaces which can be used for a transport of the type subscription:
Table 1.4. Correspondence between the generic interfaces and those specific to the
transport by subscription
27
http://www.supinfo.com
Generic
Specific subscription
ConnectionFactory
TopicConnectionFactory
Connection
TopicConnection
Destination
Topic
Session
TopicSession
MessageProducer
TopicPublisher
In this example, we use the concept of listener avoiding any blocking of the application when the reception of a
message. For that, we must implement the MessageListener interface. The method onMessage (Message
message) is then called automatically at the time of the reception of a message
Warning
Do not forget to start connection with the method start() if not no message will be received.
By the same way as the producer, the consumer can use more specific interfaces for each model of transport.
Here a summary table of the specific interfaces which can be used for a transport of the pointto point type:
Table 1.5. Correspondence between the generic interfaces and those specific to the
pointtopoint transport
Generic
MessageConsumer
QueueReceiver
Here a summary table of the specific interfaces which can be used for a standard transport subscription:
Table 1.6. Correspondence between the generic interfaces and those specific to the
transport by subscription
Generic
Specific subscription
MessageConsumer
TopicSuscriber
28
http://www.supinfo.com
Warning
The attribute mappedName is not to use because it is not portable between the various server of
applications.
It is possible to recover the context of the MDB with the injection (annotation @Resource). The type of this
object is MessageDrivenContext. We detail his use further.
You can notice that the development of MDB is really simplified. Now ,we will study the various points of
details of these components.
1.4.5.2. MessageDrivenContext
As the Beans Session, the Message Driven Beans also have a context of execution of the
MessageDrivenContext type. It is similar to the SessionContext object explained in the part Session Bean.
Indeed, this interface inherits EJBContext and does not add any method.
1.4.5.3. Tolerance of the disconnection to a topic
The model of transport of the type subscription obliges the client applications to be connected to the subject
(topic) to receive the messages of this one. If a problem of connection occurs, the disconnected client lose the
messages transmitted during their disconnection.
However, as we had specified at the beginning of this chapter, the topic mode makes it possible to use a durable
subscription. The interest is to be able to receive the messages transmitted since the last disconnection.
The use of this kind of subscription must be specified on the level of the properties of the MDB. The property to
be used is subscriptionDurability. The values taken by this one are: Durable or NonDurable. By default, a
subscription is NonDurable.
[CODE:java]@MessageDriven(
activationConfig={
@ActivationConfigProperty(propertyName="subscriptionDurability",propertyValue="Durable")
}
)
29
http://www.supinfo.com
These selectors are based on the properties of the messages. Those are located in the heading of the message,
therefore depending of the contents, and are assigned by the creator of the message. All the types of message
integrate the methods of reading and writing of properties. Indeed, these methods are described in the interface
javax.jms.Message (superinterface defining a message). The types of properties are based on the Java primitives:
boolean, int, shorts, char...
To define the values of the properties it is necessary to use the methods setXxxProperty(Xxx) where Xxx represent
the types byte, float, String, Object... The methods getXxxProperty() are also proposed to recover the values. In the
following example, we define properties on which we will be able to define criteria of recovery.
[CODE:java]TextMessage message = session.createTextMessage();
message.setText("Les indices boursiers Paris ont gagn 4% aujourdhui") ;
message.setIntProperty("result",4);
message.setStringProperty("place","FR/Paris");
message.setStringProperty("senderType","StockSenderCorp");
Thanks to the properties which we have just defined, we can apply criteria of selection.
[CODE:java]@MessageDriven(activationConfig={
activationConfig= {
@ActivationConfigProperty(
propertyName = "messageSelector",
propertyValue = "place = 'FR/Paris' and result > 0")}
}
The system is based on the same concepts as the selection of the recordings with SQL. You can use operators
AND, OR, <, >... Other functionalities are possible. Let us take the case where we wish to treat in a MDB all the
messages having a relationship with the money markets Parisian, London, and francfortoise.
[CODE:java]place IN ('FR/Paris', 'UK/London', 'GER/Francfort')
We can also think to an alarm system, if the one day result is not located between +10% and 10%, to warn the
investor that this day is not an ordinary one.
[CODE:java]result NOT BETWEEN 10 AND 10
This functionality is useful when we wish to sort and distribute the messages located in the same destination
towards various MDB, in order to apply different treatments to them.
1.4.5.5. Acknowledgement
The disadvantage of the asynchronous treatment of messages is that there is no value of return to sender. It is
difficult for him to know if the message were indeed transmitted (when it wishes to know, of course). There are
various solutions to this problem.
The first consists in using acknowledgements of delivery, transparent mechanism managed by the supplier and
container MDB. It allow the client application to warn to the supplier that the message was received. Without
this acknowledgement of delivery, the message will continue to be sent.
This mechanism is based on the transactions on the level of the MDB. When this one is managed by the
30
http://www.supinfo.com
container, the acknowledgements just after the commit, or not if the transaction fails.
There are two modes of acknowledgement: Autoacknowledge and Dupsok acknowledge. The mode Autoacknowledge defines that the acknowledgement must be sent as soon as the message was transferred to the
MDB.
[CODE:java]@MessageDriven(
name="MyQueue",
mappedName = "queue/MyQueue",
activationConfig={
@ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Autoacknowledge")
}
)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyTopicListener implements MessageListener {
// ...
}
For Dupsokacknowledge, the acknowledgement is pushed back at one unspecified moment and the container
chooses then the moment when it has few tasks to treat to send it. That permit to save the resources. One can
however disadvise this last value because the supplier could believe that the message was not treated and would
decide to transmit it again (what could involve dysfunctions). Moreover, the cost of sending an
acknowledgement of delivery is negligible that it is in capacity of calculation or load network.
[CODE:java]@MessageDriven(
name="MyQueue",
mappedName = "queue/MyQueue",
activationConfig={
@ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Dupsokacknowledge")
}
)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyTopicListener implements MessageListener {
// ...
}
The second solution consists in specifying the JMSReplyTo value in the parameters of heading of the message.
That makes it possible to the recipient to send an answer towards the parameterized destination. As regards
shipper, we define the destination of answer in the following way:
[CODE:java]Destination replyDestination = context.lookup("queue/ReplyQueue");
message.setJMSReplyTo(replyDestination);
The MDB receiving the message can then recover this property and send in its turn a message.
[CODE:java]Destination replyDestination = message.getReplyTo();
This method differs from preceding because it allows a real information feedback concerning the treatment of
the message. This solution is typically used in our example of forwardings. The message of return alerts the
system when the object is prepared and dispatched. That could not have been implemented with the first
solution. This solution is also interesting to go up reports/ratios of errors in the business process.
1.4.5.6. MDB and JMS client
We directed our presentation MDB and JMS mainly towards the consumption of messages more than on the
production of these messages. There exists however many evolutions facilitating the development of the sending
of these messages.
Let us point out the various steps for sends of a message JMS:
31
http://www.supinfo.com
Opening of a connection
Creation of a session
Creation of a MessageProducer
Creation of a Message
Disconnection.
[CODE:java]public class StockAlertListener {
@Resource (mappedName = "ConnectionFactoryName")
private ConnectionFactory cnxFactory;
@Resource (mappedName = "queue/StockAlertQueue")
private Queue stockAlertQueue;
public void sendAlertMessage(String textAlert) {
Connection cnx = cnxFactory.createConnection();
Session session = cnx.createSession(true, 0);
MessageProducer producer = session.createProducer(stockAlertQueue);
TextMessage message = session.createTextMessage();
message.setText(textAlert);
producer.send(message);
cnx.close();
}
}
The first two steps of recovery are automated with the principle of injection. For that, we used the annotation
@Resource which defines name JNDI of ConnectionFactory and the Destination (of Queue type, here).
The code of the method sendAlertMessage (String textAlert) do not changes a lot compared to the implementation
code client presented before.
Note
The examples presented in this part can completely be implemented within a Bean Session exactly in
the same way.
1.4.5.7. Life cycle
Just like the Session Beans, a Message Driven Bean has a cycle of life managed by the container. This type of
component has only two states: Does not exist and ready Method.
32
http://www.supinfo.com
A MDB is in the state does not exist when there is not any instance in memory of this one (it was not
instanciate yet). A MDB is in the state Method ready when the instance is ready to be used. Once the
application started, the container creates a whole of instance of MDB of which the state is ready Method.
The following steps describe the changes of state which a MDB can undergo:
The instance is created when the container calls the method newInstance() in the class of the component
(generally with the starting of the application). Then, the container injects all the dependences of the object.
These dependences gather the injections annotated with @Resource, @EJB... then the container calls the
methods annotated with @PostConstruct. The instance is now ready to treat the messages delivered with the
listened destination: state ready Method.
When the container does not need more the instance, it calls the methods annotated with @PreDestroy. That
generally occurs when the reserve of instances becomes disproportionate compared to the needs or that the
application stops.
The interest of the method declared with @PostConstruct is to open a connection towards a service, like the
access to a directory of company or more simply to a file. The second method, @PreDestroy, are used to release
the resources used.
[CODE:java]private FileWriter fw = null;
@PostConstruct
private void connectToFile() {
try {
fw = new FileWriter(new File("save_topic.txt")) ;
} catch(Exception e) { ... }
}
@PreDestroy
private void unconnectToFile() {
try {
fw.close();
} catch(Exception e) { ... }
}
public void onMessage(Message message){
try{
//...
fw.flush();
} catch(IOException ex) {
ex.printStackTrace();
}
}
Notice that we forced the writing in the file at the end of the method onMessage() with FileWriter.flush(). The
interest is to be sure that the file is written. Indeed, for certain reasons, the methods of recall can not be called
33
http://www.supinfo.com
The class can as well inherit a class entity as a class not entity, and conversely.
The methods, the properties of the class and the class itself should not be final
If an instance of the entity have the possibility of being sent to a distant client, then the class must implement
java.io.Serializable. Indeed, RMI uses the (un)serialisation to pass the arguments between the client
application and the client.
The class must have a constructor without argument which can be public or protected. Nevertheless, the class
can have overrided manufacturers if the preceding condition is observed.
Note
The goal of the default constructor (without argument) is to simplify the instanciation of the class by
the container. The dynamic management of any constructor is a heavy task for this one without to be
useful. The solution was to define a constructor common to all Entity Bean: the default constructor.
EJB 3 Entity Beans support the heritage, associations and the polymorphic requests. These various concepts will
be explained throughout this chapter.
[CODE:java]@Entity
public class User {
//...
}
It is with the annotation @Entity that the container will be able to know which classes must be consider as Entity
Bean. This annotation is on the class and allow to define, the name of the entity with the attribute name.
The name used must be unique in an application. The default value used is the name of the class (User in the
preceding example). This name is used to represent the entity in the requests EJBQL, which we will see later; it
is the abstract diagram of Entity Bean.
[CODE:java]@Entity(name = "MyUser")
public class User {
//...
}
Entity Bean is related to a table in database. This connection is called the mapping. By default, Entity Bean User
is mapped on the table User. If for certain reasons, you want to map on another table, you will have to use the
annotation @Table. This annotation has various attributes:
34
http://www.supinfo.com
name (required): defines the name of the table to use for the mapping.
uniqueConstraints (optional): defines the constraints which will be placed on the table. This attribute is used
when the container generates the tables with the deployment and of anything the execution even entity does
not affect.
[CODE:java]@Entity
@Table(name = "XUser")
public class User {
//...
}
Note
The name table User is a reserved name in certain databases like PostGreSql, therefore we named it
in the example above XUser.
1.4.6.1.1. Persistent fields
A persistent field represents a property of Entity Bean. For an user entity, it will be for example: the name, the
first name, the address, the date of birth, the sex...
Any field (variable of instance) not static and not transient, of Entity Bean, is automatically considered as
persistent by the container.
A set of standard annotations is defined in EJB 3 specifications. We can consider two types of annotation related
to Mapping Objet/Relationnel :
Directly on a field
35
http://www.supinfo.com
fetch (FetchType.EAGER default) : determines whether the contents of the property must be in charge with the
request 1 (FetchType.LAZY) or at the time of the loading of the entity ( FetchType.EAGER).
optional (true default) : determines whether the property accepts or not the value " null". This attribute does not
function for the primitive types (which cannot be null).
Other annotations allow to specify the parameter setting of the columns (in the relational table) related to the
persistent properties. With those, it is then possible to specify type SQL, the length of the field, and many other
properties to be used for a persistent property.
The annotation @Column will be necessary to use to specify these parameter settings SQL. This one ondefine
default values declared by EJB 3 specification. This annotation can be used jointly with the preceding ones.
Here a description of the attributes, all optional, annotation @Column:
name: specify the name of the dependent column. The name of the property is used by default.
unique: specify if the property is a unique key or not (the value is unique in the table).
insertable: specify if the value must be included during the execution of request SQL INSERT. The default
value is true.
updatable: specify if the value must be updated during the execution of request SQL UPDATE. The default
value is true.
columnDefinition: specify the piece of code SQL for the definition of the column in the database. It is with
this attribute that we can specify the SQL type of the column.
table: specify the table used to contain the column. The default value is the principal table of the entity. This
length: specify the length that the data base must associate a field text. The length by defect is 255.
scale: specify the fixed number of figures after the decimal separator (in general the point). This attribute is
usable only for the decimal properties (float, double...). The default number of decimal is defined by the
database.
[CODE:java]@Column(updatable = true, name = "price", nullable = false, precision=5, scale=2)
public float getPrice() { return price; }
The many default settings of API Persistence offers an advantage to the developer. This one can quickly test its
entities. However, it should not remain there, but use the possibilities exposed about it here to optimize the
mapping between its entities and the database.
1.4.6.1.3. Primary Key
Entity Bean must have a field whose value is unique, known as primary key. This field allow to differentiate
each instance from the entity of the others. This primary key must be defined only once in all the hierarchy of
36
http://www.supinfo.com
Entity Bean.
There are two types of identifier: simple and composite. We explain, in this part the first case the second is more
rarely used.
1.4.6.1.3.1. Simple Identifier
We speaks about simple identifier when this one is composed by a single field whose type is simple. The
simple types are: primitive types (int, float, char...), a wrapper (For example Integer, Float, Double...), the String
type or Date (java.util.Date or java.sql.Date).
Note
In general, the decimal ones (a number with comma) are not used as a primary key. The entities using
this type for the primary key are likely not portable.
To specify with the container that a field is a primary key, it is necessary to annotate this one with @Id. In our
Entity Bean User, the primary key is assigned with the field id.
[CODE:java]@Entity
public class User implements Serializable {
private int id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO) // optionnel
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
The last example uses the annotation @GeneratedValue which allow to indicate to the container to use the best
solution for the generation of the primary key. There are four strategies of generation available: AUTO,
IDENTITY, SEQUENCE and TABLE. Those are defined by the enumeration javax.persistence.GenerationType.
IDENTITY type indicates to the supplier persistence assigning the value of the primary key by using the column
identity of the data base. Under MySQL, for example, the autogenerated primary key is marked with
AUTO_INCREMENT.
[CODE:java]@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() { /* ... */ }
The SEQUENCE type, as its name indicates it, obliges the supplier of persistence to use a sequence of the
database. This one can be declared on the class or the package with @SequenceGenerator and its attributes:
name (require): a unique name for the sequence which can be referred by one or more classes (according to
sequenceName (optional): defines the name of the sequence object of the database which will be used to
allocationSize (optional): defines the number used for the incrementing of the sequence when the supplier of
37
http://www.supinfo.com
Warning
The default value for the attribute allocationSize is 50
[CODE:java]@Entity
@SequenceGenerator(
name="SEQ_USER",
sequenceName="SEQ_USER"
)
public class User {
private int id;
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_USER")
public int getId() { return id; }
}
This type of generation is useful when the database offers a native system of sequence and that it is advised to
use it by the supplier of this one.
The TABLE type indicates to the supplier persistence using an additional table to generate the numerical primary
keys. This case of use is rarest.
[CODE:java]@Entity
@TableGenerator(
name="CONTACT_GEN",
table="GENERATOR_TABLE",
pkColumnName = "key",
valueColumnName = "hi",
pkColumnValue="id",
allocationSize=25
)
public class User {
private int id;
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="CONTACT_GEN")
public int getId() { return id; }
}
The annotation @TableGenerator allow to specify the parameters of creation of the additional table of
generation. Here the detail of the attributes of this one:
pkColumnName: specify the name of the column which identifies the primary key for which the key is
generated.
valueColumnName: specify the name of the column which contains the meter of the primary key.
allocationSize: the number of incrementings carried out when the supplier requests from the table a new value.
That allow to the supplier to use a system of cache in order not to require a new value of each request for new
a id.
The AUTO type indicates to the supplier persistence using the best strategy (between IDENTITY, TABLE,
38
http://www.supinfo.com
SEQUENCE) according to the data base used. The generator AUTO is the type preferred to have a portable
application.
Even if the automatic incrementing of the primary key relieves the developer, it must be used with parsimony.
Indeed, it is preferable to use a field of the entity rather than to add one of them, especially for the primary key.
For example, the entity Account can contain a property accountNumber which wants to be single by banking
logic. This property is then the best candidate for the primary key.
1.4.6.1.4. Simple Exemple
Here an example of simple POJO. It allow to define the structure of table " COUNTRY". It implements
java.io.Serializable in order to be able to be sent directly to a distant client (and thus to pass through a network).
The obligatory annotations are:
@Id which declares the primary key (generate allow to define the type of generation to be used for this key.
GeneratorType.AUTO defines a key incremented car).
The other annotations are not obligatory allow to specify more precisely various parameters:
@Basic defines the type of a persistent field (by defect, this type is used)
[CODE:java]@Entity
@Table(name = "COUNTRY")
public class Country implements Serializable {
private int id;
private String name;
public Country() {
}
@Id(generate = GeneratorType.AUTO)
@Basic
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1.4.6.2. Relations
We saw the definition of persistent property previously. It proves that an entity generally does not work only but
that it is connected to other entities. We speak then about relations between entities.
39
http://www.supinfo.com
To define a relational field within an entity, it is enough to create a property whose type is an entity (cardinality
1) or a whole of entity (cardinality N). A relation is known as oneway if only one part knows the relation. On
the other hand, it is described as bidirectional if the two parts know it.
For the relations where one side, at least, is multivalued ("One to Many", "Many to One", "Many to Many"), the
types of containers available are: java.util.Collection, java.util.Set, java.util.List, and java.util.Map.
They are these relations between entity EJB 3 which we detail in the next parts.
1.4.6.3. One to One
A relation "One to One" is used to bind two indissociable uniques entities. For example, a body has one heart, or
a person has only one indentity card. We will suppose, in our example, which a user User has one AccountInfo
account.
To associate two entities with this type of relation, the annotation @OneToOne should be used. This one takes
again the attributes of @Basic, considering previously, and proposes other optional attributes:
mappedBy: specify the field owner of the relation the case of a bidirectional relation.
targetEntity: specify the class of a target entity. This attribute is not used a lot because the annotation uses the
40
http://www.supinfo.com
[CODE:java]@Entity
public class User {
// ...
@OneToOne
@PrimaryKeyJoinColumn
public AccountInfo getAccountInfo() {
return accountInfo;
}
// ....
}
The second solution consists in using a foreign key on a side of the relation. However, it should be noted that
the column of this key must be marked like single in order to simulating correctly the relation One to One.
The annotation to use is @JoinColumn. It makes it possible to parameterize the column of joint to be used. The
example shows the bidirectional relation.
[CODE:java]@Entity
public class User {
// ...
@OneToOne
@JoinColumn(name="account_id", referencedColumnName="id")
public AccountInfo getAccountInfo() {
return accountInfo;
}
// ...
}
The
The attribute mappedBy declares that the side owner is that holding the property accountInfo. It is thus, here, the
User entity which holds the relation and thus has the capacity to bind a user on an account (the reverse being
impossible).
The last solution consists in using a table of association of the links between the two entities. However, the
multiplicity One to One is respected if and only if one unique constraint is defined on each foreign key. Even
if this case is rarer, it is possible to find it in an existing system which one wishes to make evolve.
[CODE:java]@Entity
public class User {
// ...
41
http://www.supinfo.com
@OneToOne
@JoinTable(name = "UserAccountInfo"
joinColumns = @JoinColumn(name="user_fk", unique=true),
inverseJoinColumns = @JoinColumns(name="accountinfo_fk",
unique=true)
)
public AccountInfo getAccountInfo() {
// ...
}
}
@Entity
public class AccountInfo {
//...
@OneToOne(mappedBy = "accountInfo")
public User getUser() {
// ...
}
}
This technique obliges to write more lines, without to increase the performances. It is however a considerable
case when we use of an existing data source. The annotation @JoinTable allow to configure the table of joint for
relation. Here a description of the attributes of this one:
joinColumns: specify the columns (together @JoinColumn) of the join table which refer the primary keys of
inverseJoinColumns: specify the columns (together @JoinColumn) of the joint table which refer the primary
uniqueConstraints: specify the unique constraints to place in the table. This attribute is used only if the
42
http://www.supinfo.com
bidirectional relation, the other side must use the annotation @OneToMany. The attributes of these two
annotations correspond to those of the annotation @OneToOne.
[CODE:java]@Entity
public class Portfolio {
//...
private User user;
@ManyToOne
@JoinColumn(name = "user_fk")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
@Entity
public class User implements Serializable {
//...
private Collection<Portfolio> portfolios;
@OneToMany(mappedBy = "user")
public Collection<Portfolio> getPortfolios() {
return portfolios;
}
public void setPortfolios(Collection<Portfolio> portfolios) {
this.portfolios = portfolios;
}
}
The entity Portfolio, being the part of the relation having a cardinality of 1, defines a User property user. On the
other hand, the entity User, part of the relation to cardinality N, declare a property multivalued
Collection<Portfolio> portfolios.
Notice the use of the credits which avoid defining the target entity in the definition of our relation. If you do not
wish to use them, then you will have to specify the target of your relation with the attribute targetEntity of the
annotation @OneToMany.
In the same way that with a relation One to One, it is possible to use a table of association. The way of
proceeding already having been explained previously, we will not return above.
1.4.6.5. Many To Many
The last type of relation available is Many to Many. It can be used to bind instances of two entities between
them. For example, between articles and categories. An article can be associated several categories (cardinality
N) and a category can gather several articles (cardinality m).
For that, it is enough to use multivalued properties on each side of the relation (if this one is bidirectional) and to
annotate them with @ManyToMany. In relational term, this relation imposes the use of a table of association.
[CODE:java]@Entity
public class User {
//...
private Collection<Hobby> hobbies;
@ManyToMany
@JoinTable(name = "USER_HOBBIES",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "hobby_id", referencedColumnName = "id")
43
http://www.supinfo.com
)
public Collection<Hobby> getHobbies() {
return hobbies;
}
public void setHobbies(Collection<Hobby> hobbies) {
this.hobbies = hobbies;
}
}
[CODE:java]@Entity
public class Hobby {
//...
private Collection<User> users;
@ManyToMany(mappedBy="hobbies")
public Collection<User> getUsers() {
return users;
}
public void setUsers(Collection<User> users) {
this.users = users;
}
}
Here, each User user has a whole of hobbies Hobby. And conversely, each hobby Hobby can be related to
several User users.
1.4.6.6. Cascading operations
The annotations @OneToOne, @OneToMany, @ManyToOne and @ManyToMany have the attribute cascade. This
one specifies the operations to be carried out in cascade. The cascade means that operation applied to an entity is
propagated with the relations of this one. For example, when a user is removed, its account is also.
There are 4 possible operations on the entities: addition, modification, suppression, reloading. These operations
are gathered in the CascadeType enumeration.
CascadeType.PERSIST: automate the recording of the entities related to the association marked during the
recording of the entity owner (method persist()).
CascadeType.MERGE: automate the recording of the modifications of the entities related to marked
association, during the recording of the modifications of the entity owner (method merge()).
CascadeType.REMOVE: automate the suppression of the entities related to marked association, during the
suppression of the entity owner (method remove()).
CascadeType.REFRESH: automate recharging (side bases data) entities related to marked association, during
the recharging of the entity owner (method refresh()).
Warning
According to the specification, the CascadeType.REMOVE type can be applied only to associations
"One to One" or "One to Many". The use of this type for other associations is not portable.
For example, on the relation between User and Portfolio, it is logical to record or remove the wallets when the
user is respectively recorded or removed. Here the code corresponding:
44
http://www.supinfo.com
[CODE:java]@OneToMany(
cascade = { CascadeType.REMOVE, CascadeType.PERSIST },
mappedBy = "user"
)
public Collection<Portfolio> getPortfolios() {
return portfolios;
}
In the same way, the relation One to One between User and AccountInfo obliges to safeguard, update and
destroy AccountInfo when these operations are carried out on the instanct of User corresponding. Here the code
corresponding:
[CODE:java]@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public AccountInfo getAccountInfo() {
return accountInfo;
}
The use of the mechanism of cascade is a real simplification for the developer. Indeed, it does not have to
manage the loops of suppression any more, modification... However, this tool must be used judiciously and with
parsimony. Indeed, a too important use of this mechanism can very quickly harm the performances of the
application.
1.4.6.6.1. Relationnal sample
This bean integrates a relation with another bean of the type: ManyToOne. This relation highlights a field of the
Country type.
The use of the relational annotations describes more in detail the relation:
45
http://www.supinfo.com
46
http://www.supinfo.com
The classes Order and Product are Entity Bean as we could describe them in the first parts.
Entity Bean OrderLine is the central point of the relation. It gets the two properties product and order
respectively related to Entity Bean Product and Order. Moreover, if an autogenerated unique primary key would
simplify the work of the developer, it is more judicious to work with a composite primary key. Indeed, the
regrouping of the primary keys of Product and Order are a good candidate for a primary key, since an order
cannot have the same product twice (in this case there it is enough to increment the quantity). We must then
create a OrderLinePk class to define this composite primary key. This one contains two properties orderId and
productId respectively representing the id of Order and Product.
The annotation @Embeddable declared below makes it possible to declare an entity in time that key composite
primary education.
[CODE:java]@Embeddable
public class OrderLinePk implements Serializable {
private static final long serialVersionUID = 1L;
private int orderId;
private int productId;
protected OrderLinePk() {
}
public OrderLinePk(int orderId, int productId) {
this.orderId = orderId;
this.productId = productId;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
47
http://www.supinfo.com
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public int hashCode() {
return orderId ^ productId;
}
public boolean equals(Object that) {
return (that instanceOf OrderLinkPk && orderId == productId);
}
}
Why we use the methods hashCode() and equals() above? They are used for calculter a value based on the
contents of the instance and to compare this one with others.
[CODE:java]@Entity
@IdClass(OrderLinePk.class)
public class OrderLine {
private Product product;
private Order order;
private int quantity;
public OrderLine() {
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@ManyToOne
@JoinColumn(name="orderId",
optional=false,
insertable=false,
updatable=false
)
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
@ManyToOne
@JoinColumn(name="productId",
optional=false,
insertable=false,
updatable=false
)
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
48
http://www.supinfo.com
@Id
public int getProductId() {
return getProduct().getId();
}
@Id
public int getOrderId() {
return getOrder().getId();
}
public void setOrderId(int orderId) {
getOrder().setId(orderId);
}
public void setProductId(int productId) {
getProduct().setId(productId);
}
}
We use the annotation @IdClass in order to specify the class of the primary key used. The getters getProductId()
and getOrderId() ondefine those of the OrderLinePk class. However, they respectively turn over the primary key
of the dependent order Order and that of the dependent product Product.
That raises a problem: the columns orderId and productId are already used to refer in the relations Many to One.
They are used at the same time as primary key and foreign key! The supplier of entities encounters a problem: to
assign the primary key and the foreign keys. To specify that we do not wish to assign the foreign keys
automatically, it is necessary to assign the value false to the attributes insertable and updatable of the annotation
@JoinColumn.
1.4.6.8. The heritage
Here 3 possible relational types of mappings:
A separation of the specific fields of a class girl in a separate table of the table relationship. A junction is then
made for instancier the class girl.
The examples of this part will use two Entity Bean: Bond and Stock which inherit both Entity Bean
FinancialProduct (abstract class).
Warning
Only one primary key must be defined in a hierarchy. Here, the primary key is in the root class
FinancialProduct.
49
http://www.supinfo.com
We will describe the possibilities of each one of these configurations, like their advantages and disadvantages.
The goal is to give you the elements enabling you to make the best choice according to various situations'.
For each case, we will study the annotations used and the generated relational structure.
1.4.6.8.1. A table for a hierarchie of class
In this strategy, all the classes of the hierarchy are mapped in same and unique table. The type of heritage used
is specified on the level of root Entity Bean by the annotation @Inheritance.
[CODE:java]@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="financialproduct_type",
discriminatorType=DiscriminatorType.STRING,
length=10
)
public abstract class FinancialProduct {
private int id;
//...
@Id
@GeneratedValue(strategy=GeneratorType.AUTO)
public int getId(){
return id;
}
//...
}
The only attribute of this annotation is strategy. It allow to specify the type of strategy to use with the
InheritanceType enumeration. To define a heritage using the strategy "unique table", it is the value
InheritanceType.SINGLE_TABLE which will be used.
However, this strategy requires a column allowing to differentiate the types of entity of the hierarchy. It is
necessary to use the annotation @DiscriminatorColumn to specify the details of this column. The attributes of this
annotation are:
discriminatorType: discriminator class to be used defined by the enumeration. Possible values are INTEGER,
CHAR and STRING.
length: size of the column for the discriminator at the root of the string.
columnDefinition: SQL fragment to be used for the declaration of the column (used during the generation of the
50
http://www.supinfo.com
Here the result at the database level (one table for two entities):
This strategy provides an important profit of performance, because no joint is carried out. However, the data use
more place because the whole of the columns is not always used (according to the type of recorded data). Here,
rate has a value null when the recording corresponds to a Stock Entity Bean.
1.4.6.8.2. One table by concrete class
The second strategy presented here is one table by concrete class. In this case, each concrete class Entity Bean
is related to its own table. That means that all the properties of the class (including the inherited properties) are
included in the table related to this entity.
Concretely, on our example, that means that the table FinancialProduct is not created nor not used. Entity Bean
Stock and Bond which inherit the FinancialProduct class are mapped respectively on the tables Stock and
Jump; each one of these tables integrating the properties defined in FinancialProduct.
To specify this strategy, it is necessary to specify the strategy defined by InheritanceType.TABLE_PER_CLASS
for the annotation @Inheritance.
[CODE:java]@Entity
@Inheritance (strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class FinancialProduct {
//...
}
The children classes Bond and Stock have simply to inherit FinancialProduct.
[CODE:java]@Entity
public class Stock extends FinancialProduct {
//...
51
http://www.supinfo.com
The major advantage of this configuration is during insertion because the addition is made only in one table. In
the same way, the selection of a concrete type (here Bond or Stock) is optimized. Indeed, SELECT relates to only
one table.
The main disadvantage is the heaviness of the polymorphic requests (selection on the whole of
FinancialProduct, for example). Indeed, the data base must use instruction SQL UNION in order to gather the
recordings located in the two tables.
The other disadvantage is the duplication of the columns in each table of Entity Bean; DataBase Administrators
never appreciate this kind of practice.
1.4.6.8.3. One table for a specific part of data
In this last strategy, the class root of the entities is represented by a table. Each children class is related to its
own separate table containing the specific properties of that one.
The link between the tables child and the table root is made with the primary keys. Indeed, the primary key of
the class girl is related to that of the class relationship. Thus, a recording of the table Stock or Bond whose
value of the primary key is 15, is related to a recording of the table FinancialProduct having value 15 for the
primary key.
The heritage is declared here with the InheritanceType.JOINED strategy.
[CODE:java]@Entity
@Inheritance (strategy=InheritanceType.JOINED)
public class FinancialProduct {
//...
}
The children classes Bond and Stock do not need another annotation only @Entity:
[CODE:java]@Entity
public class Bond extends FinancialProduct {
//...
}
[CODE:java]@Entity
public class Stock extends FinancialProduct {
//...
}
Here the result at the database level (place optimization tacken by the data):
52
http://www.supinfo.com
The advantage of this strategy is to have a clearly relational model. It is the ideal model for the dBa (not of
loss of memory because all the fields are used,...). But is also to provide a good support of polymorphism. Thus,
when the client wishes to recover all Entity Beans of the FinancialProduct type, generated request SQL will result
in a simple SELECT * FROM FinancialProduct....
However, the disadvantage is that it requires the use of several joints between the tables during recovery of data.
In the case of important hierarchies (great depth of the heritage) that can involve bad performances.
Warning
Toplink, the GlassFish presistence provider, doesn't supports the joined inheritance type.
1.4.6.8.4. Summary of the methods of mapping of the heritage
Here a summary of the advantages an disadvantages of the differents strategies:
SINGLE_TABLE
Advantages
TABLE_PER_CLASS
Disadvantages
Nonoptimal
of the data
JOINED
Integration of the data
close to the model object
Warning
You must name correctly the file persistence.xml. If the name does not match, the container will not
associate any context of persistence in the application.
Here the file persistence.xml, parameterized with Hibernate, used in our example:
[CODE:xml]<?xml version="1.0"?>
<persistence version="1.0">
<persistenceunit name="stockmanagerUP">
<jtadatasource>java:StockMainDS</jtadatasource>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
53
http://www.supinfo.com
The attribute name assigns a unique name to this unit in your application. The name is used to identify the
unit of persistence during its use with the annotations You will have to define several units of persistence if
you wish to use several data sources.
<jtadatasource> (01) : allows to define name JNDI for the data source to use. This one must be parameterized
<provider> (01) : allows to define the class of implementation of the supplier of persistence used in the
Oracle
Application
Server
p3.EntityManagerFactoryProvider
GlassFish
(Sun
Application
p3.EntityManagerFactoryProvider
uses
Server
TopLink:
9)
uses
TopLink:
oracle.toplink.essentials.ejb.cm
oracle.toplink.essentials.ejb.cm
KODO: kodo.persistence.PersistenceProviderImpl
<properties> (0N) : This mark allow you to configure the attributes of configuration of the supplier of
Class of dialect
org.hibernate.dialect.MySQLInnoDBDialect
54
http://www.supinfo.com
Database
Class of dialect
PostGreSQL
org.hibernate.dialect.PostgreSQLDialect
Oracle
org.hibernate.dialect.OracleDialect
SQL Server
org.hibernate.dialect.SQLServerDialect
HSQLDB
org.hibernate.dialect.HSQLDialect
Derby
org.hibernate.dialect.DerbyDialect
DB2
org.hibernate.dialect.DB2Dialect
Note
The access to the data is represented by the operations of addition, reading, modification and
suppression (defined by acronym CRUD: Create Read Update Delete). We generally implements
Pattern DAO to standardize these accesses
In the majority of the cases, the handling of the data with a container EJB is carried out by defining a Bean
Session in "facade".
Note
The design pattern "facade" provides a uniform interface of access to a whole of subsystems. The
application uses a whole of systems without really being aware of it and having the difficulties of use
which each system can induce.
This Beans Session reaches the context of persistence and can then work with the instances of Entity Beans,
with Entity Manager. It is what will be presented in the examples of the following parts.
1.4.8.1. Recovery of Entity Manager
It is possible to let the container give the responsability to inject an instance of Entity Manager at the time of
instanciation of the Bean Session. This method is undoubtedly simplest and most practical.
You must annotate the variable of instance of the type EntityManagerFactory or EntityManager with
@PersistenceContext. This annotation admits several attributes:
name: declare a name local referred on a unit of deployed persistence (local reference towards a unit of
persistence).
unitName: the name of the unit of persistence defines to use to inject EntityManager.
Here an example of use within the business application of wallet of actions. Here, EntityManagerFactory, related
to the unit of named persistence stockmanagerUP, is injected.
[CODE:java]@Stateless
@Local({CommonService.class})
public class CommonServiceBean implements CommonService {
@PersistenceContext(unitName="stockmanagerUP")
protected EntityManagerFactory emStockManagerFactory;
}
55
http://www.supinfo.com
The context of persistence is created at the same time as the Bean Session and has the same cycle of life as this
one. It is closed when the Bean Session is destroyed. During all the life of the Bean Session, the instance of
Entity Beans associated with the context of persistence are managed.
1.4.8.2. Persist an entity instance
To record an entity mean to insert it in the database. This operation results in the call of the method
EntityManager.persist(Object o). This one does not apply that to entities yet not recorded in the database.
To record an entity, you must first of all create an instance, then to affect its properties and its relationships to
the desired values, as you can do it with a Java object. Finally, it is enough to call you the method persist().
[CODE:java]User newUser = new User();
newUser.setFirstname("Cyril");
newUser.setEmail("popom@supinfo.com");
entityManager.persist(newUser);
Once this method called, the instance newUser becomes managed and its insertion in database is put in the queue
of Entity Manager. If the method persist() is called in a transaction, insertion in data base can be immediately
made or put in queue until the transaction finishes. That depends on the mode used for synchronization at the
data base.
It is not possible to call the method persist() apart from a transaction only if Entity Manager is of wide type
(EXTENDED). We will not have time to describe this operating mode more.
1.4.8.3. Recovery entities
Once the objects are saved, it is important to be able to recover them. There are two ways of recovering these
objects of the database. We will detail the recovery of objects starting from their primary key. The other solution
consists in working with requests EJBQL (see the following chapter).
Entity Manager proposes the following method:
[CODE:java]<T> T find(Class<T> entity, Object primaryKey)
The use of the generics avoids having to cast the return value. However differences exist.
The method find() return null if no entity is associated with the required primary key. It also initializes the basic
states of the lazyloading associated the properties.
[CODE:java]User user1 = entityManager.find(User.class, 1);
if (user1 == null) {
// ...
}
56
http://www.supinfo.com
In the preceding example, Entity Manager must be associated to the current transaction if it is wished that the
modifications be recorded. Those are really affected in database when the transaction finishes or that the method
flush() is called explicitly.
The other solution is to use when you wish to amalgamate the modifications made on an object detached
towards the context of persistence. It is the case, for example, when an entity leaves container EJB towards
another application (Web or rich Customer). You must use the method EntityManager.merge() in order to attach
the instance to the context of persistence. Let us imagine that a rich client calls the method findUser() following:
[CODE:java]@PersistenceContext
private EntityManager em;
public User findUser(int userId) {
return em.find(User.class, userId);
}
The context of persistence is closed after the execution of the method findUser() (we suppose that the Bean
Session uses management of the transactions). From there, returned instance is detached and the modifications
applied are not synchronized any more. If the customer application wishes to record the modifications made
locally, it must return the authority to the Bean Session.
[CODE:java]User returnedUser = adminService.findUser(2);
returnedUser.setEmail("nouvelleemail@supinfo.com");
adminService.updateUser(returnedUser);
In this case there, the method updateUser() must use EntityManager.merge() in order to attach the instance to
the context.
[CODE:java]@PersistenceContext
private EntityManager em;
public void updateUser(User user) {
User attachedUser = em.merge(user);
}
Various behaviors apply according to the context in which you call the method merge().
If Entity Manager does not contain an instance of the entity with the same primary key, then it creates a
complete copy of the object passed in argument and return it. This copy is then attached to the context of
persistence and the modifications made above are synchronized with the data base.
If Entity Manager holds already an instance of the entity having the same primary key, then the contents of the
parameter (user here) are copied in the attached instance.
In both cases, the parameter user of the method updateUser() remains detached and is not synchronized with the
database. This is why the developer must work with the instance turned over by the method merge() if it must
make other modifications on the entity.
1.4.8.5. Delete an instance
The EntityManager.remove() method is used to ask for the suppression of an entity of the database. We speak
57
http://www.supinfo.com
about "request" because the suppression is not effective immediately but only with the call of the method flush()
or at the closing of the context of persistence. Meanwhile, it is possible to cancel the suppression.
[CODE:java]@PersistenceContext
private EntityManager em;
public void removeUser(int userId) {
User userToRemove = em.find(userId);
em.remove(userToRemove);
}
The call to the method remove() detaches the entity of the context of persistence. To cancel this suppression (in
the same context of persistence) it is necessary to call the method persist() in order to attach the instance to the
context.
1.4.8.6. Reload entities
If you know that the instance of an entity does not reflect the values of the database , you can use the method
EntityManager.refresh() in order to reload the entity since the data base. This operation override all the
modifications which could be made to the entity.
[CODE:java]@PersistenceContext
private EntityManager em;
public void workOnUser(int userId) {
User user = em.find(userId);
user.setEmail("nomail@supinfo.com");
em.refresh(user);
}
In the last example, the email is not modified because of the call to the method refresh().
1.4.8.7. Synchronization with database
When you call the methods persist(), merge() or remove(), the changes are not synchronized immediately. This
synchronization is established automatically at the end of a transaction or when Entity Manager decides to
empty its queue. However, the developer can force synchronization by explicitly calling the method flush() of
Entity Manager.
Warning
flush() and commit() are two different operations! flush() sends requests SQL to the data sources whereas
commit() validates the transaction on the level of these sources.
58
http://www.supinfo.com
detached : mean that the instance is not associated any more with the persistent context from where it
comes. It is generally the case when the instance is initialized in the container then sent to another third
(presentation, Web...).
removed : mean that the instance has an identity associated with a persistent context but which it is
intended to be withdrawn from the data base.
The call of the methods related to the cycle of life is carried out by the container. We speaksabout callback
methods (methods of return). However, the study of these methods would leave of the framework of this
essence.
1.4.9.1. Detached entities
It is necessary to handle carefully the persistent fields marked by fetch=LAZY when Entity Bean is handled
apart from the context of persistence. Indeed, the marked collections lazy are not charged by the container.
But, in the case of a detached entity, if the collection were not charged in the container with EJB, it will be
impossible to reach the property apart from the container
To resolve that, we should be sure that all the properties of the entity used at the customer are initialized before
the object is detached from the context of persistence. For that, it is enough to ask the loading of the data when
the entity is still managed.
[CODE:java]User user = entityManager.find(User.class, userId);
user.getPortfolios().size();
user.getCVContent();
In this example, the loading of the collection is launched at the same time than the call to the method size() of
this one. In the same way, the loading of the property cvContent is carried out at the same time than the access
to this one.
Warning
The dynamic loading functions only on one managed entity !
Another solution consists in using requests EJBQL with explicit joints to recover the already initialized entities.
For that, it is necessary to use key word FETCH JOIN in the request (see the following chapter).
59
http://www.supinfo.com
1.5. EJB-QL
1.5.1. What EJBQL?
EJBQL (Undertaken JavaBean Query Language) is a specification of query language. Integrated into system
EJB, this query language has several advantages. First of all, its the portability which enables him to be used
with identical between the various versions of language SQL. Indeed, this one rests on an abstraction of
language SQL and is translated into true SQL at the time of its execution. In addition, EJBQL makes it
possible to use the objects of Entity Beans of the application directly in the requests, for more facility. In the
same way, the supplier of persistence will translate these requests into true SQL at the time of the execution.
The finality of this language is to some extent identical to that of the manager of persistence, which offers,
indeed, the possibility of carrying out requests of the INSERT type, UPDATE or DELETE.
By defect, the name of the class of Entity Bean will be used. For example, the diagram abstracted owing to lack
of Entity Bean, defined by the class To use, is To use.
The abstract term distinguishes this diagram from the physical diagram of the data base. In a relational data
base, the physical diagram corresponds to the structure of the tables and columns. In EJBQL you work with the
abstract diagrams and not with the name of the tables of your physical diagram, as represents it the following
diagram.
Note
We advise you to draw a sketch of the diagram abstracted before writing your requests.
In short, it should be retained that it acts of an abstract representation of Entity Bean, used by EJBQL to sail
between the persistent and relational properties.
60
http://www.supinfo.com
Language EJB-QL
Entity manager
API Query
This one turns over the whole of the authorities of Entity Bean User in a list. This one can then be traversed by a
foreach. The details of use of these elements are explained throughout this part.
According to the salesmen, it is possible to journalize (logs) requests SQL carried out by the manager of
persistence. For example, it is enough to add the property hibernate.show_sql with the value true if you use
the engine of Hibernate persistence. We will try to the maximum to illustrate the requests of example with their
correspondence SQL.
Warning
Correspondence SQL was carried out starting from tests carried out with the supplier Hibernate and a
data base MySQL.
SELECT: list Entity Beans and the properties turned over by the request.
FROM: Entity Beans defines used. Those must be declared via the expression HAVE.
WHERE: allows to apply search criteria. It is possible to specify Java types as well there having their
equivalent in the data bases (String, Integer, Double...) but also Entity Beans. In this last case, at the time of
the passage in native request, the criterion will apply to the primary key.
Of course, others could be added, as we will see it, but those are quasi systematically used to recover data.
The operator "." is used to sail between the properties and the relations of Entity Beans. For example, in order to
recover the user having a wallet of actions, one can represent navigation in the following way:
[CODE:sql]SELECT portfolio FROM Portfolio AS portfolio WHERE portfolio.user.id = 5
Correspondence in SQL :
[CODE:sql]select portfolio0_.id as id38 _, portfolio0_.name as name38 _, portfolio0.user_fk as user3_38 _ from Portfolio
portfolio0 _
where portfolio0_.user_fk = ?
It is guessed rather clearly that the use of "." is similar, in this example, to call the method Portfolio.getUser()
61
http://www.supinfo.com
Warning
Character of termination " ; "of requests SQL does not have to be used, under sorrow which
PersistanceException is launched.
1.5.4.1. Requests SELECT
The most used request is undoubtedly SELECT, the request of research. The instruction to be used is SELECT
like illustrates it the following example, where all the users are selected:
[CODE:sql]SELECT usr FROM User AS usr
[CODE:sql]select user0_.id as id21_, user0_.address_fk as
address8_21_, user0_.password as password21_, user0_.lastName as lastName21_,
user0_.firstName as firstName21_, user0_.login as login21_, user0_.sex as
sex21_, user0_.birthDate as birthDate21_ from XUser user0_
There are many similarities with language SQL. However, it should well be understood that the difference
comes owing to the fact that EJBQL is directed object. In the preceding example, To use corresponds to the
abstract diagram of Entity Bean User and usr corresponds to one alias (as in SQL).
The preceding example works directly with the User object, however it is sometimes practical to recover only
the id, or the name, or the first name... With EJB 3, it is possible to specify the properties which one wishes to
recover. It is enough to specify them in clause SELECT.
[CODE:sql]SELECT user.id, user.lastName FROM User AS user
[CODE:sql]select user0_.id as col_0_0_, user0_.firstName as col_1_0_ from XUser user0_
Clause DELETE of EJBQL does not support the suppression in cascade. Indeed, even if the relation is
configured with CascadeType.REMOVE or CascadeType.ALL, it will be necessary all the same to manually
write their withdrawal of the data base. In this request DELETE, we are likely to receive exceptions if Entity
Bean User would have relations. We have three possibilities then:
To use the possibilities of the data base and to manage the suppression cascade about it on the level of this
one.
In this last case, its possible to use the expression ON DELETE CASCADE for, for example, the data bases of
the type MySQL version 5 and the engine of InnoDB storage.
You will have, before, to check that the constraints of modifications in cascade were indeed applied. Here an
62
http://www.supinfo.com
In this way, at the time of the removal of a user, all his wallets, financial products, and information will be
automatically removed.
1.5.4.3. Clause WHERE
The permissions included in clause WHERE exist for the majority in a similar form with that which one can use
in SQL. Here a list summarizing those most usually used:
BETWEEN: conditional operator allowing to restrict the results according to an interval. The following
example selects all the users having an identifier of 1500 to 2000.
[CODE:sql]SELECT user FROM User AS user
WHERE user.id BETWEEN 1500 AND 2000
[CODE:sql]select user0_.id as id4_, user0_.address_fk as
address8_4_, user0_.password as password4_, user0_.lastName as lastName4_,
user0_.firstName as firstName4_, user0_.login as login4_, user0_.sex as
sex4_, user0_.birthDate as birthDate4_ from XUser user0_ where user0_.id
between ? and ?
LIKE: allows to compare the value of a field with a specified reason. The following request recovers, for
example, all the accounts having a first name starting with "Jean".
[CODE:sql]SELECT user FROM User AS user
WHERE user.firstName LIKE 'jean%'
[CODE:sql]select user0_.id as id4_, user0_.address_fk as
address8_4_, user0_.password as password4_, user0_.lastName as lastName4_,
user0_.firstName as firstName4_, user0_.login as login4_, user0_.sex as
sex4_, user0_.birthDate as birthDate4_ from XUser user0_ where
user0_.firstName like ?
The reason is built with two special characters. First is "%" and it is used for a number of indefinite natures.
The second, "_", represent only one character. If your character string would use really these two characters,
you have at your disposal the escape character "\". Here some examples of use:
firstname LIKE `_axime' will return the entries such as Maxime, Aaxime...
firstname LIKE ` Ma% ' will return the entries with Marc, Martine, Maxime...
misc LIKE `%\_%' will return the entries containing the character ` _ ', such as ` java_bean', ` java _ ', `_java'
or ` _ '
63
http://www.supinfo.com
IN: test a membership of a list of character strings. The following request recovers, for example, all the
contacts located in France, Spain, and Belgium
[CODE:sql]SELECT user FROM User AS user
WHERE user.address.country IN ('France', 'Spain', 'Belgium')
[CODE:sql]select user0_.id as id4_, user0_.address_fk as
address8_4_, user0_.password as password4_, user0_.lastName as lastName4_,
user0_.firstName as firstName4_, user0_.login as login4_, user0_.sex as
sex4_, user0_.birthDate as birthDate4_ from XUser user0_, Address address1_
where user0_.address_fk=address1_.id and (address1_.country in ('France' ,
'Espagne' , 'Belgique'))
IS NULL: test if a value is null. It acts of the default value defined when a field was not indicated. The
following request returns, for example, the recordings where the login was not specified.
[CODE:sql]SELECT user FROM User AS user
WHERE user.login IS NULL
[CODE:sql]select user0_.id as id21_, user0_.address_fk as
address8_21_, user0_.password as password21_, user0_.lastName as lastName21_,
user0_.firstName as firstName21_, user0_.login as login21_, user0_.sex as
sex21_, user0_.birthDate as birthDate21_ from XUser user0_ where user0_.login
is null
MEMBER OF: test the membership of an authority to a collection, just like the method contains() of the
interface java.util.Collection. The following example recovers the users having the wallet passed in parameter
(we will further see the passage of the parameters in this chapter).
[CODE:sql]SELECT user
FROM User AS user
WHERE ?1 MEMBER OF user.portfolios
[CODE:sql]select user0_.id as id21_, user0_.address_fk as
address8_21_, user0_.password as password21_, user0_.lastName as lastName21_,
user0_.firstName as firstName21_, user0_.login as login21_, user0_.sex as
sex21_, user0_.birthDate as birthDate21_ from XUser user0_ where ? in (select
portfolios1_.id from Portfolio portfolios1_ where
user0_.id=portfolios1_.user_fk)
EMPTY: test if a collection is empty. For example, we here will turn over the list of the users not having any
wallet of action.
[CODE:sql]SELECT user
FROM User AS user
WHERE user.portfolios IS EMPTY
[CODE:sql]select user0_.id as id21_, user0_.address_fk as
address8_21_, user0_.password as password21_, user0_.lastName as lastName21_,
user0_.firstName as firstName21_, user0_.login as login21_, user0_.sex as
sex21_, user0_.birthDate as birthDate21_ from XUser user0_ where not (exists
(select portfolios1_.id from Portfolio portfolios1_ where
user0_.id=portfolios1_.user_fk))
NOT: opposite the result of the condition. We can use it with preceding operators (NOT BETWEEN, NOT
LIKE, NOT IN, IS NOT NULL...).
1.5.4.4. Clause ORDER BY
Clause ORDER BY makes it possible to arrange by order the results of a request, starting from one or more
fields by using the alphanumeric order then alphabetical. To know exactly the implementation of this function, it
is necessary to refer to the handbook of the data base.
The following example turns over the list of the users ordered according to their identifier.
64
http://www.supinfo.com
[CODE:sql]SELECT user
FROM User AS user
ORDER BY user.id ASC
[CODE:sql]select user0_.id as id4_, user0_.address_fk as
address8_4_, user0_.password as password4_, user0_.lastName as lastName4_,
user0_.firstName as firstName4_, user0_.login as login4_, user0_.sex as
sex4_, user0_.birthDate as birthDate4_ from XUser user0_ order by user0_.id
Here what one could recover (according to the data of the database):
First name
Cyril
Frederic
Olivier
Maxime
10
Jean-Baptiste
Key word optional ASC means that the classification is made in an ascending way. To carry out it in a
downward way, DESC should be used (larger with smallest). By defect, it is ASC which is applied.
It is of course possible to combine these criteria. Thus, the following request posts the name by ascending order,
however when two users have the same name, the sorting is done then on the first name, in an increasing way,
then decreasing in the second example.
[CODE:sql]SELECT user
FROM User AS user
ORDER BY user.lastName, user.firstName ASC
[CODE:sql]select user0_.id as col_0_0_, user0_.firstName as
col_1_0_ from XUser user0_ order by user0_.lastName, user0_.firstName ASC
[CODE:sql]SELECT user
FROM User AS user
ORDER BY user.lastName ASC, user.firstName DESC
[CODE:sql]select user0_.id as col_0_0_, user0_.firstName as
col_1_0_ from XUser user0_ order by user0_.lastName ASC, user0_.firstName
DESC
count(): turn over the number of recordings sum(): turn over the sum of the values
65
http://www.supinfo.com
It is also possible to use clause GROUP BY to apply the function of aggregation to a batch of recordings. Here
an example allowing to turn over the number of wallets per user:
[CODE:sql]SELECT user.firstName, COUNT(user.portfolios) AS nbrPortfolio
FROM User AS user
GROUP BY user
[CODE:sql]select user0_.id as col_0_0_,
count(portfolios1_.id) as col_1_0_, user0_.id as id72_, user0_.address_fk as
address8_72_, user0_.password as password72_, user0_.lastName as lastName72_,
user0_.firstName as firstName72_, user0_.login as login72_, user0_.sex as
sex72_, user0_.birthDate as birthDate72_ from XUser user0_ left outer join
Portfolio portfolios1_ on user0_.id=portfolios1_.user_fk group by user0_.id
Table 1.10.
First name
Portfolios
Cyril
Frederic
Jean-Baptiste
Maxime
Olivier
The interest of GROUP BY in this request is to be able to apply function COUNT() to each user.
Clause HAVING makes it possible to specify criteria, as with clause WHERE, on a column generated by one of
the functions of aggregation. In the following example, we turn over only information when the number of
financial wallets is higher than 2.
[CODE:sql]SELECT user.firstName, COUNT(user.portfolios) AS nbrPortfolio
FROM User AS user
GROUP BY user.firstName
HAVING nbrPortfolio > 2
Note
In accordance with standards SQL, it is necessary to use clause HAVING in order to apply criteria to
the result of a function.
1.5.4.6. To handle the collections with the operator IN
The major part of the relations uses collections. The course of their entries is particularly interesting because
there does not exist in the relational logic of the SQL.
We have for that the operator IN. He must be placed in clause FROM, and makes it possible to declare alias for
the entries of a collection. For example, we can recover the whole of the wallets created, as follows:
[CODE:sql]SELECT portfolio
FROM User AS user, IN (user.portfolios) portfolio
[CODE:sql]select portfolio0_.id as id139_, portfolio0_.name
as name139_, portfolio0_.user_fk as user3_139_ from Portfolio portfolio0_
where portfolio0_.user_fk=?
We gather the elements contained in the collection user.porfolios, in alias " the portfolio ". So the request
gathers the wallets of all the users and the load.
The identifiers in clause FROM are declared of left on the right. When an identifier is declared, one can use it in
the following declarations. The following request recovers all the financial products had by the user having
66
http://www.supinfo.com
identifier 42.
[CODE:sql]SELECT fp
FROM User AS user,
IN (user.portfolios) portfolio,
IN (portfolio.financialProducts) fp
WHERE user.id = 42 AND fp.quantity > 10
[CODE:sql]select financialp2_.id as id104_,
financialp2_.quantity as quantity104_, financialp2_.buyValue as buyValue104_,
financialp2_.productName as productN5_104_, financialp2_.buyDate as
buyDate104_, financialp2_.portfolio_fk as portfolio10_104_,
financialp2_.monthDuration as monthDur7_104_, financialp2_.rate as rate104_,
financialp2_.price as price104_, financialp2_.financialproduct_type as
financia1_104_ from XUser user0_ inner join Portfolio portfolios1_ on
user0_.id=portfolios1_.user_fk inner join FINANCIALPRODUCT financialp2_ on
portfolios1_.id=financialp2_.portfolio_fk where user0_.id=?
This operator allows to directly select the elements of a relation and to work with. In the preceding example, the
request turns over FinancialProduct having a quantity higher than 10 of the user of id 42 (any confused wallet).
One second function, ELEMENTS, fulfills the same role, but is in clause SELECT. Here a request with a
similar result with the first example.
[CODE:sql]SELECT ELEMENTS(user.portfolios)
FROM User AS user
[CODE:sql]select portfolio0_.id as id139_3_, portfolio0_.name as name139_3_,
portfolio0_.user_fk as user3_139_3_, user1_.id as id140_0_, user1_.address_fk
as address8_140_0_, user1_.password as password140_0_, user1_.lastName as
lastName140_0_, user1_.firstName as firstName140_0_, user1_.login as
login140_0_, user1_.sex as sex140_0_, user1_.birthDate as birthDate140_0_,
address2_.id as id143_1_, address2_.country as country143_1_, address2_.city
as city143_1_, address2_.numero as numero143_1_, address2_.street as
street143_1_, address2_.zipCode as zipCode143_1_, accountinf3_.id as
id142_2_, accountinf3_.accountId as accountId142_2_, accountinf3_.cardNumber
as cardNumber142_2_, accountinf3_.amount as amount142_2_ from Portfolio
portfolio0_ left outer join XUser user1_ on portfolio0_.user_fk=user1_.id
left outer join Address address2_ on user1_.address_fk=address2_.id left
outer join AccountInfo accountinf3_ on user1_.id=accountinf3_.id where
portfolio0_.id=?
1.5.4.7. Joints
The joints make it possible to handle the relations between the entities. We will see that the functionalities
available are multiple and will be able to adapt to many needs. To illustrate this declaration, we present the
recovery of the wallets of actions, had by a user, various manners.
By using the style thta, with the relation between primary and key keys foreign:
[CODE:sql]SELECT user.firstName, ai.cardNumber
FROM User AS user, AccountInfo AS ai
WHERE u.accountInfo.id = ai.id
[CODE:sql]select user0_.firstName as col_0_0_,
accountinf1_.cardNumber as col_2_0_ from XUser user0_, AccountInfo
accountinf1_ where user0_.id=accountinf1_.id
67
http://www.supinfo.com
Card number
Cyril
1111-2222-3333-4444
Ophlie
2222-3333-4444-5555
The turned over results are the same ones for each request with some exceptions. Indeed, the operation of the
joints is subtle. When a User entity does not have a relationship to the AccountInfo entity, the recording will
not be turned over !
1.5.4.7.1. LEFT JOIN
In order to return the recordings of the Account entity, even if they do not have a relation, it is necessary to carry
out a joint known as "open". For that, one uses the instructions LEFT OUTER JOIN or RIGHT OUTER JOIN,
also existing in SQL.
In EJBQL, the expression LEFT JOIN allows systematically to include the first entity in the result of the
request. RIGHT JOIN, as for it, adds the results of the second entity.
Note
Instruction OUTER, used in SQL, became optional.
The following example uses an open joint. The results are then different.
[CODE:sql]SELECT user.firstName, user.lastName, ai.cardNumber
FROM User AS user
LEFT JOIN user.accountInfo AS ai
Card number
Cyril
1111-2222-3333-4444
Maxime
2222-3333-4444-5555
Jean-Baptiste
NULL
Indeed, the request from now on took into account the third recording, which does not have a relation with
AccountInfo. This request carries out a "joint open on the left". Here its correspondence in SQL:
[CODE:sql]select user0_.firstName as col_0_0_, user0_.lastName as col_1_0_,
accountinf1_.cardNumber as col_2_0_
from User user0_
left outer join AccountInfo accountinf1_ on
user0_.accountinfo_fk=accountinf1_.id
68
http://www.supinfo.com
The preceding request turns over the whole of the wallets created whatever the user. It is however simpler to use
the operator IN. Here correspondence using IN:
[CODE:sql]SELECT p FROM User u, IN(u.portfolios) p
This example charges the user of id 1 and initializes its wallets and the associated financial products. That poses
problems of performances however. Indeed, the engine of persistence must carry out a request with line 2 then
for each loading of the associated financial products (line 5). This one operates N+1 requests then (N being the
number of wallet).
To optimize that, it is necessary to use a request EJBQL with a joint of the type FETCH.
[CODE:sql]SELECT U FROM To use U INNER JOIN FETCH u.portfolio p LEFT JOIN FETCH
p.financalProducts
[CODE:sql]select user0_.id have id310_0 _, portfolios1_.id have id309_1 _,
user0_.address_fk have address8_310_0 _, user0_.password have password310_0 _,
user0_.lastName have lastName310_0 _, user0_.firstName have firstName310_0 _,
user0_.login have login310_0 _, user0_.sex have sex310_0 _, user0_.birthDate have
birthDate310_0 _, portfolios1_.name have name309_1 _, portfolios1_.user_fk have
user3_309_1 _, portfolios1_.user_fk have user3_0 __, portfolios1_.id have id0 __ from
XUser user0 _ left outer join Portfolio portfolios1 _ one user0_.id=portfolios1_.user_fk left
outer join FINANCIALPRODUCT financialp2 _ one
portfolios1_.id=financialp2_.portfolio_fk
A joint fetch does not need normally to define alias except when you wish to use the concept of the fetch
recursively.
Thanks to this modification, only one request is carried out. The use of this type of joint in a program is a need
for the optimization and the improvement of the performances. Indeed, it is strongly advised to avoid too much
outward journey and return with the data base.
1.5.4.8. Management of Polymorphism
EJBQL supports polymorphism, i.e. the requests relating to a hierarchy of objects.
69
http://www.supinfo.com
The execution of the following request turns over all the recordings dependent on the FinancialProduct entity
and thus of its subclasses.
[CODE:sql]SELECT fi FROM FinancialProduct AS fi
The collection of result contains objects of the Bond type or Stock, i.e. the concrete types of the hierarchy.
1.5.4.9. Under requests
The underrequests can beings placed in clauses WHERE and HAVING. Like their equivalent SQL, they make it
possible to imbricate the requests. The following example selects the users having more than 3 financial wallets.
[CODE:sql]SELECT user
FROM User user
WHERE (
SELECT COUNT(portfolio)
FROM Portfolio AS portfolio
WHERE portfolio.user=user
GROUP BY user
) >3
[CODE:sql]select user0_.id as id327_, user0_.address_fk as
address8_327_, user0_.password as password327_, user0_.lastName as
lastName327_, user0_.firstName as firstName327_, user0_.login as login327_,
user0_.sex as sex327_, user0_.birthDate as birthDate327_ from XUser user0_
where (select count(portfolio1_.id) from Portfolio portfolio1_ where
portfolio1_.user_fk=user0_.id group by user0_.id)>?
It is noticed that one alias reuses to use of the principal request in the underrequest. One of the principal interests
of the underrequests is to be able to replace the joints, in particular in the requests of the type UPDATE and
DELETE.
The following request removes all the financial products where the user has a id having for value 5:
[CODE:sql]DELETE FROM FinancialProduct AS fp
WHERE fp.portfolio IN (
SELECT portfolio
FROM Portfolio AS portfolio
WHERE portfolio.user IN (
SELECT user
FROM User AS user
WHERE user.login = 5
)
)
[CODE:sql]delete from FINANCIALPRODUCT where portfolio_fk in
(select id from Portfolio portfolio1_ where portfolio1_.user_fk in (select id
from XUser user2_ where user2_.id = 5))
Note
Use the underrequests when you cannot make differently. We advise you to study, initially, the use of
joints or instructions such as IN, ELEMENTS... which are obligatory besides in systems not taking into
account the underrequests.
When under request is likely to turn over several lines, it is then possible to quantify the result having to be
turned over. For that, one uses the expressions:
ALL turns over true if all the results of the request checks the condition.
70
http://www.supinfo.com
We recover a Query object here via the method createQuery() of EntityManager. It is then enough to call the
method getResultList() to carry out the request and to recover the result of this one.
Here a description of the various traditional methods of the Query interface.
[CODE:java]java.util.List getResultList();
This method carries out the request and turns over the whole of the results of this one. It makes it possible for
example to recover a whole of Entity Beans complete. It is then possible to specify several properties in clause
SELECT in order to recover only certain values of the entity, in the form of table.
[CODE:java]Query query = entityManager.createQuery("SELECT user.id, user.lastName FROM User As user");
List<Object[]> listUsers = query.getResultList();
for(Object[] valueArray : listUsers){
Integer id = (Integer) valueArray[0];
String name = (String) valueArray[1];
}
In this case, the method getResultList() turns over a list of table of object (" Object[ ] ").
[CODE:java]java.lang.Object getSingleResult();
This method carries out the request and turns over a single result. If the number of results is higher than 1, a
NonUniqueResultException exception is raised. Conversely, if no result is found, an exception of the
EntityNotFoundException type is raised.
This method must be used only if you are sure that the request turns over only one single result.
[CODE:java]Query query = entityManager.createQuery("SELECT user FROM User AS user
WHERE user.login = 'durand.dupont'");
User currentUser = (User) query.getSingleResult();
In this example, the property login is single. So we are sure that the method cannot return several results.
[CODE:java]setMaxResults(int max) and setFirstResult(int first)
These two methods respectively define the maximum number of results and the index of the first element to be
turned over.
Those make it possible to limit the results of the request. Indeed, if the request tries to turn over several
thousands of lines, you are likely to quickly reduce the performances of your application. Moreover, one
generally does not work with the whole of the results of only one blow but left by part.
[CODE:java]Query query = entityManager.createQuery("SELECT user FROM User As user");
query.setMaxResults(30);
query.setFirstResults(10);
List<User> listUsers = query.getResultList();
1.6. Conclusion
In this essential about EJB3, we've first seen that they locate in the center of your application, providing lots of
71
http://www.supinfo.com
assets (like the object persistence's one and a functionnal and performant client/server model).
Furthermore, during the setting up of this technology, the code writing is kind of simple and is very well
inscribed in the Java object Model... the complicated thing being to understand and to analyse the application
architecture.
The
trade
layers
are
also
more
efficient
72
http://www.supinfo.com
and
simpler
to
write.
Validate forms
Realize that a web application can be very close from a Swing application.
1. Course
1.1. Introduction
1.1.1. Servlet / JSP limitations
The first step to create a Web Site in Java is to use Servlet and JSP. Even if its possible to create a Site with
only these technologies its clear that Servlet better suit for treatment and JSP for visual.
But Servlet/JSP has some limitations:
XSL-FO Converter.
Extensibility, numerous JSF components are available on the Internet. This goes from calendar to tree by
going through sortable table and progress bar
Support a plugin system which can be used to modify the way JSF works
Manage data conversion (can convert a String into a Date, a String into a business object and viceversa...)
Validate users requests (test field length, content type, )
Manage internationalization
1.1.2.1. JSF Audience
A large audience can use JSF. From application developer, to designer, everyone can use JSF. There are three
main categories of people between five.
Application architect which will create application, define navigation file, classes/libs to use to make the link
between view and services layers
XSL-FO Converter.
IDE creators who will use JSF as the base of the IDE and extends JSF functionalities thanks to custom
components. For example Sun has created Java Studio Creator, an IDE dedicated to JSF and which JSF as its
core.
Servlet 2.5
JSE 5.0
JEE 5.0
JavaBeans 1.0.1
JSTL 1.2
All JEE 5 application servers supports JSF 1.2. If you dont have a JEE 5 server, you can still use JSF 1.1 with a
Servlet/JSP 2.3/1.2 server or JSF 1.2 with a Servlet/JSP 2.5/2.1 server. In a global manner, to run JSF 1.2 with a
non JEE 5 server, you have to include all JSF librairies into your wars. However there may be unexpected
behaviors depending on your application server. Check the documentation of your server before deploying a JSF
application.
This lesson has been created for JSF 1.1 and 1.2. Elements specific to JSF 1.2 are specified.
Managed Beans, it means that their lifecycle are managed by the container
Form validation
XSL-FO Converter.
...
But they also have a different way of working. Struts use an actionresponse model. Each user request to Struts
pages must go through a mini Servlet (action class) that can do some process and define the JSP target page.
With JSF a request is directly targeted to a JSP/JSF page. Then the page can use JavaBeans to define what
process to execute. This model promotes code reuse thanks to components.
Finally JSF is a JEE 5 standard which ensure that community and majors actors (Oracle with ADF/MyFaces,
Sun with Java Studio Creator 2, ) will maintain it.
JavaBeans interaction. JavaBeans represents the model and are used to interact with lower layers of your
application
Obersvator/Observer system
Conversion model
Validation model
All these services are manipulated through JSF tags, which is easier than in Java code.
In practice components are mostly invisible, its like a JavaBean is directly linked to JSF tags.
In MVC model, JSF components are the view, JavaBeans represents model. Controller is the Faces Servlet.
76
Created by XMLmind
XSL-FO Converter.
In a small application, its also possible to directly interact with a database from JavaBeans.
Heres an example of a site architecture:
1.2.1.1. LifeCycle
Well now see how server process a JSF request. JSF is made of a single Servlet. This Servlet is used to
transform JSF tags into components that are manipulated on the server side. And it also produces HTML from
JSF tags. When a client send a HTTP request to a server. The Servlet first retrieve the component tree which
maps to a requested JSF page by looking to identifiant put inside of the HTML code.
JSF Servlet can be executed in a Servlet or Portlet container. Class which manages lifecycle is
"javax.faces.context.FacesContext". When a request arrive on the server, a new instance of FacesContext is
created and process the request.
Lets see in details how request processing works:
77
Created by XMLmind
XSL-FO Converter.
XSL-FO Converter.
Install JSF
" jsfapi. jar ", contains JSF classes definition (package javax.faces)
" jstl.jar ", allow usage of JSTL tags. These tags are referenced by JSF implementation
" standard.jar ", allow usage of standard tags. These tags are referenced by JSF implementation
" jsfapi. jar ", contains JSF classes definition (package javax.faces)
79
Created by XMLmind
XSL-FO Converter.
JSF pages must have ".jsp" extension. Its a JSF parameter that you can modify, see chapter "6.3 Context
parameters".
An url like "/faces/index.jsp" is used to access JSF pages. If you try to access directly the jsp page (/index.jsp),
the request will not go through JSF Servlet and all JSF tags will not be processed.
Heres another example of mapping. To acess a page you have to type its URL but replace its extension with
".jsf".
[CODE:xml]<web-app>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
Although you access page by using a ".jsf" extension. All pages need to have the ".jsp" extension when you
create it. When client ask for "index.jsf" page, JSF Servlet look for "index.jsp" on the server and process it like a
JSF page.
80
Created by XMLmind
XSL-FO Converter.
</head>
<body>
<f:view>
Hello World
</f:view>
</body>
</html>
The first 2 lines declare JSF taglibs. The following is a classic HTML structure. The only difference is the
[CODE:xhtml]<f:view>...</f:view>
tag. Its the root tag for all others JSF tags.
In this example, we can see we can display text directly on the page. However it exists dedicated tags for output,
especially for internationalization.
1.3.3.1. War Structure
Once the JSF pages are created, there must be packaged into a War (Web Archive). A War must have the
following structure:
Table 2.1.
WEB-INF/classes
WEB-INF/lib
WEB-INF/faces-config.xml
Configuratin file(optional)
WEB-INF/web.xml
*.jsp
1.3.4. Deployment
Even if your server supports JSF, you can package your own JSF jar because its always the jar of the server
which have priority.
If you want to add support of JSF on a server, you can copy all the JSF jars in the libraries folder of the server.
For example in Tomcat, you can put them in the folder "TOMCAT_HOME/shared/ lib". This folder is specific
to the server, so you have to check the server documentation to find the good folder.
1.3.4.1. JBoss
JBoss supports JSF 1.1 since its version 4.0.3. This support is based on the implementation of Apache :
MyFaces. If you want to use the Sun implementation, you have to delete the MyFaces jars on JBoss. They are
on the folder:
JBOSS_HOME/server/default/deploy/jboss-web-tomcat55.sar/jsf-lib
If "default" is the configuration that you use.
81
Created by XMLmind
XSL-FO Converter.
Then, you have to package the Sun jars of JSF 1.1 into your War.
Support of JSF 1.2 is planned for JBoss 5.
1.3.4.2. Example
Well now see a little web site made in JSF. The goal is to show how look JSF tags and code. The web site uses
validation and errors displaying, site navigation mechanisms.
There are only 2 pages. The first display a form used to register. When the user submit it, data of the form are
displayed in a second page.
If theyre validation errors (missing field, too short password, ) messages are displayed directly on the form.
Lets start with the form page, "Register.jsp":
[CODE:xhtml]<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<title>Register</title>
</head>
<body>
<f:view>
<h1>Register</h1>
<h:form>
<!--Text field for the last name-->
<h:inputText id="lastName" required="true" size="21" maxlength="20" value="#{user.lastName}">
<!--Label of this text field -->
<h:outputLabel for="lastName" value="Last name: "/>
<!-- Validator: the name length must be betwenn 3 and 20 -->
<f:validateLength minimum="3" maximum="20"/>
</h:inputText>
<!-- Display errors message about the field 'lastName' -->
<h:message for="lastName" style="color: red"/>
<br/>
<!--Text field for the first name -->
<h:inputText id="firstName" required="true" size="21" maxlength="20" value="#{user.firstName}">
<h:outputLabel for="firstName" value="First name: "/>
<f:validateLength minimum="3" maximum="20"/>
</h:inputText>
<h:message for="firstName" style="color: red"/>
<br/>
<!-- Text field for the password -->
<h:inputSecret id="password" required="true" size="21" maxlength="20" value="#{user.password}">
<h:outputLabel for="password" value="Password: "/>
<f:validateLength minimum="3" maximum="20"/>
</h:inputSecret>
<h:message for="password" style="color: red"/>
<br/>
<h:commandButton value="Submit" action="success"/>
</h:form>
</f:view>
</body>
</html>
Syntax "#{user.lastName}" allows to use a JavaBean. Here "user" is the name of a bean and "lastName" is the
name of one of its properties.
Now well look at the bean class:
[CODE:java]package com.labosun;
public class User {
private String lastName;
private String firstName;
private String password;
public String getLastName() {
return lastName;
}
82
Created by XMLmind
XSL-FO Converter.
Now lets see the configuration file of JSF (faces-config.xml). This file gives a name to the previous bean.
[CODE:xml]<managed-bean>
<!-- Name of the bean inside JSF page -->
<managed-bean-name>user</managed-bean-name>
<!-- Bean Class -->
<managed-bean-class>com.labosun.User</managed-bean-class>
<!-- Bean scope -->
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Finally well look at the Confirmation page. This page display the lastname and the firstname of the user.
Confirmation.jsp :
[CODE:xhtml]<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<title>Registration</title>
</head>
<body>
<f:view>
<h1>Successful registration </h1>
Welcome <h:outputText value="#{user.firstName} #{user.lastName}" />
</f:view>
</body>
</html>
As you can see, syntax "#{user.prenom}" is used again here to reference the bean.
The last step for this demo is to define a navigation rule, so when the user click and the submit button, he goes
to the confirmation page. For recall, the code for the submit button is:
[CODE:xhtml]<h:commandButton value="Submit" action="success"/>
"Action" attribute define a string which will be linked to the confirmation page..
[CODE:xml]<navigation-rule>
<!--Start page -->
<from-view-id>/Register.jsp</from-view-id>
<navigation-case>
<!-- String used by the start page -->
<from-outcome>success</from-outcome>
<!--Destination page-->
<to-view-id>/Confirmation.jsp</to-view-id>
</navigation-case>
</navigation-rule>
83
Created by XMLmind
XSL-FO Converter.
Site design is not good, but well see later how to do it better.
When the user submit the form, the confirmation page is displayed:
You can customize these messages as explained in the chapter "8.2.1 Customize messages".
Be careful:
JSF tags cant use some properties.
There are some tags attributes that dont map to component property or method.
1.4.1. Behaviors
There are 5 interfaces that can define a behavior to components.
Table 2.2.
84
Created by XMLmind
XSL-FO Converter.
Interface
Description
StateHolder
NamingContainer
ValueHolder
EditableValueHolder
ActionSource
Note: In JSF 1.2, interface " ActionSource " has been subclassed into " ActionSource2 ".
JSF tags which implements ValueHolder has a "converter" attribute. Its used to define how the value must be
converted to another type. For example, you can convert the String "10/05/06" into a Date object directly.
JSF components which implements EditableValueHolder has the following attributes:
"validator", define the method of a bean that will validate the used entry.
"valueChangeListener", define the method that will be called when the value of the component change.
JSF components which implements ActionSource has the attribute "actionListener ". It define the method that
will be called when the user activate this component.
Behaviors are detailed in chapter "Behaviors".
Table 2.3.
Class (implemented interfaces)
Description
UICommand (ActionSource)
UIData (NamingContainer)
UIForm (NamingContainer)
Represents a form.
UIGraphic
UIMessage et UIMessages
85
Created by XMLmind
XSL-FO Converter.
Description
UIOutput (ValueHolder)
UIPanel
UISelectBoolean
(EditableValueHolder)
UISelectMany
(EditableValueHolder)
(extends
(extends
UISelectOne (extends UIInput) (EditableValueHolder) Used to select a single value from a list.
All these components have the following attributes.
1.4.2.1. Attribute id
This attribute defines an identifier for component. Its not mandatory to use an id. Its useful to reference
components on a page. A indentifier must respect the following rules:
It must begins with a letter (see method String.Character.isLetter()) or the character '_'.
This attribute can be used to display a message only if a search has returned no results.
1.4.2.3. Immediate attribute
As seen in chapter " LifeCycle", this attribute affect the lifecycle.
86
Created by XMLmind
XSL-FO Converter.
1.4.3.3. escape
Only some components have this attribute. If set to true, characters '<', '>' and '&' are converted into HTML
code.
1.4.3.4. JavaScript events
All tags that represents a HTML tags, also share the same javascript attributes. Heres a list of javascript
attributes:
" onclick, ondblclick, onblur, onchange, onclick, ondblclick, onfocus, onkeydown, onkeypress, onkeyup,
onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onreset, onselect, et onsubmit ".
1.4.3.5. Linking between JSF Components and JavaBeans
JavaBeans represents the model part into the MVC model. This model clearly separate different layer of an
application. They are to way to bind a component to a JavaBean:
Only the value of the component is bind to a JavaBean property (only for component that has a value).
1.4.3.5.1. Value
To bind the value of a component to a bean property, you have to use the attribute "value" and specify the
referenced bean with EL syntax.
Example:
[CODE:xhtml]<h:JSFTag value="#{javaBean.property}" />
Table 2.4.
Component
Possible values
UIData
XSL-FO Converter.
Component
Possible values
UISelectBoolean
boolean or Boolean
UISelectItems
UISelectMany
Array or List.
And then, you just specify the bean property with the attribute "binding":
[CODE:xhtml]<h:outputText binding="#{linkedBean.composant}" />
Difference between attributes "value" and "binding" is that "value" only bind the value of component and
"binding" bind the component instance. For example a text field accept a "String", a "Number" or a primitive as
value. So attribute "value" must have the same type. A text field is represented by the class "HtmlInputText".
The class hierarchy is:
In JSP, a EL expression is like "${ }". In JSF we use "#{}". Without explain differences between these 2
syntaxes, remember that its generally bad to mix JSF and JSP EL expressions (like mixing AWT and Swing).
The best way is to use only JSF syntax and replace JSP tags by their equivalents in Facelets tags (see chapter "9
Facelets").
88
Created by XMLmind
XSL-FO Converter.
1.4.3.6.1. Variables
Its possible to reference any object in a page. For example:
#{person}
The Web (or Portlet) container will look for an object which is named "person" in the page, the request, the
session or the application. "." Operator is used to access a property, method of an bean. For example to access
"name" property of "person", youll write:
#{person.name}
To access an array or a list, use operator "[]". Example, you want to get the third element of an array:
#{uelBean.tab[2]}
Operator "[]" can also be used to access property or method. In this case, the name of the property (or method)
must be enclosed with quote.
Examples: Access to property "name" of "person".
#{person['name']}
Table 2.5.
Object name
Description
applicationScope
cookie
facesContext
header
headerValues
initParam
param
paramValues
XSL-FO Converter.
Object name
Description
requestScope
sessionScope
view
1.4.3.6.3. Operators
Most of Java operators can be used. But you can also used
Relational: ==, "eq", !=, "ne", <, "lt", >, "gt", <=, "le", >=, "ge". These operators can compare primitives and
String.
instanceof
90
Created by XMLmind
XSL-FO Converter.
<h:outputText>
<h:outputFormat>
<h:outputLabel>
They correspond to the components:
HtmlOutputText
HtmlOutputFormat
HtmlOutputLabel
They inherit from UIOutput which implement ValueHolder.The "value" attribute permit to define the text to
display. This attribute can be associated with a primitive, a String, a Number or every class which contains a
data converter (Chapter "7.3 Conversions").
1.5.3.1. Simple text
The simpler tag to display a text in one line is:
[CODE:xhtml]<p> <h:outputText value="text"/> </p>
Here is an other example but this time we will include some text in the tag.
[CODE:xhtml]<p> <h:outputText value="Another test of " style="color: red">
outputText
</h:outputText> </p>
Note that the text in the tag is displayed before the text specify in the "value" attribute. Only the text write in the
tag can us CSS style.
Note : Its possible to display a text from a resource file (Chapter "8.1 Internationalization).
1.5.3.2. Formatted output
The <h:outputFormat> tag displays a formatted message with the format() method from the MessageFormat
class. Its possible to transmit parameters on using under tag <f:param />.
Example of JSF code :
[CODE:xhtml]<p> <h:outputFormat value="outputFormat is {0}"><br />
<f:param value="great" /> <!--Parameters-->
</h:outputFormat> </p>
XSL-FO Converter.
[CODE:xhtml]<p>outputFormat is great</p>
Other use:
[CODE:xhtml]<h:outputFormat
value="Precision at 2 digit: {0,number,#.##}, at 1 digit: {0,number,#.#}">
<f:param value="#{basic.nb}" />
</h:outputFormat>
1.5.4. Form
This tag represents a form. The component implements "NamingContainer". It means that every tags in a form
must have an unique id.
Example:
[CODE:xhtml]<h:form>
</h:form>
JSF will add some information when the tag will be translated into HTML. The method used by the form is
always "POST" and the encoding in " application/x-www-form-urlencoded".
[CODE:xhtml]<form id="_id0" method="post" action="/HW/04Form.jsf" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="_id0" value="_id0" />
</form>
A last example which illustrate how to add an id for every under tags of a form:
[CODE:xhtml]<h:form>
<h:outputText id="name" value="text" />
</h:form>
In HTML:
[CODE:xhtml]<form i d="_id1" method="post" action="/HW/04Form.jsf" enctype="application/x-www-form-urlencoded">
<span id="_id1:name">text</span>
92
Created by XMLmind
XSL-FO Converter.
Every component which doesnt have an id will have an attributed one. The id used is prefixed by the id of the
form. It permits to give few times the same id in different form.
HtmlInputText
HtmlInputTextarea
HtmlInputSecret
HtmlInputHidden
They inherit of UIInput which implements EditableValueHolder. The "value" attribute of these tag permit to
affect a value by default to a field. The value can be linked to a primitive, a String, a Number or every class
which have a data converter. Its possible to use "required" attribute to indicate that a field is obligatory.
1.5.5.1. Text field
The simpler tag to type text is <h:inputText>.
[CODE:xhtml]<h:inputText maxlength="20" size="20" value="default value"/>
93
Created by XMLmind
XSL-FO Converter.
1.5.6. Link
It exist 2 kind of link in JSF:
The simple links, which dont start any event on the server side.
The link which will start an event on the server side. It will permit to manage the navigation of the web site
with a unique file.
Every links of your web site (which are linked to your web site) have to be the second type. With this kink of
link youll be able to define the navigation of your web site in a configuration file.
1.5.6.1. Simple link
The <h:outputLink> tag permit to display a link. It uses the "HtmlOutputLink" component which inherits of
UIOutput which implements ValueHolder.
The "value" attribute permit to define the url of the link. The value can be associated to a primitive, a String, a
Number or every class which have a data converter. It doesnt exist attribute which define the text of the link.
To define the text, we have to use an under tag like <h:outputText>.
Example :
[CODE:xhtml]<h:outputLink value="url ">
<h:outputText value="Text of the link" />
</h:outputLink>
Every urls are relatives to the current url. Its possible to refer to the web site root on prefixing the url by "/".
If we have the following url:
http://localhost:8080/JSFCours/faces/testLiens.jsp
Where " JSFCours " is the web site context and " faces " is JSF file mapping. So, for example :
" index.jsp " is reachable through the url " http://localhost: 8080/JSFCours/faces/index.jsp "
" /index.jsp " is reachable through the url " http://localhost:8080/index.jsp "
It is possible to retrieve the web site context and mapping with the following expressions:
94
Created by XMLmind
XSL-FO Converter.
#{facesContext.externalContext.requestPathInfo}, path to the current web page, starting from the JSF Servlet.
For example, if you have the URL " http://localhost:8080/JSFCourse/faces/testLiens.jsp " so you will retrieve
the following values:
facesContext.externalContext.requestContextPath = /JSFCourse
facesContext.externalContext.requestServletPath = /faces
facesContext.externalContext.requestPathInfo = /testLiens.jsp
1.5.6.2. JSF link
You can create a link with " HtmlCommandLink ". It extends UICommand which implement " ActionSource ".
The tag related to this component is <h:commandLink>. This tag has to be nested inside a <h:form> tag.
Its " value " attribute allows to define its text (not destionation URL). The value can either be a primitive, a
String, a Number or any other class with a converter (see chapter about converters). This kind of link does not
use any URL to define destionation, but a string value. This one is evaluated inside JSF navigation rules which
are defined inside its configuration (see faces-config.xml file). See chapiter " 6.2 Navigation " for further
information about the action attribute and navigation rules.
Exemple :
[CODE:xhtml]<h:form>
<h:commandLink action="success" value="This is a JSF link" />
</h:form>
1.5.6.3. Parameters
It is possible to define parameters inside a link by nesting <f:param> tags. It has two main attributes, which are "
value " and " name " :
[CODE:xhtml]<h:form>
<h:outputLink value="index.jsp">
<h:outputText value="index.jsp"/>
<f:param name="id" value="2"/>
<f:param name="sortBy" value="price"/>
</h:outputLink>
<br/>
<h:commandLink>
<f:param name="id" value="6"/>
<f:param name="sortBy" value="name"/>
</h:commandLink>
95
Created by XMLmind
XSL-FO Converter.
</h:form>
They can be retrieved with the expression " #{param.ParameterName} ". In this case, it is :
[CODE:xhtml]<h:outputText value="id=#{param.id}, sortBy=#{param.sortBy}" />
You can test wether the parameter has been defined with the expression: " #{!empty param.ParameterName} ".
It allows defining tags only if a parameter exists. Example:
[CODE:xhtml]<h:outputText value="(Only displayed if 'id' exists) id=#{param.id}"
rendered="#{!empty param.id}"/>
1.5.7. Button
The component which display a button is " HtmlCommandButton ". It extends UICommand which implements
ActionSource (and ActionSource2 for JSF 1.2). A button works almost like link. Example :
[CODE:xhtml]<h:form>
<h:commandButton action="action value" value="Send" />
</h:form>
1.5.8. Checkbox
There are 2 components which display checkboxes:
To display a text close to the checkbox, you have to nest a <h:outputLabel> tag.
Example:
[CODE:xhtml]<h:selectBooleanCheckbox id="choice" value="#{bean.property}">
<h:outputLabel for="choice" value="Married :" />
</h:selectBooleanCheckbox>
XSL-FO Converter.
define inside which boxes are selected by default (you will see that later). In order to define which boxes have to
be displayed, you have either to:
or nest a single <f:selectItems> tag which need a reference with items from the managed-bean.
1.5.8.2.1. SelectItem
The nested <f:selectItem> tag is a check box. Its attributes " itemValue " and " itemLabel " contain the value
and the displayed text. Example:
[CODE:xhtml]<h:selectManyCheckbox id="ville" layout="pageDirection"
value="#{bean.selectedCities">
<f:selectItem itemValue="StrasValue" itemLabel="Strasbourg" />
<f:selectItem itemValue="LyonValue" itemLabel="Lyon" />
<f:selectItem itemValue="ParisValue" itemLabel="Paris" />
</h:selectManyCheckbox>
Here, items value is " java.lang.String ". " #{bean.selectedCities} " expression create a link with the selected
cities. Its contains the "itemValue" of all the selected boxes. For example, when the user sends a form with the "
Strasbourg " city selected, thus " selectedCities " will contain " StrasValue ". If the user selects 2 boxes, "
selectedCities " will contain " StrasValue " and " LyonValue ". It is important to take care about the type of your
objects on the ManagedBean side. Indeed, you can either use an array of String (String []) or a List to contains
selected cties, but you can not use an array of integer because values are strings. If you want to create items with
objects of your choice (like your own class City), you have to use a converter. Indeed, JSF need a String value.
1.5.8.2.2. SelectItems
You can also initialize your items directly from a ManagedBean containing an Array, a Map or a List. Lets take
the following class as ManagedBean:
[CODE:java]public class Bean {
private List selectedCities = new ArrayList();
private List allCities = new ArrayList();
public Bean() {
//add available cities
allCities.add(new SelectItem("StrasbourgValue", "Strasbourg :"));
allCities.add(new SelectItem("LyonValue", "Lyon :"));
//city selected by default
selectedCities.add("LyonValue");
}
public List getAllCities() {
return allCities;
}
97
Created by XMLmind
XSL-FO Converter.
Finally, you can use a Map. In this case, the keys are the values, and values of the map are the displayed labels.
Example:
[CODE:java]Map allCityMap = new HashMap();
allCitiesMap.put("Strasbourg :", "StrasbourgValue ");
allCitiesMap.put("Lyon :", "LyonValue ");
Group name
Description
A SelectItem array
Once a SelectItemGroup instanciated, you can gather many groups and items inside a List as you can see on the
following example:
[CODE:java]// city list
List allCities = new ArrayList();
//french cities
SelectItem[] citiesFrance = new SelectItem[3];
citiesFrance[0] = new SelectItem("StrasValue", "Strasbourg");
citiesFrance[1] = new SelectItem("LyonValue", "Lyon :");
citiesFrance[2] = new SelectItem("ParisValue", "Paris :");
//create a group for French cities
SelectItemGroup franceGroup = new SelectItemGroup("France",
"French cities", false, citiesFrance);
//german cities
SelectItem[] germanyCities = new SelectItem[2];
germanyCities[0] = new SelectItem("KehlValue", "Kehl :");
germanyCities[1] = new SelectItem("BerlinValue", "Berlin :");
// create a group for german cities
SelectItemGroup germanyGroup = new SelectItemGroup("Allemagne", "German cities", false, germanyCities);
98
Created by XMLmind
XSL-FO Converter.
1.5.9. RadioButton
The <h:selectOneRadio> tag allows defining a radio button list. It use the class " HtmlSelectOneRadio " which
implement " EditableValueHolder ". A list is constructed with nested <f:selectItem> tags or a single
<f:selectItems> tag (see chapter " 5.8.2 MultipleCheckbox component " for more information about these tags).
Notice that only one button can be selected at the same time. The radio button selected can either be stored as a
primitive, a String, a Number or any class having a converter.
Example:
[CODE:xhtml]<h:selectOneRadio layout="lineDirection" value="#{bean.color}>
<f:selectItem itemValue="red" itemLabel="red"/>
<f:selectItem itemValue="white" itemLabel="white"/>
<f:selectItem itemValue="yellow" itemLabel="yellow"/>
</h:selectOneRadio>
The property referenced by the " value " attribute should have the same type as the item value. Above, "
#{bean.color} " is a String because values are Strings.
1.5.10. List
There is 2 components to display a list:
<h:selectOneListbox> to display a list with only one item selected in the same time (it works the same way as
<h:selectOneRadio>).
<h:selectManyListbox> display a multiple choice list (it works the same way as <h:selectManyCheckBox>).
The " size " attribute allows you to define how many lines you want to display.
Example:
[CODE:xhtml]<h:selectManyListbox id="color" value="#{bean.colors}">
<f:selectItem itemValue="red" itemLabel=" Red:"/>
<f:selectItem itemValue="white" itemLabel=" White:"/>
<f:selectItem itemValue="yellow" itemLabel=" Yellow:"/>
</h:selectManyListbox>
99
Created by XMLmind
XSL-FO Converter.
1.5.12. Pictures
The <h:graphicImage> tag allows to insert a picture. It has the following attributes:
You can also use pictures as links by nesting a <h:graphicImage> tag inside a link component:
[CODE:xhtml]<h:outputLink value="http://java.net">
<h:graphicImage value="javadotnet.jpg" />
<h:outputText value="java.net" />
</h:outputLink>
1.5.13. Panel
The <h:panelGroup> tag allows gathering many JSF components in order to handle them as only one tag.
Indeed, some components can only have one nested tag.
Example:
[CODE:xhtml]<h:panelGroup>
<h:outputText value="first child" />
<f:verbatim><br /></f:verbatim>
<h:outputText value="second child" />
</h:panelGroup>
Notice the <f:verbatim> tag around <br/>. It allows returning the text and tags in the same postition. Indeed, if
you do not use it...:
[CODE:xhtml]<h:panelGroup>
<h:outputText value="first child" />
<br />
<h:outputText value="second child" />
</h:panelGroup>
1.5.14. Table
There is two ways to create tables with JSF:
100
Created by XMLmind
XSL-FO Converter.
<h:panelGrid>
<h:dataTable>
They both have the following attributes:
footerClass: define which CSS class(es) are used to display the tables footer
headerClass: define which CSS class(es) are used to display the tables header
To declare CSS classes for each column, you have to use a comma:
class1.1 class1.2 class1.3, class2 class2.1, class3, class4 class4.1 class 4.2
has 4 columns
CSS classes " class1.1 ", " class1.2 " and " class1.3 " are used for the first column
" class2 " and " class2.1 " for the second
" class4.1 " and " class4.2 " for the fourth.
If there is not the same number of CSS classes groups and columns:
If there are more columns than CSS classes groups, then CSS classes groups are reused for the following
columns.
If there are less columns than CSS classes groupes, useless CSS classes groups wont be used.
The " rowClasses " attribute allows defining CSS classes to lines, and it works the same way.
1.5.14.1. Static table: PanelGrid
This kind of array is created with the <h:panelGrid> tag. When you use this table, it means you already know
how many lines and rows you want to display. Indeed, it does not fit well with dynamically generated tables.
In order to define the content of a table, you have to nest tags inside.
Example:
101
Created by XMLmind
XSL-FO Converter.
We described the cells starting from upper left to bottom right. There is no tag which defines the beginning or
the end of a line. JSF define the position of each component according the order in which it is declared. As there
are 2 columns, and 4 components, we can assume there is 2 lines.
It displays the following table:
Table 2.6.
A
Now, if you want to display 3 columns, a new line will be created for each after 3 tags:
[CODE:xhtml]<h:panelGrid border="1" columns="3">
<h:outputText value="A" />
<h:outputText value="B" />
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
Table 2.7.
A
D
1.5.14.1.1. Group elements
If you want to use many tags inside the same cell, you have to group them inside the <h:panelGroup> tag.
Example:
[CODE:xhtml]<h:panelGrid columns="2" border="1" rules="all">
<h:outputText value="A" />
<h:panelGroup>
<h:outputText value="B" />
<f:verbatim><br /></f:verbatim>
<h:outputText value="B bis" />
</h:panelGroup>
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
XSL-FO Converter.
A header or a footer is defined with a <f:facet> tag. It has an attribute called " name " which define which part is
currently written. Available values are the following ones:
Below is a screenshot
103
Created by XMLmind
XSL-FO Converter.
A JavaBean list
A JavaBean array
A JavaBean
A javax.faces.model.DataModel
A java.sql.ResultSet
A javax.servlet.jsp.jstl.sql.ResultSet
A javax.sql.RowSet
The " value " attribute allows defining which property to browse. Furthermore, " var " attribute is the name
which references the elements of the " value " attribute. Below is an example:
[CODE:xhtml]<h:dataTable value="#{bean.elementList}" var="itemFromTheList" />
To define the content of the table, you have to use the <h:column> tag. Each one set a new column :
[CODE:xhtml]<h:dataTable value="#{bean.elementList}" var="itemFromTheList" />
<h:column>
<%--first column--%>
<h:outputText value="#{itemFromTheList .property1" />
</h:column>
<h:column>
<%--second column--%>
<h:outputText value="#{itemFromTheList .property2}" />
</h:column>
</h:dataTable>
If the list contains five elements, thou the table display five lines.
You can also use the following attributes:
104
Created by XMLmind
XSL-FO Converter.
Then, the following JSF code uses the ResultSet with <h:dataTable> tag and its "value" attribute:
[CODE:xhtml]<h:dataTable value="#{dbBean.personRS}" var="personDB" rules="all" border="1">
<h:column>
105
Created by XMLmind
XSL-FO Converter.
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<!-- Retrieve lastname column -->
<h:outputText value="#{personDB['lastName']}" /><br />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Prnom" />
</f:facet>
<!-- Retrieve firstname column -->
<h:outputText value="#{personDB.firstName}" />
</h:column>
</h:dataTable>
Table 2.8.
Attribute
Type
Default value
Description
showDetail
boolean
false
Define
wether
more
information is displayed.
showSummary
boolean
true
Table 2.9.
Attribute
Type
Default value
Description
globalOnly
boolean
false
layout
String
list
It
106
Created by XMLmind
XSL-FO Converter.
allows
defining
Attribute
Type
Default value
Description
specific renderings:
The <f:validateLongRange> tag allows testing if value is between 1 and 10. Indeed a message is displayed if the
value is not validated.
You can also change the CSS class of your messages :
Table 2.10.
Name
Description
errorClass
fatalClass
infoClass
warnClass
There is also the " errorStyle ", " fatalStyle ", " infoStyle " and " warnStyle " attributes to define directly the
style.
XSL-FO Converter.
To configure JavaBeans and handle them through JSF pages, below is the appropriate declaration:
[CODE:xml]<managed-bean>
<managed-bean-name>nom du bean dans la page JSF</managed-bean-name>
<managed-bean-class>class du bean </managed-bean-class>
<managed-bean-scope>(application|session|request|none)</managed-bean-scope>
<managed-property>
<property-name>nom de la proprit </property-name>
<property-class>type de la proprit </property-class>
<value>valeur par dfaut </value>
</managed-property>
</managed-bean>
" managed-bean-name " is the JavaBean name to reference it from JSF pages.
" managed-bean-class " is the fully qualified name of the JavaBean class.
" managed-bean-scope " define the scope of your JavaBean (either request, session, application or none).
" application " means your JavaBean instance is reachable for all the users.
" session " means your JavaBean instance is specific for each user.
" request " means a JavaBean instance is created for each request.
" none " means a JavaBean instance is created each time it is called.
1.6.1.1. List declaration
A list is declared with the <listentries> tag. Then you nest values with <value> tags.
Example:
[CODE:xml]<managed-bean>
<managed-bean-name>cityList</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value-class>java.lang.String</value-class>
<value>Strasbourg</value>
<value>Bordeaux</value>
<value>Paris</value>
<value>Nice</value>
<null-value/>
</list-entries>
</managed-bean>
Notice you can include a null value thank to the <null-value> tag.
You can also define which class to use with the <value-class> tag.
1.6.1.2. Map declaration
108
Created by XMLmind
XSL-FO Converter.
A "Map" is declared with a <map-entries> tag. For each entry in the map, you have to insert a <map-entry> tag.
This last one has two nested elements which are <key> and <value>.
Example:
[CODE:xml]<managed-bean>
<managed-bean-name>dicoMap</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<map-entries>
<key-class>type.of.your.class</key-class>
<value-class>type.of.your.value</value-class>
<!--first entry -->
<map-entry>
<key>value of the key 1</key>
<value>value associatied with key 1</value>
</map-entry>
<!--second entry -->
<map-entry>
<key>value of the key 2</key>
<value>value associated with key 2</value>
</map-entry>
</map-entries>
</managed-bean>
Just as list declaration, you can define which class to use. The <key-class> and <value-class> tags define which
class to use as key and value. They are both nested inside the <map-entries> tag.
Finally, it is possible to define a null value with the <null-value> tag.
1.6.1.3. Example: Declaration of a SelectItem list
We already have declared collections, ... now, lets see about SelectItem list. We first created managed beans
with the SelectItem class and entries within:
[CODE:xml]<!--declare a first bean -->
<managed-bean>
<managed-bean-name>city0</managed-bean-name>
<!--this bean is a javax.faces.model.SelectItem class -->
<managed-bean-class>javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<!--we define below two entries -->
<managed-property>
<property-name>value</property-name>
<value>Stras</value>
</managed-property>
<managed-property>
<property-name>label</property-name>
<value>Strasbourg</value>
</managed-property>
</managed-bean>
<!--declare a second bean -->
<managed-bean>
<managed-bean-name>city1</managed-bean-name>
<managed-bean-class>javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>value</property-name>
<value>Lyon</value>
</managed-property>
<managed-property>
<property-name>label</property-name>
<value>Lyon</value>
</managed-property>
</managed-bean>
Then you declare another managed bean with the ArrayList class and entries made of previously declared
"city0" and "city1" managed beans.
109
Created by XMLmind
XSL-FO Converter.
As you can see, this syntax is a bit heavy, and it is shorted to write entries directly.
1.6.2. Navigation
Navigation is defined with "navigation rules". Each rules define sources and destinations pages.
[CODE:xml]<navigation-rule>
<from-view-id>/source page</from-view-id>
<navigation-case>
<from-outcome>string returned by an action</fromoutcome>
<to-view-id>/destination page</to-view-id>
</navigation-case>
</navigation-rule>
The " from-view-id " tag defines the source page. Then we can nest as many " navigation-case " as needed and
each one have an "outcome" string and "destination" page.
The " from-outcome " tag is the string returned by a link, a button, a managed bean method, etc. Finally the " toview-id " tag is the destination page.
Take the following example:
[CODE:xml]<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/buy.jsp</to-view-id>
</navigation-case>
</navigation-rule>
As you can see above, you are creating a navigation rule for the web page "index.jsp". If an action return the
value "success", then the user is being forwarded to " buy.jsp ". You have to use "/ as the beginning of the URL
to refer to the root of the web site. You can insert actions into your web pages with JSF tags and their "action"
attribute:
[CODE:xhtml]Action example with a link:
<h:form>
<h:commandLink action="success" value="Make an order"/>
</h:form>
Action example with a button:
<h:form>
<h:commandButton action="success" value="Make an order"/>
</h:form>
Notice that this declaration works well with the two following JSF declaration, inside "web.xml" file:
[CODE:xml]<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
[CODE:xml]<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
110
Created by XMLmind
XSL-FO Converter.
In this case, all the pages which returns "error" shall forward the user to the web page "error.jsp". Another
solution is to remove the <from-view-id> tag.
1.6.2.2. Action strings
Lets look a bit further about navigation. There is two main tags, which are <from-action> and <fromoutcome>. They can be used alone or in the same time. Indeed there is three ways to declare navigation rules:
If you only write out the " from-outcome " tag, the string must be equal either to an action attribute value or
the return value of a method.
If you write out the two of them, naviguation would only be true if the method defined inside " from-action "
returns the value specified inside the " from-outcome " tag.
If you only write out the " from-action " tag, the value should be a reference to a method. Whatever the return
value is, navigation is true.
Currently used action strings in " from-outcome " are the following:
Table 2.11.
Outcome
Signification
success
It worked correctly
failure
logon
no results
1.6.2.2.1. From-outcome
It is the tag we used in the previous examples. You can also call a method from a managed-bean and analyse its
return value. Below is a method example:
[CODE:java]public String methodName();
111
Created by XMLmind
XSL-FO Converter.
<to-view-id>/achat.jsp</to-view-id>
</navigation-case>
</navigation-rule>
... and finally we write out the JSF link component in the page " index.jsp ":
[CODE:xhtml]<h:form>
<h:commandLink value="Vers la page achat" action="#{navi.getSuccessString}"/>
</h:form>
We used <from-action> twice but the value nested inside <from-outcome> will allow to create different
navigation cases.
If the method returns any other string than "order" or "mustLogin", the user is not redirected and he stays on the
same page.
In order to use this navigation case, you have to use an action attribute with a reference to a method, like
displayed below:
[CODE:xhtml]<h:commandLink value="Valide les achats" action="#{navi.validateOrder}"/>
1.6.2.2.3. From-action
With this tag, you only specify which method to use:
[CODE:xml]<navigation-rule>
<from-view-id>/index.jsp</fro-mview-id>
<navigation-case>
112
Created by XMLmind
XSL-FO Converter.
<from-action>#{navi.validateOrder}</from-action>
<to-view-id>/order.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Above, whatever the return value is, the user returns to the "order.jsp" page.
Below is an action attribut which call the validateOrder() method:
[CODE:xhtml]<h:commandLink action="#{navi.valideOrder}" />
1.6.2.3. Example
Lets finish this chapiter by a comprehensive example of navigation rules. The purpose of the following web site
is to manage a list. Indeed you have to write a managed-bean with a List<String> typed object.
This web site is composed of the following pages:
" list.jsp " is the main page, it displays all the entries of the list. It also displays links to remove and modify
them.
" detail.jsp " displays all the information of an entry. It also displays links to the list and delete page.
" delete.jsp " allows to remove an entry, it displays a confirmation message and redirect the client to the list
page.
" new.jsp " allows to create a new entry inside the list. Elle possde un lien vers la page principale.
When you want to remove an entry, you have to pass the entry parameter inside the request, as you saw on the
chapter " 5.6.3 Parameters ".
Below are navigation rules:
[CODE:xml]<navigation-rule>
<from-view-id>/list.jsp</from-view-id>
<navigation-case>
<!--link with the detail page >
<from-outcome>edit</from-outcome>
<to-view-id>/edit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<!--link with the remove page >
<from-outcome>delete</from-outcome>
<to-view-id>/delete.jsp</to-view-id>
</navigation-case>
<navigation-case>
<!--link with the creation page >
<from-outcome>new</from-outcome>
<to-view-id>/new.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/delete.jsp</from-view-id>
<navigation-case>
<!--link with the main page >
<from-outcome>success</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/new.jsp</from-view-id>
<navigation-case>
<!--link with the creation page >
113
Created by XMLmind
XSL-FO Converter.
<from-outcome>success</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/edit.jsp</from-view-id>
<navigation-case>
<!--link with the delete page >
<from-outcome>delete</from-outcome>
<to-view-id>/delete.jsp</to-view-id>
</navigation-case>
<navigation-case>
<!--link with the list page >
<from-outcome>list</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
114
Created by XMLmind
XSL-FO Converter.
115
Created by XMLmind
XSL-FO Converter.
Table 2.12.
javax.faces.CONFIG_FILES
javax.faces.DEFAULT_SUFFIX
javax.faces.LIFECYCLE_ID
javax.faces.STATE_SAVING_METHOD
116
Created by XMLmind
XSL-FO Converter.
1.7. Behavior
1.7.1. ActionListener
All the components which implement "ActionSource" (UICommand) can generate an event. This means a
method is called when the user clicks on an element. The event is treated server side, when the client sends the
page to the server.
Here for recall the cycle of life of a JSF request :
The events of type ActionListener are treated during the phase "Invocation of the application". If the component
which declares the event has the attribute "immediate" set to true, the event is treated during the phase "Request
parameters appliction". Attention however, because during this phase, all the elements are not yet up to date (the
javabeans are only updated during the phase "Update model"). The elements update order is the order of the tag
declaration. There are 2 manners of dealing with server side events. The first solution is to associate a method of
a generic JavaBean. Second is to create an implementation of the interface "ActionListener".
1.7.1.1. Generic method
To create a method which manages an event, it is necessary that it has the following prototype :
[CODE:java]public void methodName(javax.faces.event.ActionEvent e);
The method can be in any bean, but it must be referred as a managed bean by the container. To use the method
you only have to refer to it by using the attribute "actionListener".
Example:
[CODE:xhtml]<h:commandButton value="Send" actionListener="#{beanName.methodName}" />
This ActionListener can be referred in 2 different ways. It is possible to use the attribute "actionListener" as
mentioned previously. But we can also use the tag <f:actionListener>. The "type" attribute of this tag makes it
possible to specify the class of the used ActionListener.
Example:
[CODE:xhtml]<h:commandLink value="with an interface">
<f:actionListener type="listeners.EventHandling" />
117
Created by XMLmind
XSL-FO Converter.
</h:commandLink>
The events of type ValueChangeListener are treated during the phase "Validation of the user entries". If the
component which declares the event has the attribute "immediate" set to true, the event is treated during the
phase "Request parameters application". In that case, all the conversion operations and validations related to this
component will be carried out before the ValueChangeListener management.
Be careful however, because during this phase, not all the elements are yet up to date (the javabeans are only
updated during the phase "model update"). The elements update order is the order of the tag declaration.
1.7.2.1. Generic method
A method which manages the event must have the following prototype:
[CODE:java]public void check(javax.faces.event.ValueChangeEvent event);
The JavaBean which declares the method must be referred as JavaBean managed by the container.
The method can then be referred thanks to the attribute "valueChangeListener".
[CODE:xhtml]<h:inputText valueChangeListener="#{beanName.methodName}" />
This listener can be referred either thanks to the attribute "valueChangeListener" as seen previously, either
thanks to the tag <f:valueChangeListener>. The "type" attribute of this one makes it possible to specify the class
of the used listener.
Example:
[CODE:xhtml]<h:inputText value="value">
<f:valueChangeListener type="listeners.BeanValueChangeListener" />
</h:inputText >
XSL-FO Converter.
able to rebuild the object which represents the value of the client request (which is in the form of a String).
Then, at the time of the return phase, the object must be translated into a String. JSF manages the conversion of
the primitives and the standard objects of Java: Boolean, Number
All the conversion operations are carried out at the time of the phase "Request parameters application".
This principle of conversion also makes it possible to personalize the posting of the objects. For example a date
canbe posted in the format "DD/MM/AAAA" or with the day in full letters.
The conversions errors can be posted with the tag <h:message>.
1.7.3.1. Standard conversion: Date
The tag <f:convertDateTime> ensures the conversion Date String. By default, a date is posted in a following
way: "Sat Jul 22 12:56: 12 CEST 2006" what corresponds to Saturday July 22, 2006.
The tag <f:convertDateTime> has the following attributes:
Table 2.13.
Attribute
Type
Description
dateStyle
String
String
locale
String or Locale
timeZone
String or TimeZone
pattern
String
type
String
Created by XMLmind
XSL-FO Converter.
Attribute
Type
Description
represented is a date, a time or both.
The values are: date (by default),
time and both.
Example:
[CODE:xhtml]<h:inputText value="#{bean.date}">
<f:convertDateTime dateStyle="full" />
</h: inputText >
Now lets see an example of a form which makes it possible to seize a date in the format "dd/mmyy" and which
then transforms the string in a Date object. For that it is necessary to use the attribute "pattern" and to define the
date format to be used. In our case it is "dd/MMyy":
[CODE:xhtml]<h:form>
<h:inputText id="date" value="#{bean.date}">
<h:outputLabel for="date" value="Date (dd/mm/yy): " />
<f:convertDateTime pattern="dd/MM/yy" />
</h:inputText>
<h:commandButton value="valider" />
</h:form>
Table 2.14.
Attribute
Type
Description
currencyCode
String
currencySymbol
String
Monetary symbol.
locale
String or Locale
integerOnly
boolean
maxFractionDigits
int
minFractionDigits
int
maxIntegerDigits
int
minIntegerDigits
int
type
String
120
Created by XMLmind
XSL-FO Converter.
*/
String getAsString(FacesContext context, UIComponent component, Object value);
The 2 methods have as parameter the FacesContext instance and the component for which one the conversion is
done. Before being able to use this converter, it should be declared. That is made in the file "faces-config. xml"
using the tag <converter>.
Example:
[CODE:xml]<converter>
<description>Mon premier convertisseur</description>
<converter-id>myConv</converter-id>
<converter-class>com.labosun.converter.MyConverter</converter-class>
</converter>
With the tag <f:converter>, the attribute "converterId" must refer the identifier of the converter.
Example:
[CODE:xhtml]<h:outputText value="#{conv.person}">
<f:converter converterId="myConv" />
</h:outputText>
selectManyCheckbox
selectOneRadio
selectOneListBox, selectManyListBox
selectOneMenu
In this example, we will use the tag selectOneRadio which will make it possible to choose between several
instances of the following class "Persson":
[CODE:java]public class Person {
public static int IDS = 0;
private int id;
121
Created by XMLmind
XSL-FO Converter.
This class simply defines a person who has a unique identifier, a name and a first name..
We will now define the bean which will define the list of SelectItem. We will start by seeing what happens
without data converter.
[CODE:java]package com.labosun;
public class PersonConv {
/**
* This list simulat at data source
*/
public static final List<Person> PERSONS_LIST = new ArrayList<Person>();
static {
PERSONS_LIST.add(new Person(1, "Jo", "Johnson"));
PERSONS_LIST.add(new Person(2, "Raymond", "Schmitt"));
PERSONS_LIST.add(new Person(3, "Bob", "LeNain"));
}
/**
* SelectItem list which return the content of a select request ....
*/
private List<SelectItem> allPersons;
/**
* A person currently selected
*/
private Person person;
public PersonConv() {
allPersons = new ArrayList<SelectItem>();
for (int i = 0; i < PERSONS_LIST.size() 1;i++) {
Person p = PERSONS_LIST.get(i);
this.allPersons.add(new SelectItem(p, p.toString()));
}
Person p = new Person(3, "Bob", "LeNain");
this.allPersons.add(new SelectItem(p, p.toString()));
}
//Getters et setters for all the properties
...
}
The constructor creates a list of SelectItem (Al) from our list of people (PERSON_LIST). But the last instance
of people is not taken out of the list, this is voluntary, you will understand later why. Here now our JSF page. It
contains as many radio buttons as there are people in the list and it posts the currently selected element
[CODE:xhtml]<h:form>
<h:selectOneRadio id="persRadio1" value="#{personList.person}">
<f:selectItems value="#{personList.allPersons}" />
</h:selectOneRadio>
<h:message for="persRadio1" />
<br />
Rsultat:
<h:outputText value="#{personList.person}" />
<br /><br />
122
Created by XMLmind
XSL-FO Converter.
The result :
Notice: error message should be displayed in English if your web browser is configurer in English. Indeed, JSF
is completely internationalized in almost 10 languages (including Chineese).
Take a look at the following HTML code :
[CODE:xhtml]Jo Johnson <input type="radio" value="Jo Johnson" />
Raymond Schmitt <input type="radio" value="Raymond Schmitt" />
Bob LeNain <input type="radio" value="Bob LeNain" />
We can see here that the value of the radio buttons (attribute value in HTML code) uses the method toString ()
of the class Persson. That means if JSF page is translated into HTML, the objects of type Person are translated
into a String thanks to the method toString (). But when the tree of JSF components must be rebuilt, the JSF
Servlet does not know how to reinstantiate the object Persson from this String. Therefor it is necessary to create
a converter which will take care of this translation.
To create the converter, we are using the "Person" identifier.
[CODE:java]package com.labosun;
public class PersonConv implements Converter {
...
/**
* @param value person " id ".
* @return an object related to the id
*/
public Object getAsObject(FacesContext ctx, UIComponent component, String value) {
int id = Integer.valueOf(value);
for (Person p : PERSONS_LIST) {
if (p.getId() == id) {
return p;
}
}
return null;
}
/**
* @param value A " person " object.
* @return " id " of the person.
*/
public String getAsString(FacesContext ctx, UIComponent component, Object value) {
if (value == null || !(value instanceof Person)) {
return "";
}
return "" + ((Person) value).getId();
}
}
123
Created by XMLmind
XSL-FO Converter.
<converter-class>com.labosun.PersonConv</converter-class>
</converter>
Everythings works very well for the first 2 instances, but when the 3rd button is selected, the following error
occurs:
The radio button value use identifiers related to the objects. The error message specific to the 3rd button occurs
because JSF will check if the object returned by the converter belongs well to the list of the items. This checking
is done using the methods hashCode () and equals ().
In our case, our converter returns instances coming from object "PERSONS_LIST", and then JSF will check if
the returned instances belong tothe list "allPersons". But, remember that only the first 2 instances of the list
"allPersons" come from list "PERSONS_LIST". As the class Persson does not redefine the methods hashCode ()
and equals (), it is those of the class Object which are used. This means that the equality is only based on the
equality of the references (==). So this only works for the 2 first instances.
So that this works for all the cases, it is enough to implement these 2 methods in the class Person:
[CODE:java]public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
return this.getId() == ((Person) o).getId();
}
public int hashCode() {
return this.getId();
}
1.7.4. Validation
JSF makes it possible to validate all the data seized by the user. The validation is only possible for the
124
Created by XMLmind
XSL-FO Converter.
components which implement EditableValueHolder. I.e. the text fields, the checkboxes, the radio buttons, the
lists and the comboboxes.
The validation is carried out during the phase "Validation of the user entries". Attention, during this one, all the
elements are not yet up to date (the javabeans are updated only during the "Update model" phase). If there are
several validations, the order of treatments of the validations is the order of the tag declarations.
Note: If the component which declares the validation has the attribute "immediate" set to true, then the
validation is treated during the phase "Request parameters application". That makes it possible to force a
validation to be done before all the others. For example, a person wishes to be recorded on a site. It must seize
the country and the city in which it lives. The validation of the country can be made immediately to be sure that
the validation of the city is considering the country.
To force the user to seize a value, you can set the attribute "required" to true.
Example:
[CODE:xhtml]<h:inputText required="true" />
To carry out a more precise control on the data, a validator should be used. JSF provides 3 standard validateurs.
They are usable thanks to the tags:
Here the entire form will not be validated if the value entered for this field text does not have a length ranging
between 3 and 10.
The validation errors are posted by the tag <h:message>.
1.7.4.1. Custom validator
It is possible to create its own validator. There are 2 manners of making it, either by using a method, either by
implementing the interface " javax.faces.validator.Validator ".
1.7.4.1.1. Generic method
Any JavaBean can declare the method, but it must be referred as JavaBean is managed by the container.
125
Created by XMLmind
XSL-FO Converter.
The method which manages the validation must have the following prototype:
[CODE:java]public void validate(javax.faces.context.FacesContext context, javax.faces.component.UIComponent
component, Object value) {
//Event handling
}
1.7.4.1.2. Interface
It is necessary to implement the interface javax.faces.validator.Validator . The only method to redefine :
[CODE:java]public void validate(FacesContext context, UIComponent component, Object value);
To use this validator, it should be declared in the file "faces-config. xml" using the tag <validator>.
Example :
[CODE:xml]<validator>
<!-- validator identifier -->
<validator-id>emailValidator</validator-id>
<!-- validator class -->
<validator-class>com.labosun.validation.EmailValidator</validator-class>
</validator>
The validator can then be used thanks to the tag <f:validator>, the attribute "validatorId" must refer the identifier
of the validator.
Example :
[CODE:xhtml]<h:inputText>
<f:validator validatorId="emailValidator" />
</h:inputText>
The last thing to do is to write the code of the page and to refer the method of our bean by using the attribute
126
Created by XMLmind
XSL-FO Converter.
Validator.
[CODE:xhtml]<h:form>
<h:inputText id="emailMethod" validator="#{beanMail.checkEmail}">
<h:outputLabel for="emailMethod" value="Email:" />
</h:inputText>
<h:message for="emailMethod" />
<br />
<h:commandButton value="Vrifier l'email" />
</h:form>
If a text which was entered does not contain an "@", the tag <h:message> posts the message "an email must
contain an @"..
The attribute basename indicate the name of the properties file who will be used. Caution, if the file is in a
package, you will need to prefix the file by the package name. The attribute var will be used in the page to
reach the ressources file.
We reach one key defined in the ressources file like this :
[CODE:xhtml]<h:outputText value="#{variable.keyName}" />
Example:
We have a properties file called SiteMessages.properties in the com.labosun package. This properties file
contains this line :
message=hello
In this case, the locale used will be the locale of the users. If you want to change the default locale, you need to
use this code in the file faces-config.xml :
[CODE:xml]<application>
<localeconfig>
<defaultlocale>en</defaultlocale>
</localeconfig>
</application>
The chapter 8.1.3 Example: Change language button explain how change the locale.
1.8.1.1. Dynamic internationalization
It is sometimes need to reach a properties file from a JavaBean. To do this, it is necessary to use the getBundle
method from the RessourceBundle method. The first attribute of this method is the name of the properties file,
and the second is the locale we want to use.
[CODE:java]FacesContext context = FacesContext.getCurrentInstance();
String basename = "conf.SiteMessages";
127
Created by XMLmind
XSL-FO Converter.
1.8.1.2. Encoding
Normalement la notion dencodage a dj t vue dans le cours JSP, mais pour rappel, il est possible de changer
lencodage des pages grce la directive de page :
The encoding concept has already been seen, but for recall, it is possible to change the encoding of apages with
the following attributes:
[CODE:xml]<%@ page pageEncoding="UTF8" contentType="text/html; charset=UTF8" %>
By default it is the value ISO-8859-1 which is used. The list of available encoding is on the page:
http://java.sun.com/j2se/1.4.2/docs/guide/intl/encoding.doc.html
1.8.1.3. Example: Change language button
In this example, we will sight how changed the site language, when an user click on a link. Starting with make
the Web page. The current locale will be shown and 4 link will perform the language change.
[CODE:xhtml]<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<body>
<f:view>
<%-- We load the properties file --%>
<f:loadBundle basename="com.labosun.i18n.ChangeLocaleRB" var="change" />
<%-- Print the current locale --%>
<h:outputText value="#{change.currentLocale} #{changeBean.changeLocale}" />
<br />
<h:form>
<%-- Link to change language --%>
<h:commandLink id="FR" value="#{change.french}"
actionListener="#{changeBean.changeLocale}" /><br />
<h:commandLink id="US" value="#{change.english}"
actionListener="#{changeBean.changeLocale}" /><br />
<h:commandLink id="CA" value="#{change.canadian}"
actionListener="#{changeBean.changeLocale}" /><br />
<h:commandLink id="DE" value="#{change.deutsch}"
actionListener="#{changeBean.changeLocale}" /><br />
</h:form>
</f:view>
</body>
</html>
This page use properties files. Here is the contents of 2 properties files ( english and french ) :
File ChangeLocaleRB_fr.properties :
currentLocale=La Locale actuelle est
french=Franais
english=Anglais
canadian=Canadien
deutsch=Allemand
File ChangeLocaleRB_en.properties :
currentLocale=The current Locale is
french=French
english=English
128
Created by XMLmind
XSL-FO Converter.
canadian=Canadian
deutsch=Deutsch
We need now to write the JavaBean who will perform the language change :
[CODE:java]package com.labosun.i18n;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import java.util.Locale;
public class ChangeBean {
/**
* Contains the current locale
*/
private Locale currentLocale = FacesContext.getCurrentInstance().
getViewRoot().getLocale();
public Locale getCurrentLocale() {
return currentLocale;
}
/**
* Change the locale of the current view.
* @param newLocale La nouvelle Locale
*/
public void setCurrentLocale(Locale newLocale) {
FacesContext.getCurrentInstance().getViewRoot().setLocale(newLocale);
this.currentLocale = newLocale;
}
public void changeLocale(ActionEvent ae) {
String id = ae.getComponent().getId();
Locale newLocale = null;
// we get all available locale
Locale[] locales = Locale.getAvailableLocales();
for (int i = 0; newLocale == null && i < locales.length; i++) {
if(locales[i].getCountry().equals(id)) {
newLocale = locales[i];
}
}
if (newLocale == null) {
newLocale = Locale.getDefault();
}
setCurrentLocale(newLocale);
}
}
129
Created by XMLmind
XSL-FO Converter.
[CODE:java]package com.labosun.message;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
public class MessageBean {
private UIInput nameInput;
public UIInput getNameInput() {
return nameInput;
}
public void setNameInput(UIInput nameInput) {
this.nameInput = nameInput;
}
public void check(ActionEvent ae) {
FacesContext context = FacesContext.getCurrentInstance();
//Retrieve component id
String nameId = nameInput.getClientId(context);
FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_WARN, "Global message summary", "message
from MessageBean");
context.addMessage(null, f);
FacesMessage f2 = new FacesMessage(FacesMessage.SEVERITY_INFO, "Specific message summmary", "message
from MessageBean and specific to component 'name'");
context.addMessage(nameId, f2);
}
}
The attribute nameInput will be linked with a component for recovered its identifier. The check method is
used as ActionListenener. It is it which make the two messages f and f2 . The first message is global
since one does not use an identifier at the context addition. The second message is specific to the component
nameInput . To link the attribute nameInput with the component of text type in the JSF page, we need to
use the attribute binding .
[CODE:xhtml]<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<f:view>
<h:messages globalOnly="true" showDetail="false" showSummary="true"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
<h:form>
<h:inputText id="name" size="10" binding="#{messageBean.nameInput}">
<h:outputLabel for="name" value="Name:" />
</h:inputText>
<h:message for="name" styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
<h:commandButton value="Valider" actionListener="#{messageBean.check}"/>
<br />
<h3>List</h3>
<h:messages showDetail="true" showSummary="true"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
<h3>Table</h3>
<h:messages showDetail="true" showSummary="false" layout="table"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
</h:form>
</f:view>
</body>
</html>
130
Created by XMLmind
XSL-FO Converter.
</managed-bean>
converterMessage : define the message when the value of the component can't be convert.
validatorMessage : define the message used when the entered value is not validated by the component.
For all others messages and for JSF 1.1, the default errors messages are in the Message_fr.properties
properties file, who is in the java.faces package, of jsfimpl.jar jar file. It is impossible to redefine these
messages by creating a new properties file with the same keys. This new file can be anywhere in your
application. We will then define it to replace the default file.
For example, we will create the MyDefaultMessages_fr.properties file, in which, we will copy the
keys/values of the original Message_fr.properties file.
javax.faces.component.UIInput.REQUIRED= Validation error : You must enter a value.
javax.faces.validator.LengthValidator.MAXIMUM= Validation error : the value is superior to the maximum authorized : ,
''{0}''
You will notice that all special characters are unicode. In these messages, syntax "{0}" allows insert of
parameters. This uses the MessageFormat class.
Now, we will put these messages:
javax.faces.component.UIInput.REQUIRED= Personalized message : This field is required.
javax.faces.validator.LengthValidator.MAXIMUM= Personalized message : The value ''{0}'' is superior to the maximum
authorized for this field.
This file is used in place of the default file. It is defined in the JSF configuration file:
[CODE:xml]<faces-config>
<application>
<locale-config>
<default-locale>fr</default-locale>
</locale-config>
<message-bundle>MyDefaultMessages</message-bundle>
</application>
</faces-config>
131
Created by XMLmind
XSL-FO Converter.
Is is also possible to use ressources injection to get an instance on JNDI current context and to seek then the
EJB.
Example:
[CODE:java]@Resource
private SessionContext ctx;
Store store = (Store)ctx.lookup("Store");
1.9. Facelets
1.9.1. Introduction
JSF was designed to work with JSP, but it is obvious there are numerous problems when both are mixed. To
only quote one, the unified language EL should be used in two different ways according to the JSP or JSF
context (syntax ${} and #{}).
The Facelets goal is to create a set of tags that are well matched with JSF and also give a new way to write JSF
code. It does not add new internal mechanisms to JSF, but settles to easy the writing of code by letting code
template creation.
Facelets works with the JSF implementations 1.1 and 1.2 of Sun and Apache MyFaces.
Facelets also provides the following enhancements:
132
Created by XMLmind
XSL-FO Converter.
Simple configuration
Let to use JSF tags as standard HTML ones (attribute jsfc, see the chapter "JSFC")
To understand what brings Facelets, we have to come back to the life cycle of a Web page. JSF was designed to
be modular, this means it is possible to change some components in the JSF internal. Facelets deals with
replacing view components, ie. the phases "View Restoration" et "Reply Rendering". Other phases stay
unchanged.
Here is a reminder of the life cycle. Yellow parts are managed by Facelets:
Thanks to the control of those two phases, all the syntax of the files can be changed and entirely retought by
Facelets.
1.9.2. Configuration
In this chapter, we will see how to install and configure Facelets to use it in a project.
1.9.2.1. Installation
First of all, you should download the last implementation of Facelets at this address:
https://facelets.dev.java.net/
This lesson is based on version "1.1.11".
You then have to uncompress the archive and get the file "jsf-facelets.jar". In the case where you do not use a
JEE 5 server, you should take the files "el-api.jar" and "el-ri.jar" that are placed in the directory "lib".
1.9.2.2. Project Structure
Facelets respects the same structure as a standard JSF application. The only difference is the extension of Web
pages, it is ".xhtml". This extension is not mandatory, but the syntax of Facelets follow the xHTML format. It is
then more logical to use that extension.
The structure of a War file stays the same as for JSF. Here it is:
Table 2.15.
133
Created by XMLmind
XSL-FO Converter.
WEB-INF/classes
WEB-INF/lib
WEB-INF/faces-config.xml
Configuration file.
WEB-INF/web.xml
*.xhtml
1.9.2.3. Configuration
We are now going to see modifications to do to the files "faces-config.xml" and "web.xml" pour to be able to
use Facelets.
First of all, we will define the extension ".xhtml" as pages extension. As seen in the chapter "Context parameters
", we shall use the context parameter "javax.faces.DEFAULT_SUFFIX".
[CODE:xml]<web-app>
<!-- Extension .xhtml for JSF pages -->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!--Specific parameter to Facelets. Useful for development -->
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
In the following examples, the suffit ".jsf" is used. This allows to call a page by replacing the extension ".xhtml"
by ".jsf". To remind you, here is how to declare it:
[CODE:xml]<web-app>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</webapp>
We now need the JSF Servlet forward calls to Facelets for the view management. This is done in the file "facesconfig.xml":
[CODE:xml]<faces-config>
<application>
<view-handler>
com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config>
Thanks to this configuration, the view management (creation of the JSF component tree, rendering of the reply)
will be managed by Facelets and not by the JSF implementation anymore.
XSL-FO Converter.
The first different in relation to a classical JSF page is that the taglibs declaration is different.
Here, we declare all the libraries like namespaces in the <html> tag.
The expression "xmlns:ui=http://java.sun.com/jsf/facelets" allows to use all the Facelets tags. Whereas the two
next ones allow to use the JSF libraries.
There is no tag <f:view>. Finally, it is possible to use an EL expression directly in the HTML code. For
instance, the code "#{param.f}" displays directly the value of the parameter "f".
If we execure this page by setting the parameter "f=Facelets" in the URL, we get the text:
Hello Facelets
This is an example assuming "JSFCoursFacelets" if the context of the project and "Hello.jsf" is the name of the
page. We must use the URL: http://localhost:8080/JSFCoursFacelets/Hello.jsf?f=Facelets .
1.9.3.2. JSFC
One of the problems that arise with the JSF tags is that editors do not all know how to render a page in a
graphics way. However, most of code editors know how to display an HTML page.
One of the possibilities offered by Facelets is to display the result of a page as HTML and without it being
executed on the server. This is done thanks to the attribute "jsfc".
Let us see an example:
[CODE:xml]<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>Form with JSFC</title>
</head>
<body>
<form jsfc="h:form">
<input id="name" type="text" jsfc="h:inputText" value="#{bean.name}" required="true">
<label for="name">Name:</label>
</input>
<h:message for="name" />
<br />
<button type="submit" jsfc="h:commandButton" value="Validate" />
</form>
</body>
</html>
Let us take the tag <form jsfc="h:form">, Facelets will do the interpretation as a tag <h:form>, but from a code
editor perspective it is only a simple <form> tag. The attribute "jsfc" serves to define the real type of the tag.
The advantage here is to be able to work with standard HTML tags and let let editors graphically display them
in a simple editor.
135
Created by XMLmind
XSL-FO Converter.
Attributes specifics to a JSF tag should be added to the HTML tag. An HTML editor will certainly indicate that
the attribute does not exist for that tag, but it will work correctly for Facelets. This is the case for the attribute
"required" for the tag <input>.
For the JSF tags that do not have HTML equivalents like the tag <h:message> for instance, we should include it
directly in the code.
We then get a mix of HTML and JSF tags, without forgetting that we always still can add EL expressions
directly in the HTML code.
1.9.3.3. Template
A template is a Facelets code that can be reused. Templates will be applied at wish in the site. this is the
equivalent of a tag, except that a template is written in a very simple manner and is more easily modular. A page
that uses a template is named a "calling page". We will later see that there are several manners to use a template.
This lesson part is only concentrating on the basic declaration of a template.
Every Facelets file can serve as a template. By default, this is all of a page that defines a template.
Template1.xhtml:
[CODE:xml]<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title></title>
</head>
<body>
</body>
</html>
Here, the entire page is considered as a template. To only use a portion of code as a template, we must use the
tag <ui:composition>.
Template2.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title></title>
</head>
<body>
<ui:composition template="Template1.xhtml">
</ui:composition>
</body>
</html>
The result of this example will be that the content of the page "template1.xhtml" will be displayed on the client.
This example is quite limited because it is equivalent to the inclusion of a page. We will see in the next chapter
how to create and use modifiable templates.
In this example, all the tags of the pages that use the template are ignored. This behavior is specific to the tag
<ui:composition>, the chapter "Facelets" will present other tags to use templates.
XSL-FO Converter.
done in practice.
One of the most occurring problems during the creation of a Web site is that every page should redefine all the
page layout of the site. Ie. redefine the title, the menu, the footer... Those elements are often the sames for every
pages of the site. It is more practical to only declare them once and that they get integrated directly to other
pages.
Facelets allow to do that thanks to its template system. Let us see how it works with a first example
First of all, we must write the template page. it will describe the structure of the site and the elements that other
pages can modify. In our example, we will create a site that contains a header, a menu, a body and a footer.
MainTemplate.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>
<ui:insert name="Title">Default Title</ui:insert>
</title>
</head>
<body>
<div style="background: cornflowerblue; position: absolute; left: 0%; right:0%; bottom: 95%; top: 0%">
<ui:insert name="Header">
<ui:include src="Header.xhtml" />
</ui:insert>
</div>
<div style="background: darksalmon; position: absolute; left: 0%; right: 90%; bottom: 5%; top: 5%;">
<ui:insert name="Menu">
<a href="">Default Menu 1</a><br />
<a href="">Default Menu 2</a><br />
<a href="">Default Menu 3</a><br />
</ui:insert>
</div>
<div style="position: absolute; left: 10%; right: 0%; bottom: 5%; top: 5%;">
<ui:insert name="Body">
Default Body
</ui:insert>
</div>
<div style="background: lawngreen; position: absolute; left: 0%; right: 0%;bottom: 0%; top: 95%">
<ui:insert name="Footer">
Default Footer
</ui:insert>
</div>
</body>
</html>
There are two tags specific to Facelets in this template page, <ui:insert> and <ui:include>. First, the tags
<ui:insert> allow to define the modifiable parts of the template. Each tag use a name to uniquely identify the
part
In the case of the tag:
[CODE:xhtml]<ui:insert name="Footer">
Default Footer
</ui:insert>
It defines all the footer part that is modifiable. The text "Default Footer" is the text displayed by default, when
another page that use the template to not modify the footer.
For the tag:
[CODE:xhtml]<ui:insert name="Header">
<ui:include src="Header.xhtml" />
137
Created by XMLmind
XSL-FO Converter.
</ui:insert>
It does not define directly the default header, but import a file that contains the default text. The import is done
with the tag <ui:include>.
HeaderTemplate.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title></title>
</head>
<body>
<ui:composition>
Default Header
</ui:composition>
</body>
</html>
This page contains the default code for the header. The tag <ui:composition> is used to define a bloc of code
that can be reused in other pages. In fact, all the code that is arround the tag <ui:composition> is ignored, that
means that it will never appear in an HTML page received by the client. This behavior is due to the tag
<ui:include> that ignores the rest of the page as soon as it finds a tag <ui:composition>. We will see the
inclusion principle in detail in the chapter " 1.4.5 Include ".
Our template is now read, we can create the page that will use the template.
PageMain.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>Main Page</title>
</head>
<body>
<ui:composition template="MainTemplate.xhtml">
<!-- A tag define must match a <ui:insert> tag in the template -->
<ui:define name="Title">Main Page</ui:define>
<ui:define name="Footer">Footer</ui:define>
<ui:define name="Body">Redefined body of the page</ui:define>
</ui:composition>
</body>
</html>
It uses the attribute "template". In this case, it does not serve to declare a template (like in
HeaderTemplate.xhtml) but to precise that we want to use an existing bloc of code.
In our case, we begin by taking all the code of the page of the attribute "template", "MainTemplate.xhtml".
Then, we replace the modifiable parts (bodies of the tags <ui:insert>) by the content of the tags <ui:define>.
Here, we do not modify the parts "Title", "Footer" and "Body". The order of the tags "define" does not matter. It
is not mandatory to redefine all parts.
138
Created by XMLmind
XSL-FO Converter.
If "JSFCoursFacelets"
http://localhost:18080/JSFCoursFacelets/PageMain.jsf
The graphical result is:
Be Careful: In the last page "PageMain.xhtml", every tags <ui:define> that is outside of the dirst
<ui:composition> tag are ignored. Moreover, all the code that is not inside valid <ui:define> tags are also
ignored. Ie. the following code will generate the same HTML page. All grayed parts are not included in the
HTML page that the client receives.
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>Main Page</title>
</head>
<body>
<!-- Ignored tag -->
<ui:define name="Title">Title not took into account</ui:define>
<!-- Only one composition tag is valid -->
<ui:composition template="MainTemplate.xhtml">
<!-- Valid define tag -->
<ui:define name="Title">Main Page</ui:define>
This text is ignored
<!-- Valid define tag -->
<ui:define name="Footer">Footer</ui:define>
<!-- Valid define tag -->
<ui:define name="Body">Redefined body of the main page</ui:define>
</ui:composition>
<!-- Ignored tag -->
<ui:define name="Menu">Menu not took into account</ui:define>
<!-- This composition tag is completely ignored -->
<ui:composition template="MainTemplate.xhtml">
<ui:define name="Menu">Menu</ui:define>
<ui:define name="Body">The body, again.</ui:define>
</ui:composition>
</body>
139
Created by XMLmind
XSL-FO Converter.
</html>
The working of the different tas will be reviewed in detail in the rest of the lesson. It is possible, from this
exemple, to create a skeleton of page that you can reuse as you wish.
It is possible to use <ui:insert> tags to define what zones of the template are modifiables.
1.9.5.1.2. Template Usage
A template can be used with the tag <ui:composition>. In this case, the attribute "template" must define the
URL to the files of the template to use. The usage of a template follow those rules:
If the template file contains one or several <composition> tags then only the body of the first tag is took into
account,
140
Created by XMLmind
XSL-FO Converter.
UseTemplateWithComposition.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title></title>
</head>
<body>
<ui:composition template="TemplateWithComposition.xhtml">
<ui:define name="Header">header</ui:define>
<ui:define name="Body">Redefined body of the main page.</ui:define>
</ui:composition>
</body>
</html>
Here, we see well that everything that is around the tags <ui:composition> is ignored.
1.9.5.1.4. Insert
The tag <ui:insert> can be used in templates. It defines a portion of code that can be replaced. The attribute
"name" let you identify that portion. The replacing is then done by the tag <ui:define> that have an attribute
"name" too. There only need to match both to do a replacement.
Example:
[CODE:xhtml]<ui:insert name="Partie1">
Modifiable part.
</ui:insert>
It is also possible to use the tag without specifying a name. In this case, all the body of the tags that uses the
template will be included.
Example without name:
ParagraphTemplate.xhtml:
[CODE:xhtml]Start of paragraph
<ui:insert />
End of paragraph
Page.xhtml:
[CODE:xhtml]<ui:composition template="Paragraph.xhtml">
Middle of paragraph
</ui:composition>
141
Created by XMLmind
XSL-FO Converter.
End of paragraph
1.9.5.1.5. Define
The tag <ui:define> allow to replace the content of a tag <ui:insert>. It has the mandatory attribute "name" that
must match a name of a <ui:insert> tag.
1.9.5.1.6. Decoration
The tag <ui:decoration> allow to use a template. It works like the tag <ui:composition> except that all the code
of the calling page is included in the reply. We have the same page of template as in the chapter "Example".
TemplateWithComposition.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title></title>
</head>
<body>
<ui:composition>
<div style="...">
<ui:insert name="Header">Header</ui:insert>
</div>
<div style="...">
<ui:insert name="Body">Default body</ui:insert>
</div>
</ui:composition>
</body>
</html>
UseTemplateWithDecoration.xhtml:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>Page principale</title>
</head>
<body>
<ui:decorate template="TemplateWithComposition.xhtml">
<ui:define name="Header">Header</ui:define>
<ui:define name="Body">Redefined body of the main page</ui:define>
</ui:decorate>
</body>
</html>
142
Created by XMLmind
XSL-FO Converter.
Header
</div>
<div style="...">
Redefined body of the main page
</div>
</body>
</html>
1.9.5.1.7. Include
The tag <ui:include> allow to include a Facelet page. It have the mandatory attribute "src" that designate the
page to include. The name of the page can be wrote directly ou it can be an EL expression.
Example that allow to include the page "Footer.xhtml":
[CODE:xhtml]<ui:include src="Footer.xhtml" />
If the file to include contains one or several tags <composition> then only the content of the first tag is took
into account.
name
value
1.9.5.1.9. Remove
The tag <ui:remove> allow to not take into account all the code that is in its body. This is like a comment on a
whole bloc (like /* and */). But this solution has the advantage to not have to comment every single line of code.
Example:
[CODE:xhtml]<body>
<h:outputText value="affich" />
<ui:remove>
<h:outputText value="Not displayed" />
<form>
<%-- <h:outputText value="Not displayed again" /> --%>
<!-- <input type="text" /> -->
<button type="submit" />
</form>
</ui:remove>
<h:outputText value="Displayed" />
</body>
Here, all the part inside <ui:remove> is not took into account.
1.9.5.1.10. Component
143
Created by XMLmind
XSL-FO Converter.
The tag <ui:component> is identical to <ui:composition>, except that all the body of the tag is included in a JSF
component that we can use. To use it, we should use the attribute "bindings".
1.9.5.1.11. Fragment
The tag <ui:fragment> is identical to <ui:component> in its working, but, like the tag <ui:decorate>, the tags of
the calling page will be included in the final reply.
1.9.5.1.12. JSTL and Fonctions Tags
Facelets proposes an implementation of JSTL Core taglibs and of functions.
1.9.5.1.12.1. JSTL Core
To
use
the
tags
JSTL
Core,
"xmlns:c="http://java.sun.com/jstl/core""
we
should
declare
the
following
namespace:
Mandatory
Description
test
Yes
var
No
Example:
[CODE:xhtml]<c:if test="#{user.roles['admin']}">
</c:if>
Description
items
var
begin
end
step
varStatus
boolean first
boolean last
int begin
int end
int index
144
Created by XMLmind
XSL-FO Converter.
Attribute
Description
int step
Description
var
value
1.9.5.1.12.2. Functions
To
use
the
functions,
we
should
"xmlns:fn="http://java.sun.com/jsp/jstl/functions"".
declare
the
following
namespace:
145
Created by XMLmind
XSL-FO Converter.
1.9.6.3. TagFile
To use this component template with to a tag, we must add it in a declaration file. The file must have the
extension ".taglib.xml".
labo-sun.taglib.xml:
[CODE:xml]<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.labo-sun.com/jsf</namespace>
<tag>
<tag-name>case</tag-name>
<source>CaseComponent.xhtml</source>
</tag>
</facelettaglib>
This declaration will allow to use our template with a tag of this kind:
[CODE:xhtml]<case columnName="" sortMethod="" caseValue="" bean="" />
The attributes of the tag are determined from the variables that are used in the template page. For Facelets to
load the file, we must add the following declaration in the file web.xml:
[CODE:xml]<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/facelets/tags/arcmind.taglib.xml</param-value>
</context-param>
Declaration:
[CODE:xml]<managed-bean>
<managed-bean-name>beanTable</managed-bean-name>
<managed-bean-class>com.labosun.facelets.BeanTable</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
[CODE:java]public class BeanTable {
private List<Person> persons;
private static Comparator<Person> personLastNameComparator = new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o1.getLastName().compareTo(o2.getLastName());
}
};
private static Comparator<Person> personFirstNameComparator = new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o1.getFirstName().compareTo(o2.getFirstName());
}
};
public BeanTable() {
persons = new ArrayList<Person>();
persons.add(new Person("Bob", "Gnoliac"));
persons.add(new Person("Thomas", "Anderson"));
persons.add(new Person("Raymond", "Smith"));
}
//Getter et setter
146
Created by XMLmind
XSL-FO Converter.
That's all, our tag is ready to be used. The declaration is done with namespaces like that:
[CODE:xhtml]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:m="http://www.labo-sun.com/jsf">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF8"/>
<title>Test column template</title>
</head>
<body>
<h:form>
<h:dataTable value="#{beanTable.persons}" var="person" border="1" rules="all">
<m:case columnName="Last name" sortMethod="sortByLastName"
caseValue="#{person.lastName}" bean="#{beanTable}" />
<m:case columnName="First name" sortMethod="sortByFirstName"
caseValue="#{person.firstName}" bean="#{beanTable}" />
</h:dataTable>
</h:form>
</body>
</html>
Table 2.19.
Sort by Last Name
1.9.7. Parameters
Table 2.20.
Parameters
Description
facelets.LIBRARIES
List of paths to libraries of Facelets tags separated by
";". The paths are relative to the root of the applciation.
A library is loaded only when the page that use it
should be compiled.
Example:
/WEB-INF/facelets/my.taglib.xml;
/WEB-INF/facelets/car.taglib.xml;
facelets.DECORATORS
XSL-FO Converter.
Parameters
Description
first query will get to the view "FaceletViewHandler".
Example: com.sun.facelets.tag.jsf.html.HtmlDecorator
facelets.DEVELOPMENT
facelets.BUFFER_SIZE
facelets.REFRESH_PERIOD
facelets.RESOURCE_RESOLVER
facelets.VIEW_MAPPINGS
1.10. Bibliography
JSF tags documentation:
JSF 1.1 : http://java.sun.com/j2ee/javaserverfaces/1.1/docs/tlddocs/index.html
JSF 1.2 : http://java.sun.com/j2ee/javaserverfaces/1.2/docs/tlddocs/index.html
JSF javadoc:
JSF 1.1 : http://java.sun.com/j2ee/javaserverfaces/1.1/docs/api/index.html
JSF 1.2 : http://java.sun.com/j2ee/javaserverfaces/1.2/docs/api/index.html
Sun
tutorial
for
J2EE
1.4
which
includes
tutorial
for
JSF
1.1:
tutorial
for
JSF
1.2:
http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html
Sun
tutorial
for
JEE
5.0
which
includes
http://java.sun.com/javaee/5/docs/tutorial/doc/index.html
Facelets homepage: https://facelets.dev.java.net/
MyFaces homepage: http://myfaces.apache.org/index.html
Oracle
ADF
http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/index.h
tml
148
Created by XMLmind
XSL-FO Converter.