Posts Tagged ‘JSF

23
Oct
10

JSF Custom Components, Importing Resources

As the web development world moves to a more “component-based” approach we see more and more usage of Dojo, YUI, jQuery, extJS. These frameworks require css and js files be imported into the page before their components could be used. This page describes the process of creating a “<resources/>” tag that will do this work for you.

Background

The benefit of using “resource tag” is to allow “selective importing” of resources onto the page so you don’t flood the client’s browser with unnecessary JavaScript.

The way it will work is by allowing each JSF component tag to indicate what resources are necessary in their constructors. This information will be communicated to the “ResourceHolder” managed bean.

The “resources” tag will read the information in the “ResourceHolder” during the render phase and import only the JavaScript necessary to render the components.

Requirements

Getting Started

To demonstrate this concept we will add to the existing project described in my “Hello World Posting”. (see above)

If you have not done so already import the project into eclipse. It will make editing a lot easier.

mvn eclipse:clean eclipse:eclipse

Import the as “Existing Project into Workspace”.

Its easy to get lost on this page so here is a summary of what is being done:

  1. Create a request scope managed bean that holds a list of resources for the current request.
  2. Create a Component Class
  3. Create a Component Renderer – this component is responsible for iterating thru the list of resources in the managed bean and rendering only the necessary “script” or “style” tags for the components on the page.
  4. Create a Resource Tag Class
  5. Define the component in the faces config
  6. Define the ResourceTag in the TLD
  7. Modify the HtmlHelloWorld tag to require extJS css and js files
  8. Modify the JSP and insert the resource tag.
  9. Run the code in Jetty

Create the Resource Holder Impl Managed Bean

The ResourceHolder class is simply a collection of URL’s (Strings). The resourceHolder is passed to the page via a request scoped Managed Bean seen above.

src/main/java/org/extjsf/resource/ResourceHolderImpl.java

package org.extjsf.resource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ResourceHolderImpl {
	private List<String> resources;
	
	public ResourceHolderImpl() {
		resources = new ArrayList<String>();
	}
	
	public void addResource(String resource) {
		if(!resources.contains(resource))
			resources.add(resource);
	}

	public Collection<String> getResources() {
		return resources;
	}
}

Insert the following towards the top of your faces-config.

src/main/webapp/WEB-INF/faces-config.xml

	<managed-bean>
		<managed-bean-name>myResourceHolder</managed-bean-name>
		<managed-bean-class>org.extjsf.resource.ResourceHolderImpl</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
	</managed-bean>

Create Resources Component Class

src/main/java/org/extjsf/component/resources/Resources.java

package org.extjsf.component.resources;

import javax.faces.component.UIComponentBase;

public class Resources extends UIComponentBase {
	public static final String COMPONENT_TYPE = "org.extjsf.component.Resources";
	public static final String COMPONENT_FAMILY = "org.extjsf.component";
	
	@Override
	public String getFamily() {
		return COMPONENT_FAMILY;
	}
}

Define the Component Renderer

src/main/java/org/extjsf/component/resources/ResourcesRenderer.java

package org.extjsf.component.resources;

import java.io.IOException;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;

import org.extjsf.resource.ResourceHolderImpl;

public class ResourcesRenderer extends Renderer {
	@Override
	public void encodeEnd(FacesContext facesContext, UIComponent component)
			throws IOException {
		ResourceHolderImpl resourceQueue = getResourceHolder(facesContext);
		ResponseWriter writer = facesContext.getResponseWriter();
		Resources resources = (Resources) component;
		
		writer.write("\n");

		for(String resource : resourceQueue.getResources()) {
			if(resource.endsWith("css")) {
				renderCSSDependency(facesContext, resource);				
			}
			else if(resource.endsWith("js")){
				renderScriptDependency(facesContext, resource);				
			}
		}
		
		writer.write("\n");
	}
	
	// for now these scriptPath references are absolute urls
	protected void renderScriptDependency(FacesContext facesContext, String scriptPath) throws IOException{
		ResponseWriter writer = facesContext.getResponseWriter();
		writer.startElement("script", null);
		writer.writeAttribute("type", "text/javascript", null);
		writer.writeAttribute("src", scriptPath, null);
		writer.endElement("script");
		writer.write("\n");
	}
	
	// for now these cssPath references are absolute urls
	protected void renderCSSDependency(FacesContext facesContext, String cssPath) throws IOException{
		ResponseWriter writer = facesContext.getResponseWriter();
		writer.startElement("link", null);
		writer.writeAttribute("rel", "stylesheet", null);
		writer.writeAttribute("type", "text/css", null);
		writer.writeAttribute("href", cssPath, null);
		writer.endElement("link");
		writer.write("\n");
	}

	protected ResourceHolderImpl getResourceHolder(FacesContext facesContext) {
		ValueExpression ve = facesContext.getApplication()
				.getExpressionFactory().createValueExpression(
						facesContext.getELContext(),
						"#{myResourceHolder}", ResourceHolderImpl.class);

		return (ResourceHolderImpl) ve.getValue(facesContext.getELContext());
	}
}

Resources Tag Class

src/main/java/org/extjsf/component/resources/ResourcesTag.java

package org.extjsf.component.resources;

import javax.faces.webapp.UIComponentELTag;

import org.extjsf.component.resources.Resources;

public class ResourcesTag extends UIComponentELTag {

	public String getComponentType() {
		return Resources.COMPONENT_TYPE;
	}

	public String getRendererType() {
		return "org.extjsf.component.ResourcesRenderer";
	}
}

Define the Component in the faces-config.xml

Put the following xml after the component that is currently defined in the file.
src/main/webapp/WEB-INF/faces-config.xml

	<component>
		<component-type>org.extjsf.component.Resources</component-type>
		<component-class>org.extjsf.component.resources.Resources</component-class>
	</component>

Define the Renderer in the faces-config.xml

Put the following xml after the renderer that is currently defined in the file.

		<renderer>
			<component-family>org.extjsf.component</component-family>
			<renderer-type>org.extjsf.component.ResourcesRenderer</renderer-type>
			<renderer-class>org.extjsf.component.resources.ResourcesRenderer</renderer-class>
		</renderer>

Define the resources tag in the tag library descriptor

Insert the following into:
src/main/webapp/WEB-INF/htmlHelloWorld.tld

<tag>
	<name>resources</name>
	<tag-class>org.extjsf.component.resources.ResourcesTag</tag-class>
	<body-content>JSP</body-content>
</tag>

At this point the resources tag is defined to print resources that are required by each of the components.

HtmlHelloWorld

Next we will modify the HelloWorld Component Class to require the extJSF resources in the default constructor. This component will indicate that the extjs css and js files should be included by the resource renderer. It will store this information in the resourceHolder managed bean seen above.

Your HtmlHelloWorld should look like this…

src/main/java/org/extjsf/component/helloworld/HtmlHelloWorld.java

package org.extjsf.component.helloworld;
 
import javax.el.ValueExpression;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;

import org.extjsf.resource.ResourceHolderImpl;

 
public class HtmlHelloWorld extends UIComponentBase {
    public static final String COMPONENT_FAMILY = "org.extjsf.component";
 
    @Override
    public String getFamily() {
        return COMPONENT_FAMILY;
    }
    
	protected ResourceHolderImpl getResourceHolder() {
		FacesContext facesContext = getFacesContext();
		if (facesContext == null)
			return null;

		ValueExpression ve = facesContext.getApplication()
				.getExpressionFactory().createValueExpression(
						facesContext.getELContext(),
						"#{myResourceHolder}", ResourceHolderImpl.class);

		return (ResourceHolderImpl) ve.getValue(facesContext.getELContext());
	}
	
	public HtmlHelloWorld() {
		ResourceHolderImpl resourceHolder = getResourceHolder();

		if(resourceHolder != null) {
			// Note: In an actual production code you would create a resource
			// servlet and use relative url's. The way its done here is 
			// just for demonstration purposes only.
			resourceHolder.addResource("http://dev.sencha.com/deploy/ext-3.3.1/resources/css/ext-all.css");
			resourceHolder.addResource("http://dev.sencha.com/deploy/ext-3.3.1/adapter/ext/ext-base.js");
			resourceHolder.addResource("http://dev.sencha.com/deploy/ext-3.3.1/ext-all.js");
		}
	}
}

And Finally the JSP Page

Finally we create a JSP page that uses the “resources” tag…

src/main/webapp/examples/resources.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="e" uri="http://extjsf.org/components" %>
 
<f:view>
    <html>
    <head>
        <title>Resources JSF Example</title>        
		<e:resources/>        
	</head>
<body>
<e:helloworld/>
    </body>
    </html>
</f:view>

Run the example

Drop to the command line and “cd” to the project’s base folder (where the pom.xml file is).

Type the following command to start the jetty servlet engine.
mvn jetty:run
Navigate to: http://localhost:8080/examples/resources.jsf

View source on the page should show something like this…
src/main/webapp/examples/resources.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html>
    <head>
        <title>Resources JSF Example</title>        
		
<link rel="stylesheet" type="text/css" href="http://dev.sencha.com/deploy/ext-3.3.1/resources/css/ext-all.css" />
<script type="text/javascript" src="http://dev.sencha.com/deploy/ext-3.3.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="http://dev.sencha.com/deploy/ext-3.3.1/ext-all.js"></script>

        
	</head>
<body>
<div style="color: red">HelloWorld! from renderer.</div>
    </body>
    </html>

To demonstrate Dynamic Resources

To demonstrate that the inclusion of the resources is dynamic, just remove the helloWorld tag from the body of the jsp page. Hit refresh on your browser and you will see that the head of the page no longer includes the css and the javascript files.

To productionalize the code

The example above can be improved by introducing a “ResourceServlet” that is responsible for resolving the libraries via “relative” links. The Resource Servlet can be programmed to return the files from the classpath (within the jar) thus simplifying the deployment.

If you run into trouble

The code on this page has been tested and worked at the time of this writing. If its not working for you please make sure you double check each step to make sure nothing was missed. If you are still having trouble just write a small note about it below and I will try to help you out.

That’s all for now

23
Sep
10

JSF Custom Components Hello World

This page describes how to write a JSF Custom component to print “Hello World” to the page.

This is a demonstration on how to create JSF custom tags using the Sun’s JSF Reference Implementation. This page will lay a solid foundation on how to write custom components to wrap any library or tool kits available for web development into standard JSF components.

This is crazy but these are the steps involved in creating a new JSF Component.

New JSF Custom Component Checklist:

  1. Component Class – This is the Java class that represents the core logic of the component. This class can be coded to render itself or use the help of a the “Renderer” class.
  2. Component Renderer – Responsible for rendering the component on the page.
  3. Tag Class – This is class brings the “custom tag” concept onto the table. Custom Tag libraries were introduced with the JSP 1.1 specification back in December 1999. Today the JSF specification builds upon the custom tag library concept.
  4. Tag Library Descriptor – XML file necessary for the custom tag.
  5. Faces Context – XML file necessary for the custom component.

Requirements

  • Maven 2 or later
  • JSF 1.2 or above
  • Java 5 or later

Start a new Maven Project

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

For the group id enter: org.extjsf
For the artifactId enter: jsfCustom

Answer the rest of the questions using defaults [Hit Enter].

cd to the project’s folder

Next we create the src/main/java folder since this is not done for us using the archetype.

on unix you type:

cd jsfCustom
mkdir -p src/main/java

Project Configuration File

Modify the pom.xml file. It should look like this…

vi pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.extjsf</groupId>
    <artifactId>extJSF</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>jsfTestWeb Maven Webapp</name>
    <url>http://extjsf.org</url>
    <dependencies>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>1.2_02</version>
            <scope>compile</scope> <!--use compile scope for testing with jetty-->
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>1.2-b19</version>
            <scope>compile</scope> <!--use compile scope for testing with jetty-->
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
			<artifactId>geronimo-jsp_2.1_spec</artifactId>
			<version>1.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-servlet_2.5_spec</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
		<dependency>
		    <groupId>javax.el</groupId>
		    <artifactId>el-api</artifactId>
		    <version>1.0</version>
		    <scope>provided</scope>
		</dependency>        
    </dependencies>
    <build>
        <finalName>extJSFWeb</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
                <configuration>
                    <scanIntervalSeconds>2</scanIntervalSeconds>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <configuration>
                    <wtpapplicationxml>true</wtpapplicationxml>
                    <wtpversion>1.5</wtpversion>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                    <classpathContainers>
                        <classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
                        <classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
                    </classpathContainers>
                    <additionalProjectFacets>
                        <jst.web>2.5</jst.web>
                        <jst.jsf>1.2</jst.jsf>
                    </additionalProjectFacets>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

web.xml

This is boiler plate code. There are no references to the custom components.

We will start from a fresh web.xml file so delete the one that is there.
rm src/main/webapp/WEB-INF/web.xml

Edit the file using a text editor.
vi src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>

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

</web-app>

Create the Component Class

As mentioned above this is the main class that represents the custom component. It can either render itself or have another class assigned to do the work of rendering. In this case all we are defining is the component family. This is the package we will use to place all the components in.

Create the directory if it does not exist
mkdir -p src/main/java/org/extjsf/component/helloworld

Edit the file using a text editor.
vi src/main/java/org/extjsf/component/helloworld/HtmlHelloWorld.java

package org.extjsf.component.helloworld;

import javax.faces.component.UIComponentBase;

public class HtmlHelloWorld extends UIComponentBase {
	public static final String COMPONENT_FAMILY = "org.extjsf.component";

	@Override
	public String getFamily() {
		return COMPONENT_FAMILY;
	}
}

Create the Component Renderer

This is where the actual rendering of the hello world message is done.
Edit the file using a text editor.
vi src/main/java/org/extjsf/component/helloworld/HelloWorldRenderer.java

package org.extjsf.component.helloworld;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;

public class HelloWorldRenderer extends Renderer {
    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("div", component);
        writer.writeAttribute("style", "color: red", null);
        writer.writeText("HelloWorld! from renderer.", null);
        writer.endElement("div");
    }
}

Create the Tag Class

This is the custom tag class that will allow the JSP to communicate with the JSF component. You can consider this to be a “hook” into the Java Server Pages API. Allows the JSP page developer to pass “parameters” as tag attributes to the JSF custom component.

The Custom Tag class “componentType” is used to lookup the JSF Component class using the faces-context.xml.
Edit the file using a text editor.
vi src/main/java/org/extjsf/component/helloworld/HtmlHelloWorldTag.java

package org.extjsf.component.helloworld;

import javax.faces.webapp.UIComponentTag;

public class HtmlHelloWorldTag extends UIComponentTag {
    @Override
    public String getComponentType() {
        return "HtmlHelloWorld";
    }
    public String getRendererType() {
        return "org.extjsf.component.HelloWorldRenderer";
    }
}

Create the Tag Library Descriptor

Edit the file using a text editor.
vi src/main/webapp/WEB-INF/htmlHelloWorld.tld

<taglib 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/web-
jsptaglibrary_2_0.xsd"
	version="2.0">
<tlib-version>1.0</tlib-version>
<uri>http://extjsf.org/components</uri>

<tag>
	<description>Hello World Tag</description>
	<name>helloworld</name>
	<tag-class>org.extjsf.component.helloworld.HtmlHelloWorldTag</tag-class>
</tag>
</taglib>

Modify the faces-config.xml

Edit the file using a text editor.
vi src/main/webapp/WEB-INF/faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config 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-facesconfig_1_2.xsd"
              version="1.2">

<component>
	<component-type>HtmlHelloWorld</component-type>
	<component-class>org.extjsf.component.helloworld.HtmlHelloWorld</component-class>
</component>
<render-kit>
	<renderer>
		<component-family>org.extjsf.component</component-family>
		<renderer-type>org.extjsf.component.HelloWorldRenderer</renderer-type>
		<renderer-class>org.extjsf.component.helloworld.HelloWorldRenderer</renderer-class>
	</renderer>
</render-kit>

</faces-config>

Create the JSP Page

Create the examples directory
mkdir -p src/main/webapp/examples

Edit the file using a text editor.
vi src/main/webapp/examples/helloWorld.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="e" uri="http://extjsf.org/components" %>

<f:view>
    <html>
    <head>
        <title>Hello World JSF Example</title>
</head>
    <body>
<e:helloworld/>
    </body>
    </html>
</f:view>

The following is how all these files are related:

  1. Servlet Container encounters a <e:helloworld/> tag and checks the tag library described by the “http://extjsf.org/components&#8221; tag library xml file.
  2. The tag library xml file indicates that the “org.extjsf.component.helloworld.HtmlHelloWorldTag” is responsible for handling the custom tag.
  3. The System inspects the HtmlHelloWorldTag and gets the component Type and RendererType.
  4. The System inspects the faces-config.xml reads that “HtmlHelloWorld” component type is handled by the “HtmlHelloWorld” component class, and rendered by the “HelloWorldRenderer”.
  5. The family that is specified in the component class is used to make a determination on what renderer family to use.

Run the application

Drop to the command line and navigate to the project’s base directory (location of the pom.xml file).

Execute the following command to test the web application using Jetty servlet engine.

mvn jetty:run

Navigate to: http://localhost:8080/examples/helloWorld.jsf

Next steps

Classic Form Components:

INPUT
	text
	password
	checkbox
	image
	hidden
	file
LABEL

Buttons
-------

http://developer.yahoo.com/yui/button/

INPUT
	radio
	submit 
	reset
	button
BUTTON
SELECT

TEXTAREA
--------

http://developer.yahoo.com/yui/editor/

PRIMEFACES
----------

Mobile Components
-----------------
Pages &amp; Dialogs
Toolbars
	Header
	Footer
	Nav Bars
	Persistant Footer Nav
	
Buttons
	Inline Buttons (more narrow)
	Grouped Buttons
Layout
	Column Grids
	Collapsible Content
	
Form Elements
	Text
	Text Area
	Search Input
	Flip Switch
	Slider
	checkbox
	Radio
	Select

Lists
	Nested List
	Numbered List
	Split Button List
	Formatted Content

Advanced functionality:
Making AJAX requests for JSON data, Sorting Hiding of grid columns, grouping, row expanding, type ahead combo boxes, validation, Editor grid panel, saving preferences in browser cookies and in the database, live search functionality.

That’s all for now.

More to come.

25
Aug
10

Removing JSF Managed Bean from the Session

This page describes the process of cleaning up the session after using a JSF managed bean.

Background

JSF managed beans can be request or session scoped. If they are session scoped then they must be cleaned up manually after the user has navigated off the page. Otherwise they will hang around until the session times out.

In order to do a clean up just execute the following when the user performs the last step on the page.

  1. Program a cleanup() method in the managed bean (see below)
  2. Have the cleanup() method called by the last step the user takes on the page.
  3. Setup a nav-rule that allows the user to navigate to a new page.
	public String cleanup() {
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
		.getExternalContext().getSession(true);
		session.removeAttribute("page1MB");

		return "page2";
	}

The clean up method is called by a command button:

<h:commandButton value="cleanup" action="#{page1MB.cleanup}"/>

A nav rule that directs the user to another page:

	<navigation-rule>
		<from-view-id>/page1.jsp</from-view-id>
		<navigation-case>
			<from-outcome>page2</from-outcome>
			<to-view-id>/page2.jsp</to-view-id>
		</navigation-case>
	</navigation-rule>

Use a SnoopServlet to verify that the values have been removed:
http://numberformat.wordpress.com/2010/01/02/snoopservlet-example/

25
Aug
10

Using JSF to Display Table Data

This page describes the process of using JSF to manage data that appears in tables.

Below you see an example data table where each item has:

  1. A textbox where user can specify the quantity
  2. An edit button where they can select a basket
  3. Submit/add buttons that act on the whole collection of baskets.

Using DataTables

When you surface links to allow the user to select the current row object then bind with data table and use dataTable.rowData().

Steps to follow in order to use DataTables:

  • Create an HtmlDataTable attribute in your managed bean.
  • Create a List<GiftBasket> attribute that will hold the backing data
  • Create getter/setters for both attributes
  • In your <h:dataTable> element include a binding and value attributes that points to the htmlDataTable, and the backing List you added to the managed bean.

The Managed Bean is defined like this…

private List<GiftBasket> list = new ArrayList<GiftBasket>();
private HtmlDataTable dataTable;
    // getters setters omitted.

The dataTable is defined like this in the JSP. As you can see a “backing” list is still necessary to hold the table data.

<h:dataTable var="giftBasket" value="#{page1MB.list}" binding="#{page1MB.dataTable}">

The Action column is defined like this in the JSP.

<h:column>
    <f:facet name="header"><h:outputText value="Action"/></f:facet>
    <h:commandLink value="edit" action="#{page1MB.editBasket}"/>
</h:column>

The Add button is mapped to the following method. It populates the backing list with data.

	public String addAllGiftBaskets() {
		list = giftBasketDataManager.getAllGiftBaskets();
		return null; // stay on the same page
	}

As you can see the value attribute points to a standard ArrayList.

When you run the code the system should print “Edit basket called for: ” at the server console.

    public String editBasket() {
        GiftBasket basket = (GiftBasket)dataTable.getRowData();
        System.out.println("Edit basket called for: " + basket);
        return null;
    }

Using ListDataModel

DataModels allow you to do what dataTables can do. Examples for ListDataModel or any other DataModel are rare on the internet. the following article describes some more information about the topic: http://forums.sun.com/thread.jspa?threadID=653909

The following example is based on the screen shot above.

The big difference when using ListDataModel is that you only need to specify the “value” attribute of the dataTable element. A binding to a HtmlDataTable attribute is not necessary.

<h:dataTable var="giftBasket" value="#page1MB.selectedGiftBasketDataModel}" >

In your Managed Bean you define the following attribute.

private ListDataModel selectedGiftBasketDataModel =
    new ListDataModel(new ArrayList<GiftBasket>());

To populate the table with data you click the add button and that executes the following code in the managed bean.

	public String addAllGiftBaskets() {
		List<GiftBasket> list = giftBasketDataManager.getAllGiftBaskets();
		selectedGiftBasketDataModel.setWrappedData(list);
		return null;
	}

To get a reference to the data for a single row that was selected just do the following:

	public String editBasket() {
		GiftBasket basket = (GiftBasket)selectedGiftBasketDataModel.getRowData();
		System.out.println("Edit basket called for: " + basket);
		return null; // stay on the same page
	}

To print data for all the rows, do the following.

	public String printResults() {
		List<GiftBasket> list = (List<GiftBasket>) selectedGiftBasketDataModel.getWrappedData();

		for(GiftBasket basket : list) {
			System.out.println(basket);
		}
		return null; // stay on the same page
	}

Complete JSP

This is the “ListDataModel” version of the JSP used in the above example:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="f"  uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h"  uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Page 1</title>
<link rel="stylesheet" type="text/css" href="styles/style.css" />
</head>
<body>
<f:view>
<h:form id="myform">
<h:messages showDetail="#{true}" showSummary="#{false}" />
    <div id="left" style="margin-bottom: 20px;">
		The following is an example a user input form created from a database.
    </div>

	<h:dataTable var="giftBasket" value="#{page1MB.selectedGiftBasketDataModel}" >
		<h:column>
			<f:facet name="header"><h:outputText value="ID"/></f:facet>
			<h:outputText value="#{giftBasket.id}"/>
		</h:column>
		<h:column>
			<f:facet name="header"><h:outputText value="Gift Basket Type"/></f:facet>
			<h:outputText value="#{giftBasket.type}"/>
		</h:column>
		<h:column>
			<f:facet name="header"><h:outputText value="Quantity"/></f:facet>
			<h:inputText value="#{giftBasket.quantity}" size="4"/>
		</h:column>
		<h:column>
			<f:facet name="header"><h:outputText value="Action"/></f:facet>
			<h:commandLink value="edit" action="#{page1MB.editBasket}"/>
		</h:column>
	</h:dataTable>
	<h:commandButton value="submit" action="#{page1MB.printResults}"/>
	<h:commandButton value="add" action="#{page1MB.addAllGiftBaskets}"/>
</h:form>
</f:view>
</body>
</html>
14
May
10

Getting Apache Tomahawk to work in Websphere 6.1 and JSF 1.1

This page describes how to get Apache MyFaces Tomahawk to work with IBM Websphere 6.1 / JSF 1.1 / Servlet Specification 2.4 combo.

Requirements

  • Java 1.5
  • Maven 2
  • Eclipse or IBM RAD 7.5 Development Environment
  • Websphere Test Environment (understand how to create and deploy an Ear file)
  • Servlet 2.4, JSF 1.1 (Default in WAS 6.1)

Background

Websphere 6.1 Application server comes pre-installed with Sun’s Reference Implementation of JSF. Unless you change the Classloader policy of your application to PARENT_LAST it is difficult to get the myfaces-impl and myfaces-api to play nice with the JARS that come pre-installed. Also if you are converting an existing application, then changing the classloader policy can open up a new can of worms. Therefore it is just easier to use the JSF Implementation available by default on the Websphere App Server.

Note: The examples in this page do NOT use the “standard maven directory structure”.  The jsp and the WEB-INF files will be kept in the “WebContent” folder instead of “src/main/webapp”. This is on purpose since we want this project to work in RAD 7.5 development environment.

Project Setup

Create a blank project using Maven archetype. Open up the command prompt and navigate to an empty directory.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

groupId: com.test
artifactId: jsfTest

Answer the rest of the questions with defaults “Just hit the enter key”

Since we are not using the maven standard directory structure you need to add the “WebContent” and the “WebContent/WEB-INF” folders right under the project main directory. Once these folders are created then move the files from the “src/main/webapp” to “WebContent”.

Settings

The archetype will set up most of the directory structure and generate a blank web.xml file and a pom.xml. At this time open up the pom.xml file and modify it to the way you see it below.

Notice in the file below, the myfaces-impl and myfaces-api are in the “provided” scope. This means that the jars will be available during compile time but will NOT be included during runtime.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>jsfTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>jsfTest Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

	<dependency>
	    <groupId>org.apache.myfaces.tomahawk</groupId>
	    <artifactId>tomahawk</artifactId>
	    <version>1.1.9</version>
	</dependency>

	<dependency>
	    <groupId>org.apache.myfaces.core</groupId>
	    <artifactId>myfaces-api</artifactId>
	    <version>1.1.7</version>
	    <scope>provided</scope> <!--use compile scope for testing with jetty-->
	</dependency>

	<dependency>
	    <groupId>org.apache.myfaces.core</groupId>
	    <artifactId>myfaces-impl</artifactId>
	    <version>1.1.7</version>
	    <scope>provided</scope> <!--use compile scope for testing with jetty-->
	</dependency>

  </dependencies>
  <build>
    <finalName>testWebApp</finalName>
    <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.0.2</version>
        <configuration>
            <source>1.5</source>
            <target>1.5</target>
        </configuration>
    </plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
				  <webappDirectory>WebContent</webappDirectory>
					<webResources>
						<resource>
							<directory>WebContent</directory>
						</resource>
					</webResources>
					<outputDirectory>
						WebContent/WEB-INF/classes
					</outputDirectory>
					<warSourceDirectory>WebContent</warSourceDirectory>
					<warName>jsfTest</warName>
					<webXml>WebContent/WEB-INF/web.xml</webXml>
				</configuration>
			</plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
            <wtpapplicationxml>true</wtpapplicationxml>
            <wtpversion>1.5</wtpversion>
            <downloadSources>true</downloadSources>
            <downloadJavadocs>true</downloadJavadocs>
					<outputDirectory>
						WebContent/WEB-INF/classes
					</outputDirectory>
            <classpathContainers>
							<classpathContainer>
								org.eclipse.jst.server.core.container/com.ibm.ws.ast.st.runtime.runtimeTarget.v61/was.base.v61
							</classpathContainer>
							<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/WebSphere v6.1 JRE</classpathContainer>
                <classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
                <classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
            </classpathContainers>
            <additionalProjectFacets>
                <jst.jsf>1.2</jst.jsf>
            </additionalProjectFacets>
        </configuration>
    </plugin>
		    <plugin>
		        <groupId>org.mortbay.jetty</groupId>
		        <artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
		        <configuration>
		            <webAppSourceDirectory>WebContent</webAppSourceDirectory>
					<scanTargets>
						<scanTarget>WebContent/WEB-INF</scanTarget>
					</scanTargets>
		            <scanIntervalSeconds>2</scanIntervalSeconds>
		        </configuration>
		    </plugin>

    </plugins>
  </build>
</project>

WebContent/WEB-INF/web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="WebApp_ID"
	version="2.4"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <display-name>Archetype Created Web Application</display-name>

	<filter>
	        <filter-name>MyFacesExtensionsFilter</filter-name>
	        <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
	</filter>

	<!-- extension mapping for adding <script/>, <link/>, and other resource tags to JSF-pages  -->
	<filter-mapping>
	    <filter-name>MyFacesExtensionsFilter</filter-name>
	    <!-- servlet-name must match the name of your javax.faces.webapp.FacesServlet entry -->
	    <servlet-name>Faces Servlet</servlet-name>
	</filter-mapping>

	<!-- extension mapping for serving page-independent resources (javascript, stylesheets, images, etc.)  -->
	<filter-mapping>
	    <filter-name>MyFacesExtensionsFilter</filter-name>
	    <url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
	</filter-mapping>

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

WebContent/WEB-INF/faces-config.xml

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

<!DOCTYPE faces-config PUBLIC
    "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
    "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

</faces-config>

WebContent/index2.jsp

<%@ page session="false" contentType="text/html;charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t" %>

<html>
<body>
<f:view>
    <h:form>
        <f:verbatim>
            <h1>Input Text Help</h1>
        </f:verbatim>
        <t:outputText value="hello tomahawk"/>

        <h:outputText value="Select helper text:"/>
        <t:inputTextHelp value="" id="i1" helpText="Hello World"/>
        <t:div/>
        <h:outputText value="Select helper text:"/>
        <t:inputTextHelp value="" id="i2" selectText="true" helpText="TT.MM.JJJJ"/>
    </h:form>
</f:view>
</body>
</html>

Generated Javascript in Websphere 6.1 (important)

This step is important don’t skip it.

The Apache Tomahawk framework generates javascript for some of the components. You need to enable the following setting in “Application servers > server1 > Web container > Custom Properties”
Set the custom property “com.ibm.ws.webcontainer.invokefilterscompatibility” = true

Also don’t forget to do the same thing when your program reaches QA or PROD environments.

Testing using Websphere Test Environment

In order to run a Dynamic Web Project in the Application server built into RAD just create an Enterprise Project and put the Web Project into the EAR. Deploy the ear just like any other project. Start the application server and navigate to http://localhost:9081/jsfTest/index2.jsf

Testing using Jetty

This application can also be tested using jetty servlet engine. You just need to make sure to change the two <scope>provided</scope> tags to <scope>compile</scope>

After changing the pom.xml file above just type “mvn jetty:run” on the command line and then navigate to http://localhost:8080/index2.jsf using your browser.

References

01
Feb
10

Display Google Map Using JSF

This page describes the process of creating a web application to display a google map using the Gmap4JSF tag library. All the Javascript code to display the map is generated by the JSF library.

Requirements

  • Maven – installed and configured

Generate a new project using maven
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
groupId: com.test
artifactId: googleMapTest
choose defaults for the rest of the questions.

Generate the eclipse project
mvn eclipse:clean eclipse:eclipse

Import the project into eclipse

Modify the pom.xml file.
My pom.xml looks like this…

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>googleMapTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>googleMapTest Maven Webapp</name>
  <url>http://maven.apache.org</url>

    <repositories>
        <repository>
            <id>googlecode.com</id>
            <url>http://gmaps4jsf.googlecode.com/svn/trunk/gmaps4jsf-repo</url>
        </repository>
    </repositories>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>com.googlecode.gmaps4jsf</groupId>
            <artifactId>gmaps4jsf-core</artifactId>
            <version>1.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-api</artifactId>
            <version>1.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-impl</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
  </dependencies>
  <build>
    <finalName>googleMapTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
                        <configuration>
                         <scanIntervalSeconds>2</scanIntervalSeconds>
                        </configuration>
            </plugin>
        </plugins>
  </build>
</project>

Regenerate the eclipse project and refresh.
mvn eclipse:clean eclipse:eclipse

src/main/webapp/WEB-INF/web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

src/main/webapp/index.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Your Page Title</title>
<meta http-equiv="REFRESH" content="0;url=<c:url value='/faces/displayMap.jsp'/>"></HEAD>
<BODY>
Optional page text here.
</BODY>
</HTML>

src/main/webapp/displayMap.jsp

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://code.google.com/p/gmaps4jsf/" prefix="m"%>
<!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">
<head>
<title>Welcome to GMaps4JSF</title>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<script
	src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAxrVS1QxlpJHXxQ2Vxg2bJBQdkFK-tWRbPPQS4ACM1pq_e-PltxQXeyH20wQuqDaQ_6EM5UeGGVpnIw"
	type="text/javascript"></script>

</head>
<body onunload="GUnload()">
<f:view>
	<h:form id="form">
		<m:map width="600px" height="600px" latitude="37.4"
			longitude="-122">
			<m:marker latitude="37.4" longitude="-122" draggable="true"/>
			<m:htmlInformationWindow latitude="37.4" longitude="-122"
				htmlText="<B>Hello World</B>" />
		</m:map>
	</h:form>
</f:view>
</body>
</html>

Test the project in Jetty

mvn clean compile jetty:run

navigate to http://localhost:8080/

You should see a map with a popup that says hello world. Read the Gmap4JSF website for more detailed instructions on how to use the tag.

Reference

31
Jan
10

Collapsible Navigation Bar in Apache Tobago

Typical Web applications contain some form of left navigation bar. This page describes how to create a simple tree like collapsible navigation bar using Apache MyFaces Tobago.

Requirements

At this time please complete a simple Hello World application (previous link) before proceeding…

For the site navigation we will use the tc:tree element to display a collapsible table.

Implementing the Model

The code listed below sets up a static Tree Structure that represents the left navigation bar. Each tree element will specify the key and the “outcome”. The key is used to find the Text to display for that item. And the “outcome” will be used by JSF to identify what page to forward the request to.

package com.test;

import java.util.Enumeration;

import javax.faces.context.FacesContext;
import javax.swing.tree.DefaultMutableTreeNode;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.tobago.context.ResourceManagerUtil;
import org.apache.myfaces.tobago.model.TreeState;

/**
 * The following constructs a very basic static navigation bar.
 */
public class Navigation {

  private static final Log LOG = LogFactory.getLog(Navigation.class);

  private DefaultMutableTreeNode tree;

  private TreeState state;

  public Navigation() {

    tree = new DefaultMutableTreeNode(new Node("test", "Root", null));

    DefaultMutableTreeNode home = new DefaultMutableTreeNode(new Node("test", "home", "pages/home"));
    DefaultMutableTreeNode products = new DefaultMutableTreeNode(new Node("test", "products", "pages/products"));

    DefaultMutableTreeNode portableAudio = new DefaultMutableTreeNode(new Node("test", "portable_audio", "pages/portable_audio"));
    portableAudio.add(new DefaultMutableTreeNode(new Node("test", "cd", "pages/cd")));
    portableAudio.add(new DefaultMutableTreeNode(new Node("test", "mp3", "pages/mp3")));

    DefaultMutableTreeNode books = new DefaultMutableTreeNode(new Node("test", "books", "pages/books"));

    DefaultMutableTreeNode newReleases = new DefaultMutableTreeNode(new Node("test", "new_releases", "pages/new_releases"));

    newReleases.add(new DefaultMutableTreeNode(new Node("test", "action_adventure","pages/action_advendure")));

    books.add(newReleases);

    products.add(portableAudio);
    products.add(books);

    tree.add(home);
    tree.add(products);

    state = new TreeState();
    state.expand(tree, 1);
    state.setMarker(home);
  }

  public String navigate() {
    Node selected = (Node) state.getMarker().getUserObject();
    return selected.getOutcome();
  }

  public void updateMarker(String viewId) {
    Enumeration enumeration = tree.depthFirstEnumeration();
    while (enumeration.hasMoreElements()) {
      DefaultMutableTreeNode maybeMarker = ((DefaultMutableTreeNode) enumeration.nextElement());
      Node node = (Node) maybeMarker.getUserObject();
      if (node.getOutcome() != null && viewId.contains(node.getOutcome())) {
        state.setMarker(maybeMarker);
        break;
      }
    }
  }

  public DefaultMutableTreeNode getTree() {
    return tree;
  }

  public void setTree(DefaultMutableTreeNode tree) {
    this.tree = tree;
  }

  public TreeState getState() {
    return state;
  }

  public void setState(TreeState state) {
    this.state = state;
  }

  public String gotoFirst() {
    DefaultMutableTreeNode first = tree.getNextNode();
    state.setMarker(first);
    return ((Node) first.getUserObject()).getOutcome();
  }

  public String gotoPrevious() {
    DefaultMutableTreeNode previousNode = state.getMarker().getPreviousNode();
    if (previousNode != null) {
      state.setMarker(previousNode);
      return ((Node) previousNode.getUserObject()).getOutcome();
    }
    return null;
  }

    public String gotoNext() {
    DefaultMutableTreeNode nextNode = state.getMarker().getNextNode();
    if (nextNode != null) {
      state.setMarker(nextNode);
      return ((Node) nextNode.getUserObject()).getOutcome();
    }
    return null;
  }

  public boolean isFirst() {
    return state.getMarker().getPreviousNode().isRoot();
  }

  public boolean isLast() {
    return state.getMarker().getNextNode() == null;
  }

  public static class Node {

    private String title;
    private String id;
    private String outcome;

    public Node(String resourceBundle, String key, String outcome) {
      this.title = ResourceManagerUtil.getProperty(
          FacesContext.getCurrentInstance(), resourceBundle, key);
      this.id = key;
      this.outcome = outcome;
    }

    public String getTitle() {
      return title;
    }

    public void setTitle(String title) {
      this.title = title;
    }

    public String getId() {
      return id;
    }

    public void setId(String id) {
      this.id = id;
    }

    public String getOutcome() {
      return outcome;
    }

    public void setOutcome(String outcome) {
      this.outcome = outcome;
    }
  }
}

Create the resource bundle file

need to create a resource bundle file in

src/main/webapp/tobago-resource/html/standard/standard/property/test.properties.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<entry key="neeraj_name">Neeraj Verma</entry>
	<entry key="home">Home</entry>
	<entry key="products">Products</entry>
	<entry key="portable_audio">Portable Audio</entry>
	<entry key="cd">CD</entry>
	<entry key="mp3">MP3</entry>
	<entry key="books">Books</entry>
	<entry key="new_releases">New Releases</entry>
	<entry key="action_adventure">Action Adventure</entry>
</properties>

Modify Navigation Rules

The next step is to setup the navigation rules. Make the changes highlighted below to the faces-config.xml file. The navigation rules section describes how to forward the user to the next page when they click on the navigation bar. The navigation bar contains the “outcome” for each entry.

src/main/webapp/WEB-INF/faces-config.xml

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

<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

  <application>
    <locale-config>
      <default-locale>en</default-locale>
      <supported-locale>de</supported-locale>
      <supported-locale>de_DE</supported-locale>
      <supported-locale>de_AT</supported-locale>
      <supported-locale>de_CH</supported-locale>
    </locale-config>
  </application>

	<navigation-rule>
		<navigation-case>
			<from-outcome>pages/home</from-outcome>
			<to-view-id>pages/home.jsp</to-view-id>
		</navigation-case>
		<navigation-case>
			<from-outcome>pages/products</from-outcome>
			<to-view-id>pages/products.jsp</to-view-id>
		</navigation-case>
		<navigation-case>
			<from-outcome>pages/portable_audio</from-outcome>
			<to-view-id>pages/portable_audio.jsp</to-view-id>
		</navigation-case>
		<navigation-case>
			<from-outcome>pages/cd</from-outcome>
			<to-view-id>pages/cd.jsp</to-view-id>
		</navigation-case>
	</navigation-rule>

  <managed-bean>
    <managed-bean-name>navigation</managed-bean-name>
    <managed-bean-class>com.test.Navigation</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>
</faces-config>

Implement the Target Pages

As you can see above each “outcome” leads to a different jsp page. For that reason please take the time to create the 4 jsp’s listed above

  1. src/main/webapp/pages/home.jsp
  2. src/main/webapp/pages/products.jsp
  3. src/main/webapp/pages/portable_audio.jsp
  4. src/main/webapp/pages/cd.jsp

You can put anything you want in those JSP’s “Test 123 [jsp name]” whatever…

Implement the page

Modify the helloWorld.jsp page to look like this: The lines highlighted below are the differences from the file posted in my previous article.

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<tc:loadBundle basename="test" var="testBundle"/>

<f:view>
  <tc:page>
    <f:facet name="layout">
      <tc:gridLayout/>
    </f:facet>
    <tc:tree value="#{navigation.tree}"
             mode="menu"
             id="nav"
             nameReference="userObject.title"
             idReference="userObject.id"
             tipReference="userObject.title"
             state="#{navigation.state}"
             showIcons="false"
             showJunctions="false"
             showRoot="false">
      <f:facet name="treeNodeCommand">
        <tc:link action="#{navigation.navigate}" immediate="true"/>
      </f:facet>
    </tc:tree>

  </tc:page>
</f:view>

Test the Application

Start the application in jetty.

mvn jetty:run

Navigate to http://localhost:8080/

You should see a navigation menu smack in top of the html page. It will most likely take up the whole browser window. Next we need to create a layout and place this navigation bar on the left of the page. Please read my next article where I describe how this is done.

That’s All for now…

31
Jan
10

Page Layout with Apache MyFaces Tobago

This page describes the process of setting up a reusable layout for your web application.

Requirements

This page will continue where we left off. Therefore if you have not done so already please follow the instructions to create a simple hello world application + navigation bar.

In this page we will create a banner and footer pages. We will take the navigation bar and place it on the left side of the page. In the body section we will display a simple calendar component.

Tag File

src/main/webapp/WEB-INF/tags/layout/overview.tag

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view >
  <tc:page applicationIcon="icon/favicon.ico" label="Test Page Title" id="page" width="1000px" height="750px">

    <jsp:include page="/menu.jsp" />

    <f:facet name="layout">
      <tc:gridLayout border="0" columns="*;4*"
        margin="10px" rows="100px;*;fixed"  />
    </f:facet>

    <tc:cell spanX="2">
      <jsp:include page="/header.jsp"/>
    </tc:cell>

    <tc:cell spanY="2" >
      <jsp:include page="/navigation.jsp"/>
    </tc:cell>

    <tc:cell>
      <jsp:doBody/>
    </tc:cell>

    <tc:cell>
      <jsp:include page="/footer.jsp" />
    </tc:cell>

  </tc:page>
</f:view>

Header

src/main/webapp/header.jsp

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:subview id="header" >

  <tc:panel>
    <tc:out value="This is the header..."/>
  </tc:panel>
</f:subview>

Menu

src/main/webapp/menu.jsp

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:subview id="menu" >
<!-- This is a place holder for the top menu -->
</f:subview>

Footer

src/main/webapp/footer.jsp

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:subview id="footer" >

  <tc:panel>
    <tc:out value="This is the footer..."/>
  </tc:panel>
</f:subview>

Navigation

src/main/webapp/navigation.jsp

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:subview id="navigation" >

  <tc:panel>
		<tc:box label="Navigation">
			<tc:tree value="#{navigation.tree}" mode="menu" id="nav"
				nameReference="userObject.title" idReference="userObject.id"
				tipReference="userObject.title" state="#{navigation.state}"
				showIcons="false" showJunctions="false" showRoot="false">
				<f:facet name="treeNodeCommand">
					<tc:link action="#{navigation.navigate}" immediate="true" />
				</f:facet>
			</tc:tree>
		</tc:box>
  </tc:panel>
</f:subview>

Actual Page

This page uses the layout we defined above. It specifies only the body of the page. This is typically where we will put the components that interact with the user.
src/main/webapp/helloLayout.jsp

<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>

<layout:overview>
  <jsp:body>
  	<tc:out value="This is the main body..."/>
  	<tc:panel >
  		<f:facet name="layout">
  			<tc:gridLayout rows="fixed;*" columns="fixed;*"/>
  		</f:facet>
  	<tc:box label="calendar component" height="225" id="box">
  		<tc:calendar />
  	</tc:box>
  	<tc:cell id="abc"/>
  	<tc:cell id="abcd"/>
  	</tc:panel>
  </jsp:body>
</layout:overview>

Test the application

Start jetty and test the application by navigating to:

http://localhost:8080/tobagoTestWeb/faces/helloLayout.jsp

That’s all for now…

31
Jan
10

Using Resource Bundles with Apache Tobago

This page describes the steps necessary to use resource bundles in your Apache Tobago based applications.

This page builds upon the Hello World Application and modifies it to use resource bundles to display messages. If you have not done so already please click on the above link to complete the hello world application before proceeding.

To allow tobago to use property files add the following to:

src/main/webapp/WEB-INF/tobago-config.xml

<resource-dir>tobago-resource</resource-dir>

The above specifies that the tobago-resource directory contains files used for application display. The resource directory follows a standard directory structure. This allow for customization for different themes and locales.

src/main/webapp/tobago-resource/html/standard/standard/property contains the properties files.

add the following
src/main/webapp/tobago-resource/html/standard/standard/property/test.properties.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
 <entry key="neeraj_name">Neeraj Verma</entry>
 </properties>

src/main/webapp/hello.jsp should look like this. The lines highlighted below indicate where the changes were made.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>

<tc:loadBundle basename="test" var="testBundle"/>  

<f:view>
  <tc:page>
    <f:facet name="layout">
      <tc:gridLayout/>
    </f:facet>
    <tc:out value="Hello World"/>
    <tc:out escape="false" value="#{testBundle.neeraj_name}" />
  </tc:page>
</f:view>

Save and run the page in jetty

mvn jetty:run

Navigate to http://localhost:8080/

You should see hello world up top and somewhere in the middle you will see my name.

That’s all for now.

28
Jan
10

Hello World with Apache Tobago

This page describes the process of setting up and running a Hello World Application using Apache MyFaces Tobago. This is similar to the blank application that is published by the apache group however unlike the blank application this one is totally independent. It is a standalone application that will run on its own without any complicated parent project relationships. Using this page you should be up and running in about 20 minutes.

Requirements

  • A basic understanding of JSF
  • Maven installed and configured

Overview

The hello world application consists of the following files

  1. pom.xml file that describes the project
  2. web.xml that describes the application
  3. faces-config.xml – very basic faces configuration file
  4. tobago-config.xml – very basic tobago configuration file
  5. hello.jsp – The actual hello world jsp that prints the message at “/faces/hello.jsp”

Generate the project

We start with the pom.xml file.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

groupId: com.test
artifactId: tobagoTestWeb
Leave the rest defaults

Import it into Eclipse

Import the project by clicking import existing project into workspace.

Modify the POM.xml file

Once the project is built make sure the poml.xml file looks like this:
I know the pom.xml file is a bit large but “It is what it is…”
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>test</groupId>
	<artifactId>jsfTestWeb</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>jsfTestWeb Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

<!-- This is tobago itself + 1 theme -->
		<dependency>
			<groupId>org.apache.myfaces.tobago</groupId>
			<artifactId>tobago-core</artifactId>
			<version>1.0.24</version>
			<exclusions>
				<exclusion>
					<groupId>sun.jdk</groupId>
					<artifactId>tools</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.myfaces.tobago</groupId>
			<artifactId>tobago-theme-speyside</artifactId>
			<version>1.0.24</version>
		</dependency>

<!-- Start Tobago dependencies -->
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.7.0</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>commons-digester</groupId>
			<artifactId>commons-digester</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.1</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1</version>
		</dependency>
<!-- End Tobago dependencies -->
<!-- Start JSTL -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
		</dependency>
		<dependency>
			<groupId>taglibs</groupId>
			<artifactId>standard</artifactId>
			<version>1.1.2</version>
		</dependency>
<!-- End JSTL -->

<!-- Start JSF and MyFaces -->
		<dependency>
			<groupId>org.apache.myfaces.core</groupId>
			<artifactId>myfaces-api</artifactId>
			<version>1.1.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.myfaces.core</groupId>
			<artifactId>myfaces-impl</artifactId>
			<version>1.1.7</version>
		</dependency>
<!-- End JSF and MyFaces -->

	</dependencies>
	<build>
		<finalName>jsfTestWeb</finalName>
		<plugins>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
				<configuration>
					<scanIntervalSeconds>2</scanIntervalSeconds>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

web.xml

that describes the application
src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
    version="2.4">

  <display-name>Hello World Tobago Application</display-name>
  <context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>
    <param-value>false</param-value>
  </context-param>  

  <filter>
    <filter-name>multipartFormdataFilter</filter-name>
    <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>multipartFormdataFilter</filter-name>
    <url-pattern>/faces/*</url-pattern>
  </filter-mapping>

<!--  workaround (e.g. for Oracle AS 10.1.2.0.0)-->
  <listener>
    <listener-class>org.apache.myfaces.tobago.webapp.TobagoServletContextListener</listener-class>
  </listener>

  <!-- servlet -->

  <servlet>
    <servlet-name>FacesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>ResourceServlet</servlet-name>
    <servlet-class>org.apache.myfaces.tobago.servlet.ResourceServlet</servlet-class>
  </servlet>

  <!-- servlet-mapping -->

  <servlet-mapping>
    <servlet-name>FacesServlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>ResourceServlet</servlet-name>
    <url-pattern>/org/apache/myfaces/tobago/renderkit/*</url-pattern>
  </servlet-mapping>

  <!-- The Usual Welcome File List -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

faces-config.xml

very basic faces configuration file
src/main/webapp/WEB-INF/faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>
  <application>
    <locale-config>
      <default-locale>en</default-locale>
      <supported-locale>de</supported-locale>
      <supported-locale>de_DE</supported-locale>
      <supported-locale>de_AT</supported-locale>
      <supported-locale>de_CH</supported-locale>
    </locale-config>
  </application>
</faces-config>

tobago-config.xml

src/main/webapp/WEB-INF/tobago-config.xml
very basic tobago configuration file

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

<!DOCTYPE tobago-config PUBLIC
    "-//The Apache Software Foundation//DTD Tobago Config 1.0//EN" "tobago-config_1_0.dtd">

<tobago-config>
  <theme-config>
    <default-theme>speyside</default-theme>
  </theme-config>
</tobago-config>

hello.jsp

And Lastly the most important file in the whole application… The actual hello world jsp that prints the message when you navigate to: “/faces/hello.jsp”
src/main/webapp/hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>
<f:view>
  <tc:page>
    <f:facet name="layout">
      <tc:gridLayout/>
    </f:facet>
    <tc:out value="Hello World"/>
  </tc:page>
</f:view>

index.jsp

src/main/webapp/index.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Your Page Title</title>
<meta http-equiv="REFRESH" content="0;url=<c:url value='/faces/hello.jsp'/>"></HEAD>
<BODY>
Optional page text here.
</BODY>
</HTML>

Run the Application

At this time you can run the application in Jetty.

mvn jetty:run

navigate to http://localhost:8080/

Limitations

  • JSF only supports one renderkit (renderkitId) per page (f:view). Because Tobago has it’s own renderkitId you cannot use any non-Tobago components that need a renderer. This means that you will not be able to use tomahawk components on tobago pages.

That’s all for now…




Follow

Get every new post delivered to your Inbox.

Join 50 other followers