Introduction
The last
section looked installing all the required software to develop
enterprise applications. In this installment, an example JEE application
starts to be developed.
The example application is called MyCV, the goal is to allow users to
register, and edit their personal details. An option to generate
a CV as HTML or in an other format is made available. Such an application,
while being relatively simple, is good enough to cover most issues
encountered in the development of JEE applications, namely:
- JSP and JSF, for the presentation layer (Web pages)
- EJB's for the business logic
- JAAS for security and authentication
- Internationalization for multiple language support
- Using third party libraries
In this installment, Java Server Faces and internationalization
are introduced.
The source code for this chapter can be downloaded as a zip archive
from
here.
Before starting this installment, JBoss, Eclipse and the JBoss Eclipse
IDE plug-in should be installed and configured correctly, as explained
in the previous installments.
Create The Project
In Eclipse a new EJB 3 project is created.
Next is pressed and MyCV is entered as the project
name.
Next is pressed, and the existing JBoss configuration
is selected. If no JBoss configuration exists, how to create a
configuration is covered here.
Finish is clicked, and the project is created.
Create The Web Application Deployment Descriptor
A new web application deployment descriptor is created
by right clicking the project folder in the package explorer, and
selecting new->other. The Web Application 2.4 Deployment Descriptor
is selected, and next is clicked:
The src folder is selected as the folder where the
new file called web.xml will be created, finish is clicked:
Create A JSF Library
The JBoss installation includes JSF 1.1.To make
use of this, a new user library is created in JBoss. The project
properties dialog is selected, within this, the Java Build path
is selected, then the project libraries tab is clicked:
Add library is clicked in the above dialog.
User library is selected, as this is a new "user"
library that is being created.
In the "User Libraries" dialog, the "New..." button
is pressed.
The name of the library given is JBossJSF, as it
will include the jar files that JBoss includes in its installation.
When the above dialog is dismissed, by clicking on OK, the "Add
Jars..." button is clicked in the "User Libraries" dialog.
The jar files to add to this library can be found
in a JBoss folder, below the root installation of JBoss called
server/default/deploy/jbossweb-tomcat55.sar/jsf-libs.
All the files in this folder are selected and added to the library,
then OK is clicked. All the subsequent dialogs are dismissed by
clicking on OK or Finish. This completes the creation of the JSF
user library.
Configure The Project Web.xml File
In order to use Java Server Faces, the web application
deployment descriptor needs to be altered to look like the one
shown below:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>MyCV</display-name> <listener> <listener-class>
org.apache.myfaces.webapp.StartupServletContextListener
</listener-class> </listener> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <servlet> <display-name>FacesServlet</display-name> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> </web-app>
The above enables JSF in the web application. In
addition, the application's display name is given, and the JSF
state saving method is set to "server".
The STATE_SAVING_METHOD can
be either "client" or "server". The client value
means that the entire state is saved in a hidden field on each
page page. The server value means that the state is saved
on the server. For large applications, saving the state on the
client may become problematic, hence saving on the server is usually
the best option.
Create An Error Page
When developing web applications, an error page
can prove to be very valuable. The error error page, shown below,
is used to display an exception message and a stack trace. It is
usually displayed if there is a bug in the code, or the if system
is not behaving correctly. The errors generated when the user enters
incorrect values should not use the error page.
Some errors generate a stack trace
in Eclipse's console window (and JBoss' log file), but others
do not. When creating JSF pages, it is common to mistype something
or forget to include an attribute. When the application is run,
the JSF page in question cannot be displayed, instead the error
page is displayed and the error message is usually a good indicator
of what needs to be fixed in the JSF page. For these reasons, it
is well worth creating the error page early on in the project.
A new JSP file called errorpage.jsp is created in
the src/web folder of the project:
<%@ page isErrorPage="true" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <link href="styles.css" rel="stylesheet" type="text/css"> </head> <body> <div class="errorMessage"><%= exception.getLocalizedMessage() %></div> <pre class="errorStackTrace"> <% java.io.CharArrayWriter cw = new java.io.CharArrayWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(cw, true); exception.printStackTrace(pw); out.println(cw.toString()); %> </pre> </body> </html>
It is usually recommended to put as little code as possible in the error
page, so that there is less chance of the error page generating an
error.
Now that the error page is done, the rest of the application can be
developed.
The Default index.jsp
Whenever the application is accessed without specifying
a page, index.jsp is accessed. This jsp is used to forward the
user to the welcome page.
A new JSP in the src/web folder is created, called
index.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <jsp:forward page="/welcome.faces" /> </body> </html>
The page above forwards to the application's welcome page.
The Style Sheet
A style sheet file called styles.css is created in the src/web folder.
JSF allows the use of styles with its tags. The style sheet created
looks like this:
body, div, td, span, li, input {
font-family: Arial, Helvetica;
font-size: 12px;
}
th {
font-size: 14;px
}
.center, .pageTitle, .form {
position: relative;
margin: 0 auto;
text-align: center;
}
.pageTitle {
font-size: 18px;
font-weight: bold;
}
.form {
border:2px solid black;
}
.tableHeader {
background-color: #E0E8E8;
}
.tableFooter {
background-color: #E0E8E8;
}
.tableRowOdd {
background-color: #FFFFFF;
}
.tableRowEven {
background-color: #EEF0F0;
}
a {
text-decoration: none;
color: #337799;
font-weight: bolder;
}
a:hover {
text-decoration:underline;
color: #FF5555;
font-weight: bolder;
}
td {
text-align: left;
}
.errorMessage {
color : #FF0000;
font-weight: bolder;
}
.errorStackTrace {
color : #000000;
}
.formUserError {
color : #FF0000;
font-weight: bolder;
}
The Welcome Page
The welcome page allows the user to select a language
to use, register and logon to the site. As a first step, the language
selection is done. The additional steps of logon and registering
are covered in a later installment.
A new JSP file called welcome.jsp is created:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ page errorPage="errorpage.jsp" %> <f:view> <f:loadBundle basename="com.j3ltd.web.messages.ApplicationMessages" var="msg"/> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title><h:outputText value="#{msg.pageTitle}"/></title> <link href="styles.css" rel="stylesheet" type="text/css"> </head> <body> <h:form > <div class="pageTitle"><h:outputText value="#{msg.welcome}"/></div> <br/> <h:panelGrid columns="3" styleClass="center" style="border:2px solid black" headerClass="tableHeader"> <f:facet name="header"> <h:outputText value="#{msg.welcomeBoxTitle}"/> </f:facet> <h:outputText value="#{msg.login}"/> <h:outputText value="#{msg.register}"/> <h:outputText value="#{msg.forgotPassword}"/> <h:outputText value=" "/><h:outputText value=" "/><h:outputText value=" "/> <h:commandLink id="english" action="chooseLocale" actionListener="#{welcomeBean.onChooseLocale}"> <h:outputText value="#{msg.english}" /> </h:commandLink> <h:outputText value=" "/> <h:commandLink id="french" action="chooseLocale" actionListener="#{welcomeBean.onChooseLocale}"> <h:outputText value="#{msg.french}" /> </h:commandLink> </h:panelGrid> </h:form> </body> </html> </f:view>
The page starts with the page directive, after this comes the JSF tag
libraries, two of them. the html tag
library is used to place JSF widgets on the page, the core library
is independent of the rendering used (here it is html), it is usual
to have both tag libraries, since every page's JSF content must
be enclosed with the core tag "view". By convention, the html tags
use the <h:...> prefix, the core tag library tags use the <f:...>
prefix.
The error page to use is defined with <%@
page errorPage="errorpage.jsp" %>.
The bundle used in loadBundle contains
the internationalized text to display. All the text displayed
uses this bundle, as can be seen with the outputText tags.
The form tag acts much like
an html form, though it is worth noting that it does not specify
which page to submit to. In JSF, the page navigation is placed
in a configuration file, which is covered in a later
section.
JSF provides a panelGrid tag.
It is very much like an html table, the
number of columns is specified in the panelGrid tag. The facet "header" is
used to provide a heading to the table. The table rows and columns
are worked out by JSF, hence it is not necessary to specify where
to put a new row or a new column. To create a blank row, three
<h:outputText
value=" "/> tags are coded
The page as it stands simply allows the user to select the language
to use when displaying the page. commandLink tags
are used to do select the language to use. When a commandLink tag
is clicked by the user, a piece of code in a "managed bean" is
called. It is usual to code one managed bean class per JSF page.
The managed bean for the welcome page is explained in the next
section. The action attribute is hard coded here with the value "chooseLocale",
this value is used to decide what page to display next (as explained
in a later
section)
JBoss 4.03 comes with JSF 1.1. It is worth noting that in JSF 1.2 it
is possible to specify a prelude and coda for each page. This makes
it possible to place the tag libraries, error page, bundle and
<f:view> in the prelude file, and the closing tags in the coda
template file. Thus the repetition of this information is no longer
required in each page.
The Welcome Page Managed Bean
It is usual for every JSF page to have a managed
bean class associated with it. The managed bean class (written
in Java) contains the code that the pages use to display computed
values or to perform some programming logic. The idea of using
JSF is that the JSF page does not contain code, only display information.
In this application, the managed bean for the welcome
page is used to change the locale (language used to display welcome.jsp
and all future pages).
A new file called Welcome.java is created
in the src/com/j3ltd/web folder, which looks like this:
package com.j3ltd.web;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import java.util.*;
public class Welcome {
private HashMap<String, Locale> locales = null;
public Welcome() {
locales = new HashMap<String, Locale>(2);
locales.put("english", new Locale("en", "UK"));
locales.put("french", new Locale("fr", "FR"));
}
public void onChooseLocale(ActionEvent event) {
String current = event.getComponent().getId();
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale((Locale) locales.get(current));
}
}
When the user clicks on a language hyperlink (commandButton tag)
in the welcom.jsp page, this managed bean's onChooseLocale() method
is invoked. The method gets the "id" of the commandLink, which
is either "french" or "english". This "id" value
is used to look up the locale to set in the "locales" HashMap.
The reason for using a HashMap is that additional languages can be added
easily to the class, just by editing the constructor.
Internationalization Message Bundles
The easiest method of storing the text to be displayed
is to use properties files. It is also possible to use java classes,
but this is not done here. In this example, english and french
are supported, the default language is english. The english text
is placed in a file within the src folder path as follows: src/com.j3ltd/web/messages/ApplicationMessages.properties.
The french version of the text is placed in src/com.j3ltd/web/messages/ApplicationMessages_fr.properties.
Java's internationalization framework works out which file to use
depending on the language. The file extensions _en for english,
_fr for french, _de for german and others are defined as part of
Java's internationalization, see http://java.sun.com/docs/books/tutorial/i18n/index.html for
more details about internationalization. In the next
section, english
is configured as the default language to use, so it is not necessary
to append "_en" to the filename.
ApplicationMessages.properties looks like this:
################### # # MyCV Application localised text, English # ################### pageTitle=MyCV, anytime, anywhere, always there
# Welcome Page
welcome=Welcome To MyCV
welcomeBoxTitle=Please select an option from those listed below
register=Register
login=Login
forgotPassword=Forgot Password
#General Values english=English french=Français
The french version, called ApplicationMessages_fr.properties looks like this:
################### # # MyCV Application localised text, French # ################### pageTitle=MyCV, n'importe quand, n'importe où, toujours la
# Welcome Page
welcome=Bienvenu Sur MyCV
welcomeBoxTitle=Selectionnez un des choix ci-dessous svp.
register=Joindre
login=Entrée membre
forgotPassword=Oublié mot de passe
The faces-config.xml Configuration File
JSF uses a file called faces-config.xml to store
JSF specific information about the application. This includes:
- Which locales are supported.
- Managed bean names, and the java classes they use.
- Navigation rules, which specify which page to display following a
given action.
Many other things are also present in this file, each one is explained
as the need arises.
The file faces-config.xml is created in the src/web folder of the project.
At this stage there is very little that needs to go into faces-config.xml:
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<!DOCTYPE faces-config
PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<application> <message-bundle>com.j3ltd.web.messages.ApplicationMessages</message-bundle> <locale-config> <default-locale>en</default-locale> <supported-locale>fr</supported-locale> </locale-config> </application>
<!-- Managed Beans -->
<managed-bean>
<managed-bean-name>welcomeBean</managed-bean-name>
<managed-bean-class>com.j3ltd.web.Welcome</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<!-- Navigation Rules -->
<navigation-rule>
<from-view-id>/welcome.jsp</from-view-id>
<navigation-case>
<description>
Choose locale changes locale then returns to welcome page
</description>
<from-outcome>chooseLocale</from-outcome>
<to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
The internationalization details are given: the
message files' location, the default locale
(english) and the other locales supported (french).
The managed bean for the welcome page is defined,
this bean contains the code that changes the user's locale, depending
on the commandLink that is clicked.
The navigation rule states the welcome.jsp navigates
to welcome.jsp when the outcome is "chooseLocale". The outcome
chooseLocale was hard coded in the welcome.jsp
page.
At this point all the code needed to display the
welcome page is present. Also the code to change the language in
which the page is displayed is present in the managed bean. This
is a good point to build and test what has been written so far.
Packaging The Project
At this point there is enough to test that JSF and
internationalization are all configured correctly. The project,
as seen from the package explorer should look something like this:
The project properties dialog is opened (right click
on MyCV in the package explorer and select "Properties..."),
and the packaging configuration is selected, note that the
"Enable Packaging" checkbox is checked. The add button is pressed
and MyCV.war is entered as the archive to generate:
The archive is right clicked and the project file
web.xml is added with the prefix WEB-INF. This process is repeated
to add faces-config.xml:
MyCV.war is right clicked and "Add Folder" is
selected, the "Project Folder" bin is added. **/*.class is
entered in the
"includes" field to include all the java classes in the bin
folder. These classes are to be archived in the WEB-INF/classes
folder, the prefix textfield is used to specify this.
MyCV.war is right clicked and "Add Folder" is
selected, the "Project Folder" src is added. **/*.ApplicationMessages*.properties
is entered in the "includes" field to include all the internationalization
message files in the src folder.
These files are to be archived in the WEB-INF/classes folder.
Finally the web folder (which contains the style
sheet and the jsp files) needs to be added. * is entered in the
Includes field, no prefix is specified:
Al the project properties dialogs are dismissed
by clicking on OK, or Finish.
In the package explorer, the project MyCV is right
clicked and "Run Packaging" is selected to build the war archive
file.
Debug The Project
In the package explorer, the project MyCV is right
clicked and "Debug
As->Debug..." is
selected:
This should bring up the debug dialog, with the
settings already given during the installation of JBoss (see The
section regarding Testing the installation for
details).
In the debug dialog, the source tab is selected.
The "Add..." button is pressed, to tell the debugger
where to find the source files for the project. Finally, the Java
Project MyCV is selected:
OK is pressed, in both dialogs to return to the
debug dialog, where "Apply" is pressed.
The "Debug" button is pressed, and JBoss
is launched. The console window displays the status of JBoss as
it starts up, as mentioned in the installation
chapter, any exception
stack traces in the Eclipse console should be resolved before going
any further. When the console finally says that JBoss has started, the
war file MyCV.war is right clicked in the package explorer, and "deployment->deploy
to" is selected:
The deployment dialog should show the JBoss configuration
already defined in the "Test Installation" chapter.
A browser is opened, and the URL http://localhost:8080/MyCV is entered:
Clicking on the "Français" hyperlink displays the
french version of the page:
This completes the first step in the project. The
following has been achieved:
- JSF, as supplied with JBoss is configured, and an Eclipse library
has been created for JSF.
- Internationalization is implemented and working.
- An error page has been implemented.
- A JSF page and managed bean have been created, configured and tested
(the welcome page).
The next step is to implement the registration
process, so that a user can become a member of MyCV.
|