Skip to main content

Developing RIA using JSF

There is plenty of Web Application Frame works exist today for developing J2EE based enterprise applications. Struts, JSF, Tapestry, Cocoon, Spring, Wicket, Turbine, WebWork, MyFaces and the list goes on. Benchmarking or choosing the right frame work can be a daunting task. JSF seem to be a clear choice in the MVC world- the only component based architecture- with clean separation of roles, extensible and ease of use.

RichFaces is a powerful extension of JSF framework. It brings AJAX capability to applications out of the box without needing to write any JavaScript code or needing to replace existing components with new AJAX widgets. It provides a skin-ability feature allowing easy definition and management of different color schemes and other characteristics of the UI through named skin parameters.

Assuming a fair understanding of the underlying technologies, let’s get started with relatively simple set up to developing a simple yet serious web application step by step.


Where do you want to Fly?

The first part one of this application, “Where do you want to Fly?” is small but good enough to demonstrate some of the cool features of RichFaces. Please see the sample Screens from the application. Required software set up:


  • JBose Installation. Download and install the latest version of JBoss application Server. For this example, I used the current stable version JBboss-4.2.3.GA from:

https://www.jboss.org/jbossas/downloads/.

  • Eclipse IDE: I used Eclipse 3.3.2 with WebTools plug-ins. You may download this from the following location.

http://www.eclipse.org/downloads/packages/release/europa/winter

  • JBoss Plugins for Eclipse: Download the “All Plug-ins xxx” from the JBoss web site

https://www.jboss.org/tools/download/ Unzip the plug-in into the Eclipse folder.

  • RichFaces Libraries: Download the latest RichFaces libs (richfaces-ui-3.2.2.GA-bin.zip or whichever is the latest) from the following location https://www.jboss.org/jbossrichfaces/downloads/. Unzip this into a folder. We need the following JARs required to run our applications:



  • richfaces-api-xxxx.GA.jar
  • richfaces-impl-xxxx.GA.jar
  • richfaces-ui-xxxx.GA.jar


Start Eclipse and make sure that your plug-in is active. Open up Eclipse-Window-Preferences. Under Server-Installed Runtimes you should be able to configure the newly installed JBoss server. Once you are able to run the JBose Server from Eclipse, your set is complete. Try to access the Web-Console of the server by hitting the following URL:

http://localhost:8080/web-console/


Create a JSF Project


In Eclipse, create a JSF project named “WhereIWantToFly”

Select JSFEnvironment : JSF 1.2 With Facelets

Template : FaceletsKickStartWithoutLibs

Once the project is created, copy the RichFaces Libs (richfaces-api-xxxx.GA.jar, richfaces-impl-xxxx.GA.jar, richfaces-ui-xxxx.GA.jar) into the WEB-INF\lib folder. Once this step is done, the project folder will look as shown:


Scope of the Application.


This simple application “Where do you want to Fly?” should enable the user to select a Country, and then a City, a date you want to fly. Once the selections are made, the user should be able to navigate with the map of the City. The application intent to use the AJAX features of the RichFaces to load Microsoft Virtual Earth custom controls.


Create Domain Classes


Now create the following domain classes Country and City.


1. City.java


package com.leisure.domain;

public class City {
private String name;
private Float latitude;
private Float longitude;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Float getLatitude() {
return latitude;
}

public void setLatitude(Float latitude) {
this.latitude = latitude;
}

public Float getLongitude() {
return longitude;
}

public void setLongitude(Float longitude) {
this.longitude = longitude;
}

public City (String name)
{
this.name = name;
}

public boolean equals(Object o)
{
if (o instanceof City)
{
City thatCity = (City) o;

if (getName () != null && thatCity.getName () != null && getName ().equals(thatCity.getName () ))
{
return true;
}
}

return false;
}

public City (String name, Float latitude, Float longitude)
{
this.name = name;
this.latitude = latitude;
this.longitude = longitude;
}

@Override
public String toString() {
System.out.println (this.name + " - Latitude : " + this.latitude + " longitude : " + this.longitude);
return super.toString();
}
}


2. Country.java


package com.leisure.domain;

import java.util.List;

public class Country {

private String name;

private List cities;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public List getCities() {

return cities;

}

public void setCities(List cities) {

this.cities = cities;

}

public Country (String name)

{

this.setName(name);

}

public boolean equals(Object o)

{

Country thatCountry = (Country) o;

if (getName () != null && thatCountry.getName () != null && getName ().equals(thatCountry.getName () ))

{

return true;

}

return false;

}

}


Creating the Managed Bean

Create the managed Bean called “Destination.java”. Take a look at the init () method at the end of the method. The @PostConstruct annotation ensures that this method gets called immediately after the creation of the bean and initialises with data required for running this application.


package com.leisure.jsf.backingbeans;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import javax.annotation.PostConstruct;

import javax.faces.context.FacesContext;

import javax.faces.event.ActionEvent;

import javax.faces.event.ValueChangeEvent;

import javax.faces.model.SelectItem;

import com.leisure.domain.City;

import com.leisure.domain.Country;

public class Destination {

private List countries;

private Country selectedCountry = new Country ("");

private City selectedCity = new City ("");

private Date selectedDate = new Date ();

private boolean isRenderMap = false;

private Float latitude;

private Float longitude;

private String selectedCountryName;

private String selectedCityName;

public List getCountries() {

return countries;

}

public void setChangeCountry ()

{

System.out.println ("Requestig setChangeCountry ");

}

public void changeCountry ()

{

System.out.println ("Requestig changeCountry ");

}

public List getCountryNames ()

{

List contryNames = new ArrayList ();

for (Country country : countries)

{

contryNames.add(new SelectItem(country.getName(), country.getName()));

}

contryNames.add(new SelectItem("", ""));

return contryNames;

}

public List getCityNames ()

{

List cityNames = new ArrayList ();

if (this.selectedCountry != null && this.selectedCountry.getCities() != null)

{

for (City city : this.selectedCountry.getCities())

{

cityNames.add(new SelectItem(city.getName(), city.getName()));

}

}

return cityNames;

}

public void setCountries(List countries) {

this.countries = countries;

}

public List autocomplete(Object suggest) {

return getCountries();

}

public void displayMap(ActionEvent event){

System.out.println ("Selected Country " + getSelectedCountry().getName());

System.out.println ("Selected City " + getSelectedCity().getName());

isRenderMap = true;

}

public void processValueChangeCountry (ValueChangeEvent countryChange)

{

System.out.println ("Requestig countryChange " + countryChange.getNewValue());

isRenderMap = false;

String newCountry = (String) countryChange.getNewValue();

setSelectedCountry(newCountry);

/*Render the response*/

FacesContext.getCurrentInstance().renderResponse();

}

public void processValueChangeCity (ValueChangeEvent cityChange)

{

isRenderMap = false;

String newCity = (String) cityChange.getNewValue();

System.out.println ("Requestig changeCity " + cityChange.getNewValue());

setSelectedCity(newCity);

/*Render the response*/

FacesContext.getCurrentInstance().renderResponse();

}

public Country getCountryByName (String name)

{

Country aCountry = new Country (name);

if (countries.contains(aCountry))

{

aCountry = (Country) countries.get(countries.indexOf(aCountry));

return aCountry;

}

return null;

}

public City getCityByName (String cityName)

{

List cities;

City aCity = new City (cityName);

if (this.selectedCountry != null && cityName != null)

{

cities = this.selectedCountry.getCities();

if (cityName != null && cities.contains(aCity))

{

aCity = (City) cities.get(cities.indexOf(aCity));

}

}

return aCity;

}

public String getSelectedCountryName() {

if (selectedCountry == null)

{

selectedCountry = new Country ("");

}

return selectedCountry.getName();

}

public void setSelectedCountry(String selectedCountry) {

System.out.println ("Calling setSelectedCountry : " + selectedCountry);

this.selectedCountry = getCountryByName (selectedCountry);

}

public City getSelectedCity() {

return selectedCity;

}

public void setSelectedCity(String selectedCity) {

System.out.println ("Calling setSelectedCity : " + selectedCity);

this.selectedCity = getCityByName (selectedCity);

}

public Date getSelectedDate() {

return selectedDate;

}

public void setSelectedDate(Date selectedDate) {

this.selectedDate = selectedDate;

}

public boolean isRenderMap() {

return isRenderMap;

}

public void setRenderMap(boolean isRenderMap) {

this.isRenderMap = isRenderMap;

}

public Float getLatitude() {

return latitude;

}

public void setLatitude(Float latitude) {

this.latitude = latitude;

}

public Float getLongitude() {

return longitude;

}

public void setLongitude(Float longitude) {

this.longitude = longitude;

}

public Country getSelectedCountry() {

return selectedCountry;

}

public void setSelectedCountry(Country selectedCountry) {

this.selectedCountry = selectedCountry;

}

public void setSelectedCity(City selectedCity) {

this.selectedCity = selectedCity;

}

public String getSelectedCityName() {

return selectedCityName;

}

public void setSelectedCityName(String selectedCityName) {

this.selectedCityName = selectedCityName;

}

public void setSelectedCountryName(String selectedCountryName) {

this.selectedCountryName = selectedCountryName;

}

@PostConstruct

public void init () {

countries = new ArrayList ();

Country america = new Country ("United States of America");

List usCities = new ArrayList ();

usCities.add(new City ("New York", new Float (40.748472222222226), new Float (-73.98571111111112)));

usCities.add(new City ("San Francisco", new Float(37.81103611111111), new Float (-122.47740277777778)));

usCities.add(new City ("Los Angeles", new Float (34.052186111111105), new Float (-118.243425)));

america.setCities(usCities);

Country canada = new Country ("Canada");

List canCities = new ArrayList ();

canCities.add(new City ("Toronto", new Float (43.67023333333333), new Float (-79.38675555555557)));

canCities.add(new City ("Montreal", new Float(45.54544722222222), new Float (-73.639075)));

canCities.add(new City ("Vancouver", new Float (49.26358888888889), new Float (-123.1385638888889)));

canada.setCities(canCities);

Country uk = new Country ("United Kingdom");

List ukcities = new ArrayList ();

ukcities.add(new City ("London", new Float (51.50015277777778), new Float (-0.1262361111111111)));

ukcities.add(new City ("Cambridge", new Float (52.20254444444445), new Float (0.1312361111111111)));

uk.setCities(ukcities);

countries.add(america);

countries.add(canada);

countries.add(uk);

setCountries(countries);

}

}


Registering the “Destination” bean with “faces-config.xml”


Now it’s time to register the bean with “faces-config.xml”. Here is how the bean can be registered with a session scope.



xml version="1.0" encoding="UTF-8"?>

<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xi="http://www.w3.org/2001/XInclude"

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-facesconfig_1_2.xsd">

<managed-bean>

<managed-bean-name>destinationBeanmanaged-bean-name>

<managed-bean-class>com.leisure.jsf.backingbeans.Destinationmanaged-bean-class>

<managed-bean-scope>sessionmanaged-bean-scope>

managed-bean>

<application>

<view-handler>com.sun.facelets.FaceletViewHandlerview-handler>

application>

faces-config>


Building the User Interface.


Now under “WebContent/pages” folder, create a page called “WhereIWantToFly.xhtml”. If we use the Wizard to create the file, it’s possible to select and include the required libraries for the page. For instance, we need to use the JSF Core, JSF HTML, AJAX for JSF (JBose), RichFaces (JBose) librearies for this page. See the listing below:


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:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:ui="http://java.sun.com/jsf/facelets"

xmlns:rich="http://richfaces.org/rich"

xmlns:a4j="http://richfaces.org/a4j">

<ui:composition>

<h:form id="flyingForm" >

<rich:panel render="cityMapGrid" >

<f:facet name="header">Where do you want to Fly?f:facet>

<table border="0" cellspacing="0" cellpadding="0">

<tr>

<td><h:outputLabel id="countryInputText" value="Country"/>td> <td> td>

<td>

<h:selectOneMenu id="countryInput" value="#{destinationBean.selectedCountryName}"

valueChangeListener="#{destinationBean.processValueChangeCountry}"

immediate="true" onchange="this.form.submit()">

<f:selectItems value="#{destinationBean.countryNames}"/>

h:selectOneMenu>

td>

tr>

<tr><td> td>tr>

<tr>

<td><h:outputLabel id="cityInputText" value="City"/>td> <td> td>

<td>

<h:selectOneMenu id="cityInput" value="#{destinationBean.selectedCityName}"

valueChangeListener="#{destinationBean.processValueChangeCity}"

immediate="true" onchange="this.form.submit()">

<f:selectItems value="#{destinationBean.cityNames}"/>

h:selectOneMenu>

td>

tr>

<tr><td> td>tr>

<tr>

<td><h:outputLabel id="flightDateText" value="When are you planing to Fly?"/>td> <td> td>

<td>

<a4j:outputPanel id="calendar" layout="block" >

<rich:calendar value="#{destinationBean.selectedDate}"

cellWidth="24px" cellHeight="22px" style="width:200px"/>

a4j:outputPanel>

td>

tr>

table>

<br />

<h:commandButton id="showMap" value="Show me this City Map" immediate="true"

actionListener="#{destinationBean.displayMap}"/>

<br /><br />

rich:panel>

<rich:panel id="cityMap">

<h:panelGrid id="cityMapGrid">

<rich:virtualEarth

lat="#{destinationBean.selectedCity.latitude}" lng="#{destinationBean.selectedCity.longitude}" dashboardSize="Normal"

zoom="17" mapStyle="Birdseye" rendered="#{destinationBean.renderMap}"/>

h:panelGrid>

rich:panel>

h:form>

ui:composition>

html>

Configuring the Web.xml

RichFaces doesn't require any parameters to be defined in your web.xml. But there exist few parameters (Default Skin, loading of styles, loading of Scripts etc), help increase the flexibility of RichFaces. Finally, here is our web.xml:

xml version="1.0"?>

<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">

<description>Sample applicationdescription>

<display-name>richfaces-startdisplay-name>

<context-param>

<param-name>javax.faces.DEFAULT_SUFFIXparam-name>

<param-value>.xhtmlparam-value>

context-param>

<context-param>

<param-name>facelets.REFRESH_PERIODparam-name>

<param-value>2param-value>

context-param>

<context-param>

<param-name>facelets.DEVELOPMENTparam-name>

<param-value>trueparam-value>

context-param>

<context-param>

<param-name>javax.faces.STATE_SAVING_METHODparam-name>

<param-value>serverparam-value>

context-param>

<context-param>

<param-name>org.richfaces.SKINparam-name>

<param-value>emeraldTownparam-value>

context-param>

<filter>

<display-name>Ajax4jsf Filterdisplay-name>

<filter-name>ajax4jsffilter-name>

<filter-class>org.ajax4jsf.Filterfilter-class>

filter>

<filter-mapping>

<filter-name>ajax4jsffilter-name>

<servlet-name>Faces Servletservlet-name>

<dispatcher>REQUESTdispatcher>

<dispatcher>FORWARDdispatcher>

<dispatcher>INCLUDEdispatcher>

filter-mapping>

<servlet>

<servlet-name>Faces Servletservlet-name>

<servlet-class>javax.faces.webapp.FacesServletservlet-class>

<load-on-startup>1load-on-startup>

servlet>

<servlet-mapping>

<servlet-name>Faces Servletservlet-name>

<url-pattern>*.jsfurl-pattern>

servlet-mapping>

<login-config>

<auth-method>BASICauth-method>

login-config>

web-app>


Running the Application

Now build the application and run. You can select the Country and accordingly select the City. Click on the “Show me this City Map” button to render the map of the city.

Comments

ts said…
This is working...Thanks!

Popular posts from this blog

SAAS Simple Maturity Model

There are two architectural models – commonly referred as SAAS Maturity models- that describe the transition of a service to what is called Multi-tenant efficient, highly scalable application. The SAAS Maturity model described by Microsoft has four distinct stages and is illustrated below. Another similar well-known model for SaaS-maturity is known as Forrester-model but adds another stage known as "Dynamic Business Apps-as-a-service". The three key Attributes of a SAAS Architecture: Configurability: Metadata used to configure the way the application behaves for customers Multi-tenant Efficiency : Maximizing the sharing of resources across tenants Scalability: Maximizing concurrency, resource efficiency SAAS Simple Maturity Model (Microsoft, 2006) SaaS Maturity Model (Forres

SpringBoot : Performance War

Reactive Systems are designed to address challenges posed by modern software systems - the challenges related to large number of users and high throughput. Reactive systems are expected to be highly responsive, resilient, elastic and message driven. In this article we will: Build a set of fully non-blocking REST API using SpringBoot 2.0, WebFlux and Reactive Redis. Performance test the above Reactive APIs against the traditional non-reactive APIs. The code used in this example can be downloaded from GitHub Step 1: Create a skeleton Reactive WebFlux SpringBoot project Create a SpringBoot maven project using - https://start.spring.io/ Add the following dependencies: spring-boot-starter-web spring-boot-starter-data-redis spring-webflux spring-boot-starter-data-redis-reactive Refer to the dependencies in pom.xml Step 2: Create Domain Objects The demo project uses the domain objects Customer and Account . A customer can have multiple accounts.

Web Service Framework comparison

Web Services is one of those concepts made all the more difficult to understand because of the myriad acronyms and abbreviations that are superfluous in any discussion. Covering all the concepts and standards associated with Web Services is a vast topic in itself. There are a large number of standards around Web Services. These standards define the norms of a Web Services implementation and ensure that a Web Services is accessed independently of the client platform. There are numerous frameworks available to select to build web service today. Below is the most widely used ones. Product Does it fit my need? Axis2.0 Apache Axis2 is a complete re-design and re-write of the widely used Apache Axis SOAP stack to build on the lessons learnt from Apache Axis. An advantage of Axis 2 is its support for the binding frameworks XMLBeans. Axis 2 with XMLBeans is widely