Creating a Web Application on JBoss AS 5

Exclusive offer: get 50% off this eBook here
JBoss AS 5 Development

JBoss AS 5 Development — Save 50%

Develop, deploy, and secure Java applications on this robust, open source application server

$29.99    $15.00
by Francesco Marchioni | December 2009 | JBoss Java Open Source

In this two-part article by Francesco Marchioni, we will be developing and configuring web applications using JBoss web container. Most developers have surely gained some experience with web applications. Therefore, we will not cover the basics of web applications; we will rather disclose how easy it can be to create a consistent web layer for your applications, using just the right tools and, of course, the right technique.
We will cover the following topics in more detail:

  • What is JSF and how to install it on JBoss AS
  • How to create a JSF facade for our pasture application
  • How to configure JBoss Web Server

Wonder what was the first message sent through Internet? At 22:30 hours on October 29, 1969, a message was transmitted using ARPANET (the predecessor of the global Internet) on a host-to-host connection. It was meant to transmit "login". However, it transmitted just "lo" and crashed.

Developing web layout

The basic component of any Java web application is the servlet. Born in the middle of the 90s, servlets quickly gained success against their competitors, the CGI scripts. This was because of some innovative features, especially the ability to execute requests concurrently, without the overhead of creating a new process for each request. However, a few things were missing, for example, the servlet API did not address any APIs specifically for creating the client GUI. This resulted in multiple ways of creating the presentation tier, generally with tag libraries that differed from job to job and from individual developers.

The second thing that was missing in the servlet specification was a clear distinction between the presentation tier and the backend. A plethora of web frameworks tried to fill this gap; particularly the Struts framework effectively realized a clean separation of the model (application logic that interacts with a database) from the view (HTML pages presented to the client) and the controller (instance that passes information between view and model).

However, the limitation of these frameworks was that even if they realized a complete modular abstraction, they still failed as they always exposed theHttpServletRequest and HttpServletSessionobjects to their action(s). Their actions, in turn, needed to accept the interface contracts such as ActionForm, ActionMapping, and so on.

The JavaServer Faces that emerged on the stage a few years later pursued a different approach. Unlike request-driven Model–View–Controller (MVC) web frameworks, JSF chose a component-based approach that ties the user interface component to a well-defined request processing lifecycle. This greatly simplifies the development of web applications.

The JSF specification allows you to have presentation components be POJOs. This creates a cleaner separation from the servlet layer and makes it easier to do testing by not requiring the POJOs to be dependent on the servlet classes.

In the following sections, we will describe how to create a web layout for our application store using the JSF technology. For an exhaustive explanation of the JSF framework, we suggest you to surf the JSF homepage at http://java.sun.com/javaee/javaserverfaces/.

Installing JSF on JBoss AS

JBoss AS already ships with the JSF libraries, so the good news is that you don't need to download or install them in the application server. There are different implementations of the JSF libraries. Earlier JBoss releases adopted the Apache MyFaces library. JBoss AS 4.2 and 5.x ship with the Common Development and Distribution License (CDDL) implementation (now called "Project Mojarra") of the JSF 1.2 specification that is available from the java.net open source community.

Switching to another JSF implementation is anyway possible. All you have to do is package your JSF libraries with your web application and configure your web.xml to ignore the JBoss built-in implementation:

<context-param>
<param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_
IMPL</param-name>
<param-value>true</param-value>
</context-param>

We will start by creating a new JSF project. From the File menu, select New | Other | JBoss Tools Web | JSF | JSF Web project. The JSF applet wizard will display, requesting the Project Name, the JSF Environment, and the default starting Template.

JBoss AS 5 Development

Choose AppStoreWeb as the project name, and check that the JSF Environment used is JSF 1.2. You can leave all other options to the defaults and click Finish. Eclipse will now suggest that you switch to the Web Projects view that logically assembles all JSF components. (It seems that the current release of the plugin doesn't understand your choice, so you have to manually click on the Web Projects tab.)

JBoss AS 5 Development

The key configuration file of a JSF application is faces-config.xml contained in the Configuration folder. Here you declare all navigation rules of the application and the JSF managed beans. Managed beans are simple POJOs that provide the logic for initializing and controlling JSF components, and for managing data across page requests, user sessions, or the application as a whole.

Adding JSF functionalities also requires adding some information to your web.xml file so that all requests ending with a certain suffix are intercepted by the Faces Servlet. Let's have a look at the web.xml configuration file:

<?xml version="1.0"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>AppStoreWeb</display-name>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param> [1]
<param-name>com.sun.faces.
enableRestoreView11Compatibility</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.
ConfigureListener</listener-class>
</listener>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>

The context-param pointed out here [1] is not added by default when you create a JSF application. However, it needs to be added, else you'll stumble into an annoying ViewExpiredException when your session expires (JSF 1.2).

Setting up navigation rules

In the first step, we will define the navigation rules for our AppStore. A minimalist approach would require a homepage that displays the orders, along with two additional pages for inserting new customers and new orders respectively.

Let's add the following navigation rule to the faces-config.xml:

<faces-config>
<navigation-rule>
<from-view-id>/home.jsp</from-view-id> [1]
<navigation-case>
<from-outcome>newCustomer</from-outcome> [2]
<to-view-id>/newCustomer.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>newOrder</from-outcome> [3]
<to-view-id>/newOrder.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id></from-view-id> [4]
<navigation-case>
<from-outcome>home</from-outcome>
<to-view-id>/home.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

In a navigation rule, you can have one from-view-id that is the (optional) starting page, and one or more landing pages that are tagged as to-view-id. The from-outcome determines the navigation flow. Think about this parameter as a Struts forward, that is, instead of embedding the landing page in the JSP/servlet, you'll simply declare a virtual path in your JSF beans.

Therefore, our starting page will be home.jsp [1] that has two possible links—the newCustomer.jsp form [2] and the newOrder.jsp form [3]. At the bottom, there is a navigation rule that is valid across all pages [4]. Every page requesting the home outcome will be redirected to the homepage of the application.

The above JSP will be created in a minute, so don't worry if Eclipse validator complains about the missing pages. This configuration can also be examined from the Diagram tab of your faces-config.xml:

JBoss AS 5 Development

The next piece of code that we will add to the confi guration is the JSF managed bean declaration. You need to declare each bean here that will be referenced by JSF pages. Add the following code snippet at the top of your faces-config.xml (just before navigation rules):

<managed-bean>
<managed-bean-name>manager</managed-bean-name> [1]
<managed-bean-class>
com.packpub.web.StoreManagerJSFBean
</managed-bean-class> [2]
<managed-bean-scope>request</managed-bean-scope> [3]
</managed-bean>

The <managed-bean-name> [1] element will be used by your JSF page to reference your beans. The <managed-bean-class> [2] is obviously the corresponding class. The managed beans can then be stored within the request, session, or application scopes, depending on the value of the <managed-bean-scope> element [3].

JBoss AS 5 Development Develop, deploy, and secure Java applications on this robust, open source application server
Published: December 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Adding a JSF managed bean

The StoreManagerJSFBean class follows the JavaBean patterns, providing get and set methods for its properties (to make the code more maintainable, we have skipped the getter/setter methods that simply wrap the fields of the class). We have declared the bean as request bound, so for each user of the application, JSF creates a StoreManagerJSFBean instance, which is stored within the request scope.

Add to your project a new Java class and name it com.packtpub.web.StoreManagerJSFBean:

package com.packpub.web;
// skipping imports
public class StoreManagerJSFBean {
@EJB(mappedName = "AppStoreEJB/local") [1]
private StoreManager storeManager;
private int customerId;
private int orderQuantity;
private int orderPrice;
private String customerName;
private String customerCountry;
private String orderProduct;
List<Order> listOrders;
List <SelectItem> listCustomers;
public List<SelectItem> getListCustomers() {
if (listCustomers == null) {
listCustomers= new ArrayList();
findAllCustomers();
}
return listCustomers;
}
/*
other getter/setter methods omitted for brevity
*/
public StoreManagerJSFBean() { }
public void findOrders() { [2]
listOrders = storeManager.findAllItems(this.customerId);
}
public void findAllCustomers() {
List<Customer> listCustomersEJB =
storeManager.findAllCustomers();
for(Customer customer:listCustomersEJB) {
listCustomers.add(new
SelectItem(customer.getId(),customer.getName()));
}
}
}
public void saveOrder() {
storeManager.saveOrder(customerId,this.orderPrice,
this.orderQuantity,this.orderProduct);
FacesMessage fm = new FacesMessage("Saved order for
"+this.orderQuantity+ " of "+this.orderProduct);
FacesContext.getCurrentInstance().addMessage("Message", fm);
this.orderPrice=0;
this.orderQuantity=0;
this.orderProduct=null;
}
public void insertCustomer() {
storeManager.createCustomer(this.customerCountry,
this.customerName);
FacesMessage fm = new FacesMessage(«Created Customer
«+this.customerName+ « fromf «+this.customerCountry);
FacesContext.getCurrentInstance().addMessage("Message", fm);
this.customerName=null;
this.customerCountry=null;
// Forces customer reloading
this.listCustomers=null;
}
/* Navigation rules */
public String home() { [4]
return "home";
}
public String newOrder() {
return "newOrder";
}
public String newCustomer() {
return "newCustomer";
}
}

As you can see, the StoreManagerJSFBean references the session bean we have created previously (StoreManager). Therefore, we must tell the compiler how to solve this dependency. This can be easily solved by choosing Properties on the current project, and then choosing Projects from the Java Build Path option. Add the project AppStore to your build path, as shown here:

JBoss AS 5 Development

Having fixed the compilation issues, we can now concentrate on the JSF bean. The first thing we want to capture your attention to is how the StoreManager EJB is injected [1] in the class, skipping completely the lookup/casting/exception handling part.

The findOrders() method [2] retrieves the list of orders from the StoreManager EJB. They will be displayed later in the dataTable component.

The findAllCustomers() [3] is slightly different. It recalls our entity bean's corresponding findAllCustomers() method and then populates a SelectItem object with the list of customers. SelectItem is a JSF object used to render a combobox programmatically. In our case, we will populate it with the customerId (as value) and customerName (as label).

The remaining EJB wrapper methods, saveOrder() and insertCustomer(), are quite intuitive; their job is to persist data for Orders and Customers.

The final piece of code is about navigation rules [4] that are coded as simple Java methods returning the outcome view as a string. For example, in order to return to the homepage from any other page, we will add the following button:

<h:commandButton action="#{manager.home}" value="Back" />

Setting up the view

Setting up the view JSF pages are just behind-the-scenes JSP pages that are engineered by the JSF servlet. Therefore, in order to create your views, add the following pages to your web application: home.jsp, newCustomer.jsp and newOrder.jsp. A new JSP page can be added from the Web Projects menu by right-clicking on the WebContent folder, then choosing New | File | JSP Page and naming it home.jsp.

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> [1]
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<body>
<f:view> [2]
<style type="text/css"> [3]
@import url("css/appstore.css");
</style>
<h:panelGrid columns="1" border="1" styleClass="spring"> [4]
<f:facet name="header">
<h:outputText value="Order List"/>
</f:facet>
<h:form id="listOrdersForm"> [5]
<h:outputText value="Select Customer:" /> [6]
<h:selectOneMenu id="selectCustomer"
value="#{manager.customerId}" styleClass="buttons"> [7]
<f:selectItems
value="#{manager.listCustomers}" />
</h:selectOneMenu>
<h:commandButton action="#{manager.findOrders}"
value="ListOrders" styleClass="buttons"/> [8]
<h:dataTable value="#{manager.listOrders}" var="orders"
border="1" rowClasses="row1, row2" headerClass="header"> [9]
<h:column>
<f:facet name="header">
<h:outputText value="Product" />
</f:facet>
<h:outputText value="#{orders.product}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Price" />
</f:facet>
<h:outputText value="#{orders.price}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Quantity" />
</f:facet>
<h:outputText value="#{orders.quantity}" />
</h:column>
</h:dataTable>
<h:commandButton action="#{manager.newCustomer}"
value="Insert Customer" styleClass="buttons" /> [10]
<h:commandButton action="#{manager.newOrder}"
value="Insert Order" styleClass="buttons" /> [11]
</h:form>
</h:panelGrid>
</f:view>
</body>
</html>

JSF contains two tag libraries [1] called JSF core and HTML Basic. The former provides a few general tags and some other tags that let you register validators and event listeners to UI components. The latter contains JSP tags that render HTML UI components such as buttons, text fields, checkboxes, lists, and so on. The standard prefixes of these two tag libraries are h and f, and they are declared at the beginning of home.jsp.

The view tag [2] is the container for all JavaServer Faces component tags used on a page. Stylesheets [3] are used here to decorate the UI components. The panelGrid [4] component simplifies the task of constructing a layout table, to hold form fields, labels, and buttons. In this case, it will contain the main input form.

The form element [5] manages an HTML form just the same way as standard form HTML. Rendering simple text on the page can be achieved with an outputText tag [6]. Here, you can use value-binding expressions from your JSF beans.

The selectOneMenu element [7] is used to display an HTML combobox that is bound to a bean collection. Review the findAllCustomers() method of your StoreManagerJSFBean, where the combobox is built dynamically.

The commandButton [8] is applied to render an HTML button. In our case, we have bound the button to the findOrders() method of our JSF bean.

A core JSF tag is the dataTable tag [9] that can be used to render an HTML table using a collection from the backing bean. This component is generally used to display tabular data and it offers a vast choice of built-in options for customizing its header and footer, and for paginating the table.

The last two buttons, [10] and [11], plot the route to the newCustomer and newOrder forms.

The form for inserting a new customer is as follows:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<body>
<f:view>
<style type="text/css">
@import url("css/appstore.css");
</style>
<h:form id="newCustomer">
<h:panelGrid columns="2" border="1" styleClass="spring">
<f:facet name="header">
<h:outputText value="Insert new Customer" />
</f:facet>
<h:outputText value="Name" />
<h:inputText value="#{manager.customerName}" /> [1]
<h:outputText value="Country" />
<h:inputText value="#{manager.customerCountry}" />
<h:commandButton action="#{manager.insertCustomer}" [2]
value="Insert Customer" />
<h:commandButton action="#{manager.home}" value="Back" />
</h:panelGrid>
<h:messages />
</h:form>
</f:view>
</body>
</html>

The inputText fields [1] are used to populate the individual managed bean properties. With the commandButton [2], the insertCustomer() action is recalled, thus inserting a new customer. This is the last JSP needed for our example newOrder.jsp:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<body>
<f:view>
<style type="text/css">
@import url("css/appstore.css");
</style>
<h:form id="newOrder">
<h:panelGrid columns="2" border="1" styleClass="spring">
<f:facet name="header">
<h:outputText value="Insert new Order" />
</f:facet>
<h:outputText value="Product" />
<h:inputText value="#{manager.orderProduct}" />
<h:outputText value="Quantity" />
<h:inputText value="#{manager.orderQuantity}" />
<h:outputText value="Price" />
<h:inputText value="#{manager.orderPrice}" />
<h:outputText value="Customer" />
<h:selectOneMenu id="selectCustomerforOrder"
value="#{manager.customer}">
<f:selectItems value="#{manager.listCustomers}" />
</h:selectOneMenu>
<h:commandButton action="#{manager.saveOrder}"
value="Save Order" />
<h:commandButton action="#{manager.home}" value="Back" />
</h:panelGrid>
<h:messages />
</h:form>
</f:view>
</body>
</html>

Assembling and deploying the application

So far, you have got two standalone projects, one EJB project and one web project. While you could technically deploy them separately, it is worth combining them in an Enterprise ARchive (EAR). The most obvious reason for deploying the application as an Enterprise ARchive is that the web application will be loaded by a ClassLoader in the same hierarchy as the EJB classloader. In short, you don't need to provide the EJB interfaces to the web application, as you would for a standalone application.

Packaging the application can be done entirely by Eclipse, without messing with archive files. From the menu, select New | Other | Java EE | Enterprise Application project. The next facet will request the Project name and a few details about the configuration. Your archive name will be, by default, the project name plus the extension .ear. Verify that both Target Runtime and the Configuration point correctly to the JBoss 5.0 environment.

JBoss AS 5 Development

Click Next. On the window that follows, you can select the components of your archive application, that is, the AppStore application and the AppStoreWeb component. Check the option Generate Deployment Descriptor.

JBoss AS 5 Development

Verify that META-INF/application.xml deployment descriptors contain both the modules enlisted below:

<application>
<display-name>EnterpriseStore</display-name>
<module>
<web>
<web-uri>AppStoreWeb.war</web-uri>
<context-root>AppStoreWeb</context-root>
</web>
</module>
<module>
<ejb>AppStore.jar</ejb>
</module>
</application>

Okay, now you need only a few more laps to complete the race. Let's deploy the process to JBoss by switching on the JBoss Server View. Right-click on the JBoss server and select Add and remove projects. Add the EnterpriseStore to the configured projects.

Now deploy the application in the usual way. Right-click on the EnterpriseStore and select Full Publish (at the time of writing, JBoss 5 doesn't support partial deployment of this component).

JBoss AS 5 Development

Verify from the console that the application has been deployed correctly.

Running the store

The application gateway will be home.jsf page. Point the browser to the location http://localhost:8080/AppStoreWeb/home.jsf.

Testing the application is quite simple. First add some customers and then link some orders to the customers. In the home.jsf page, check that the orders are correctly listed from the datagrid.

JBoss AS 5 Development

A last trick
Usually web applications ship with a welcome file list so that you don't have to remember anything else besides the web context. If you have already tried to add home.jsf to the welcome file list (in web.xml), you would have noticed that it doesn't work. Actually, Tomcat is a bit stubborn and requires a trick to set a JSF page as a welcome file. First, add the following to your web.xml:

<welcome-file-list>
<welcome-file>home.jsf</welcome-file>
</welcome-file-list>

Then create an empty home.jsf page in your web context root. This will trick Tomcat to detect home.jsf as the welcome file and will load home.jsp instead.

Summary

This two-part article on creating a web application is about developing and configuring web applications on JBoss AS 5.0 using the JSF cutting-edge technology. In this part of the article we have enhanced the Appstore Enterpirse application by adding a web layer to it.

In the next part, we will explain in detail how to properly Configure JBoss Web Server.

 

If you have read this article you may be interested to view :

JBoss AS 5 Development Develop, deploy, and secure Java applications on this robust, open source application server
Published: December 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Francesco Marchioni

Francesco Marchioni is a Sun Certified Enterprise Architect employed for an Italian company based in Rome. He started learning Java in 1997 and since then has followed the path to the newest application program interfaces released by Sun. He joined the JBoss community in 2000, when the application server was running release 2.x.

He has spent many years as a software consultant, where he has envisioned many successful software migrations from vendor platforms to open source products such as JBoss AS, fulfilling the tight budget requirements of current times.

Over the past 5 years, he has been authoring technical articles for OReilly Media and is running an IT portal focused on JBoss products (http://www.mastertheboss.com).

He has authored the following titles:

He has also co-authored the book Infinispan Data Grid Platform, Packt Publishing (August 2012), with Manik Surtani, which covers all the aspects related to the configuration and development of applications using the Infinispan Data Grid Platform (http://www.packtpub.com/infinispan-data-grid-platform/book).

Books From Packt


Apache Geronimo 2.1: Quick Reference
Apache Geronimo 2.1: Quick Reference

Tomcat 6 Developer's Guide
Tomcat 6 Developer's Guide

GlassFish Administration
GlassFish Administration

MooTools 1.2 Beginner's Guide
MooTools 1.2 Beginner's Guide

JSF 1.2 Components
JSF 1.2 Components

jBPM Developer Guide
jBPM Developer Guide

Spring Persistence with Hibernate
Spring Persistence with Hibernate

Apache Roller 4.0 – Beginner's Guide
Apache Roller 4.0 – Beginner's Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software