30
Dec
09

Listbox Picker Using JSF and Tomahawk


This page is about creating an HTML Switchlist or Picker using JSF and the Tomahawk library. We will start by creating a basic multiselect listbox and then convert that to a switchlist. If you have Maven installed you may follow along. The full program should not take more then 20 minutes to complete and have up and running.

Requirements

  • Maven
  • Eclipse or IDEA Java IDE
  • That’s about it :)

Step 1: Project Setup

cd to your workspace directory and create a new project using the maven archetype “maven-archetype-webapp”.

I did it the following way

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

Answer the rest of the questions like this… hit enter for the defaults.

Define value for groupId: : com.test 
Define value for artifactId: : testSwitchList
Define value for version:  1.0-SNAPSHOT: : 
Define value for package:  com.test: : 
Confirm properties configuration:
groupId: com.test
artifactId: testSwitchList
version: 1.0-SNAPSHOT
package: com.test
 Y: : 

Make sure you Answer the highlighted items exactly as above. The rest of the page depends on this.

cd testSwitchList; mvn eclipse:clean eclipse:eclipse (if you have IDEA then mvn idea:idea)

Import the project Into your IDE.

The pom.xml file should look like this…

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>testSwitchList</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>testSwitchList 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.core</groupId>
    <artifactId>myfaces-api</artifactId>
    <version>1.2.8</version>
</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-impl</artifactId>
    <version>1.2.8</version>
</dependency>
<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-servlet_2.5_spec</artifactId>
    <version>1.2</version>
    <type>jar</type>
    <scope>provided</scope>
</dependency>
  </dependencies>
  <build>
    <finalName>testSwitchList</finalName>
<plugins>
    <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
                <version>7.0.0pre1</version>
        <configuration>
            <scanIntervalSeconds>2</scanIntervalSeconds>
        </configuration>
    </plugin>
            <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>
</plugins>
  </build>
</project>

Create a folder named java in the src/main directory of your project. By default this archetype does not create one.

Regenerate the eclipse or idea project (ex. mvn eclipse:clean eclipse:eclipse) and refresh the project in your IDE.

Step 2: Configuration

Replace the web.xml file in the src/main/webapp/WEB-INF folder with this:

<?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.jsp</welcome-file>
	</welcome-file-list>
</web-app>

faces-config.xml

Create a faces-config.xml file in the src/main/webapp/WEB-INF folder.

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

	<converter>
	    <converter-for-class>com.test.Genre</converter-for-class>
	    <converter-class>com.test.GenreConverter</converter-class>
	</converter>

	<managed-bean>
		<managed-bean-name>genreBean</managed-bean-name>
		<managed-bean-class>com.test.GenreBean</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
	</managed-bean>

</faces-config>

Implementation

The following is the Genre Entity Class.

src/main/java/com/test/Genre.java

package com.test;

import java.io.Serializable;

public class Genre implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;

	public Genre() {
		super();
	}

	public Genre(Integer id, String name) {
		this.id = id;
		this.name = name;
	}

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Genre [id=" + id + ", name=" + name + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Genre other = (Genre) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id)) {
			return false;
		}
		return true;
	}
}

The following is the Genre Managed Bean.

src/main/java/com/test/GenreBean.java

package com.test;

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

import javax.faces.model.SelectItem;

public class GenreBean {
    private Genre[] selectedDataList;

	public Genre[] getSelectedDataList() {
		return selectedDataList;
	}

	public void setSelectedDataList(Genre[] selectedDataList) {
		this.selectedDataList = selectedDataList;
	}

    public List<SelectItem> getSelectItemsStatic() {
        List<SelectItem> selectItems = new ArrayList<SelectItem>();
        for (Genre genre : GenreBean.getAllGenreStatic()) {
            selectItems.add(new SelectItem(genre, genre.getName()));
        }
        return selectItems;
    }

    public static Genre getById(Integer id) {
    	List<Genre> list = getAllGenreStatic();
    	int index = list.indexOf(new Genre(id, "doesnt matter based on equals()"));
    	Genre genre = null;
    	if(index != -1) {
    		genre = list.get(index);
    	}
    	return genre;
    }

    private static List<Genre> getAllGenreStatic() {
    	List<Genre> list = new ArrayList<Genre>();
    	list.add(new Genre(1, "Action"));
    	list.add(new Genre(2, "Drama"));
    	list.add(new Genre(3, "Documentary"));
		return list;
	}

    public String countSelected() {
    	System.out.println("selected: " + selectedDataList.length);
    	selectedDataList = null;
    	return "delete";
    }
}

The following is the Converter

The converter helps to translate between the string representation of the object and the object itself. Typical objects like String dont need converters. Any object that is an entity that you want displayed in Any JSF component needs a converter. Below you see an object that converts the Genre bean from a string representation to an actual Genre bean. In reality you would replace the source of the data to be a object cache or database datamanager. But for now we are using hard coded data in the GenreBean.

src/main/java/com/test/GenreConverter.java

package com.test;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class GenreConverter implements Converter {

	/**
	 * This method is responsible for re-constructing the object from the text
	 * representation of the object from the HTML form element. Typically this
	 * method would use a datamanager that will "lookup" the information.
	 */
	@Override
	public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
			throws ConverterException {
		Genre genre = new Genre();
		if("".equals(arg2)) {
			return genre;
		}
		// typically would go to the database to get the object.
		Integer id = Integer.parseInt(arg2);
		// call a static method for now. But this really should be coming
		// from a datamanager.
		genre = GenreBean.getById(id);
		return genre;
	}

	@Override
	public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
			throws ConverterException {		
		if(arg2 instanceof Genre) {
			Genre genre = (Genre)arg2;
			return ""+ genre.getId();
		}
		return "";
	}
}

The following is the JSP

/src/main/webapp/index.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"%>

<f:view>
	<html>
	<head>
	<title>Hello World JSF Example</title>
	</head>
	<body>
	<h:form id="myform">
	<h3>Select Movie Genre</h3>
		<h:selectManyListbox id="genre_select"
			value="#{genreBean.selectedDataList}" size="5">
			<f:selectItems value="#{genreBean.selectItemsStatic}" />
		</h:selectManyListbox>
		<br />
		<h:commandButton action="#{genreBean.countSelected}" />
	</h:form>
	</body>
	</html>
</f:view>

test the application

mvn jetty:run
http://localhost:8080/testSwitchList/index.jsf

Convert to a Switch List

The final step is to convert the listbox to a switchlist. We are going to use the advanced features provided by the tomahawk jsf plugin to generate ourselves the switchlist as well as the javascript that supports it.

The old school method of doing this is described here. As you can see this process was tedious because the javascript had to be manually customized and some additional frameworks like JQuery needed to be used in order to make things easier.

On this page we will describe the easier way of getting this done with JSF.

Go ahead and add the following to the web.xml file.

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

Include the following up top in the jsp file.

<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>

Simply changing the h:selectManyListbox to the t:selectManyPicklist enables the switchlist functionality on the page.

		<t:selectManyPicklist id="genre_select"
			value="#{genreBean.selectedDataList}" size="5">
			<f:selectItems value="#{genreBean.selectItemsStatic}" />
		</t:selectManyPicklist>

The selectManyPicklist imports all the necessary javascript on the page in addition to the command buttons that let you move items from left to right.

test the application

mvn jetty:run
http://localhost:8080/testSwitchList/index.jsf
By viewing the source for the page you notice that most of the coding is already done for you. JSF makes all this easy.

Thats all for now!

Advertisements

2 Responses to “Listbox Picker Using JSF and Tomahawk”


  1. 1 seema
    October 4, 2011 at 9:25 pm

    Hi Tried using the above code. But i get a Nul pointer exception and the tag is not rendered


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 78 other followers

December 2009
S M T W T F S
« Nov   Jan »
 12345
6789101112
13141516171819
20212223242526
2728293031  

Blog Stats

  • 822,357 hits

%d bloggers like this: