Two Ways for Partial Facelets Adoption


This article explains two ways to use JSP-based JSF and Facelets-based JSF in the same project, one of which is well known while the other is less known and is worth writing about.

Motivation and Prefix Mapping Technique

Say, you have hundreds of JSP-based JSF files and you want to switch to Facelets. Some people say it is fairly easy to manually conver them and it would take a day or two, but you don't want to risk. So you need to use JSP and Facelets in the same JSF project. A well known way to do this is to use prefix mapping technique as described here. With this technique, *.xhtml files will use Facelets while *.jsp files will use JSP. A drawback is that you must use prefix mapping, thus URLs will have to change. It is a pain in some cases, when your pages have many incoming links, for example.

Suffix Mapping Technique

Fortunately, there is another way that use suffix mapping. With this technique, URLs don't have to change for your old JSP-based JSF. This could be done with some sacrifice: Facelets-based JSF files must have jsp extention instead of xhtml. To distinguish JSP and Facelets, name Facelets files *_.jsp for example. Then all *_.jsp files will use Facelets while the other *.jsp files will use JSP. In some cases, this is an easier way to adopt Facelets partially. To use this technique, you just configure your web.xml as below:
    <!-- Default suffix for jsf files -->

    Only jsf files with _.jsp suffix are processed with Facelets.
    Other .jsp files are processed as JSP-based JSF.

        <servlet-name>Faces Servlet</servlet-name>

    <!-- Url with .jsf suffix are passed to facesServlet -->
URL with .jsf extention are handled by FacesServlet. A suffix ".jsp" is used to determine the JSF view file, as specified by javax.faces.DEFAULT_SUFFIX param. If the view file ends with "_.jsp" then Facelets processes the view file, otherwise the view processing is deligated to the default JSP engine.

posted by apptaro at 17:30 | Comment(0) | TrackBack(0) | JSF


How to avoid borders when using UnsharpMask operation with JAI


When using unsharp mask with JAI (Java Advanced Imaging), a resulting image may have borders. This article explains how to avoid it.

How to use unsharp mask with JAI

The following is the sample code. The key is to use RenderingHints to specify a BorderExtender. Without this, borders may appear.
public class UnsharpTest {
    public static void main(String[] args) throws IOException {
        // load image
        RenderedOp image = JAI.create("stream", new FileSeekableStream(new File("test.jpg")));

        // unsharp image
        ParameterBlock unsharp_params = new ParameterBlock();
        unsharp_params.add(null); // convolution kernel
        unsharp_params.add(1.0F); // gain factor

        RenderingHints unsharp_hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
        image = JAI.create("UnsharpMask", unsharp_params, unsharp_hints);
        // save image
        JPEGEncodeParam encParam = new JPEGEncodeParam();
        ParameterBlock filestore_params = new ParameterBlock();
        filestore_params.add("image_unsharpened.jpg"); // path of the file to write to
        filestore_params.add("JPEG"); // format of the file
        filestore_params.add(encParam); // encoding parameters
        JAI.create("filestore", filestore_params);
posted by apptaro at 21:07 | Comment(0) | TrackBack(0) | Java/Servlet


Corrupted Characters in JSF due to Expired Session


When a session is expired, JSF may parse form data using incorrect character encoding. This leads to corrupted characters on a page, or in a worst case, corrupted data in a database.

How form data can be corrupted

As I wrote in the previous article on some tips for JSF character encoding, JSF mostly depends on javax.faces.request.charset session attribute to determine a correct character encoding to decode form data. JSF 1.1 and 1.2 are designed this way so that you can use existing mechanism such as JSP page directive or servlet filter to change character encoding. I think people usually just set charset in JSP page directive. Then, JSF seems to take care of the rest.

My application uses client side state saving, and view-scoped beans (using t:saveState for request-scoped managed beans.) This is the best way because this way I can let users use multiple browser windows to access the same JSF form at once. If you use session-scoped beans, beans are shared between accesses from different browser windows, and it messes things up. I thought my application does not depend on sessions in any way, so I set short session-timeout. But there was a pitfall!

Users sometimes leave JSF page open, and later come back and do updates on the page. The session has been expired by that time, and JSF falls back to use ISO-8859-1 in decoding form data, when it should be using, for example, Windows-31J for Japanese characters. Corrupted data are then stored in a backing bean, leading to corrupted characters on the response page, or corrupted data can even be saved on a database.

So what to do?

So what to do to avoid this problem? You could ...
  • Set long session-timeout

    I don't like this idea because I wanted to set it short for the first place for some reasons.

  • Set up a servlet filter to set request encoding

    I feel it waste because then JSF spec would look meaningless, and if you changed charset in JSP page directive, you would also have to modify the filter. If they don't match, it will messes things up. A servlet filter sets a request character encoding first, then JSF sets a request character encoding when found in a session, then actual encoding used to decode the form data may be the former or the latter. (Note: The servlet will use the last request character encoding set to parse form data, on an initial call to request.getParameter.)

  • Add a logic to disallow form data if a session is null or new

    This would make it worse in terms of application usability. What would the error message say? "You were away too long, so I forgot the character encoding?"

I wonder if there are other ways to solve this issue. For now, I would go with the second option.
posted by apptaro at 13:52 | Comment(0) | TrackBack(0) | JSF


Tips for JSF character encoding


This article explains some tips for JSF character encoding.

How request character encoding is determined by JSF.

As described in section of JSF specification 1.1 and 1.2, request character encoding is determined in the following order:
  • Charset of Content-Type is used, if exists.
  • Charset of a previous response is used, if stored in a session.
  • Otherwise, request character encoding is unmodified.

Determining correct encoding is crutial because it is used to decode POST parameters.

Obtaining charset from Content-Type is considered the best way, but this usually does not happen because most browsers currently do not send it.

JSF stores previous response character encoding in a session ("javax.faces.request.charset" in case of MyFaces.) Most browsers send requests using the same character encoding as the HTML, so following requests to JSF can assumingly use previous response character encoding as request character encoding.

On an initial request of a session to JSF, whatever request character encoding set by servlet/container is used unmodified. Thus it can fall back to ISO-8859-1 as specified by Servlet Specification 2.4 and 2.5. A common way to specify request character encoding is to build a small servlet filter which call request.setCharacterEncoding.


Here's the tips:
  • Always use servlet filter to set request character encoding. Otherwise, an initial request to JSF will fail to decode parameters correctly.

    If you have a JSF page which uses incoming POST parameters, and a calling page is a simple html page with a form, chances are JSF will fail to process the parameter correctly for the first request, but will succeed for the following requests.

  • Always use only one encoding throughout the application. Otherwise, JSF may fail to decode parameters correctly.

    Note that response encoding is stored by session, not by session and page. If some JSF pages renders response by encoding A, while others renders response by encoding B, accessing the former pages after accessing the latter pages will result in decode failure. This may also happen if response encoding is changed dynamically based on user's preferences, and multiple windows are open while changing the preferences.


  • Even if you set a character encoding in a servlet filter, JSF will override it with the encoding found in Content-Type or the previous response encoding stored in a session. The servlet will use the last request character encoding set to parse form data, on an initial call to request.getParameter. (Modifying q request character encoding after a call to request.getParameter is ignored.) (Added: 2008/10/10)
posted by apptaro at 17:06 | Comment(2) | TrackBack(0) | JSF


MyFaces Tomahawk: Tree2 Component Improvement


MyFaces Tomahawk's Tree2 is a great JSF component to display hierarchic data, such as directory structure or sitemap. When used with dynamic data, however, its default implementation has some issues with tree state as described in TOMAHAWK-244 and TOMAHAWK-296. In this article, I will solve the issues by providing custom implementations of TreeModel and TreeWalker interfaces.


This article focuses on usage of tree2 component with the following attributes:
  • clientSideToggle="true"
  • preserveToggle="true"
Tested with MyFaces Core 1.1.3 and MyFaces Tomahawk 1.1.3. For server side toggle, no test has been done.

Problem Description

Tree2 component stores tree state (if each node is expanded or collapsed) in index-based node naming schema such that:
  • root node is named "0"
  • first child is named "0:0"
  • second child is named "0:1"
  • third child of second child is named "0:1:2"
This simple schema does not work as expected when tree data is dynamic. For example, in the diagram below, a root node has two nodes A and B, and node B is expanded. This tree state is described as "node 0:1 is expanded."
  • ROOT
  • + A
  • - B
  • + B1
  • + B2
Let's look at the situation when node C is inserted as a first child of ROOT. Then what you would expect is:
  • ROOT
  • + C
  • + A
  • - B
  • + B1
  • + B2
However, this is what really happens. Because tree state is stored as "node 0:1 is expaned," in this case what is expanded is node A:
  • ROOT
  • + C
  • - A
  • + A1
  • + A2
  • + B
Because tree state is index-based, when data is inserted/deleted/moved/sorted, tree state becomes unfavorable.

Solution Description

Good news is, Tree2 component has a mechanism to solve this problem by supplying custom naming schema implementation. Bad news is, there is no working example or good documentation on the Internet (as far as I know.) So, I have done some investigation and created one!
Idea is to use naming schema based on node identifier, as suggested in TOMAHAWK-244. In the above example, "node 0:1 is expanded" is instead described as "node ROOT:B is expanded" or "node 0:200 is expanded" if ROOT's identifier is 0 and B's identifier is 200 (I think this is typical case where record ids are integers generated by database sequence.)


The following two files are the implementation of the solution.
  • CustomTreeModel.java
  • CustomTreeWalker.java
Naming schema can be customized by implementating TreeWalker interface, but besides that, a custom implementation of TreeModel is needed.
The code uses Java5 generics syntax, but you can remove them if you are using Java1.4.
package example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.myfaces.custom.tree2.TreeModel;
import org.apache.myfaces.custom.tree2.TreeNode;
import org.apache.myfaces.custom.tree2.TreeState;
import org.apache.myfaces.custom.tree2.TreeStateBase;
import org.apache.myfaces.custom.tree2.TreeWalker;

public class CustomTreeModel implements TreeModel {

    private TreeNode rootTreeNode;
    private TreeState treeState;

    public CustomTreeModel(TreeNode rootTreeNode) {
        this.rootTreeNode = rootTreeNode;
        this.treeState = new TreeStateBase();


    public String[] getPathInformation(String nodeId) {
        if (nodeId == null) {
            throw new IllegalArgumentException("Cannot determine path for a null node.");

        ArrayList pathList = new ArrayList();
        while (nodeId.lastIndexOf(SEPARATOR) != -1) {
            nodeId = nodeId.substring(0, nodeId.lastIndexOf(SEPARATOR));


        return pathList.toArray(new String[0]);

    public boolean isLastChild(String nodeId) {
        if (nodeId.lastIndexOf(SEPARATOR) == -1) { // return true for root node
            return true;

        String parentNodeId = nodeId.substring(0, nodeId.lastIndexOf(SEPARATOR));
        String childIdentifier = nodeId.substring(nodeId.lastIndexOf(SEPARATOR) + 1);

        TreeNode parentNode = getNodeById(parentNodeId);
        TreeNode lastChildNode = (TreeNode)parentNode.getChildren().get(parentNode.getChildCount() - 1);

        return lastChildNode.getIdentifier().equals(childIdentifier);

    public TreeNode getNodeById(String nodeId) {
        if (nodeId == null) return null;

        StringTokenizer st = new StringTokenizer(nodeId, SEPARATOR);

        // check first node identifier equals root node identifier
        if (!rootTreeNode.getIdentifier().equals(st.nextElement())) {
            throw new IllegalArgumentException("Cannot find a root node.");
        TreeNode node = rootTreeNode;
        while (st.hasMoreTokens()) {
            String nodeIdentifier = st.nextToken();
            boolean found = false;
            for (TreeNode childNode : (List)node.getChildren()) {
                if (childNode.getIdentifier().equals(nodeIdentifier)) {
                    node = childNode;
                    found = true;
            if (!found) {
                throw new IllegalArgumentException("Cannot find a node. (" + nodeId + ")");

        return node;

    public void setTreeState(TreeState treeState) {
        this.treeState = treeState;

    public TreeState getTreeState() {
        return treeState;

    public TreeWalker getTreeWalker() {
        return new CustomTreeWalker();

    public TreeNode getRootTreeNode() {
        return rootTreeNode;

To use a custom TreeWalker implementation, getTreeWalker() method of TreeModel must be implemented to return it. I first tried just to override getTreeWalker() method of TreeModelBase (the default implementation of TreeModel,) but I found it not possible because part of the code depends of index-based naming schema. So I created a new CustomTreeModel class. getRootTreeNode() is added so that CustomTreeWalker can get access to TreeNode's.
package example;

import java.util.List;
import java.util.Stack;

import org.apache.commons.lang.StringUtils;
import org.apache.myfaces.custom.tree2.TreeModel;
import org.apache.myfaces.custom.tree2.TreeNode;
import org.apache.myfaces.custom.tree2.TreeWalker;
import org.apache.myfaces.custom.tree2.UITreeData;

public class CustomTreeWalker implements TreeWalker {

    private static final String SEPARATOR = TreeModel.SEPARATOR;

    private UITreeData treeData;
    private Stack idStack = new Stack();
    private Stack nodeStack = new Stack();
    private boolean checkState = true;
    private boolean startedWalking = false;


    public boolean isCheckState() {
        return checkState;

    public void setCheckState(boolean checkState) {
        this.checkState = checkState;

    public boolean next() {
        if (!startedWalking) { // first step of walking : start from the root
            CustomTreeModel treeModel = (CustomTreeModel)treeData.getDataModel();
            TreeNode rootTreeNode = treeModel.getRootTreeNode();

            startedWalking = true;
            return true;

        if (nodeStack.isEmpty()) { // if stack is empty, end the walking
            return false;

        String prevNodeId = idStack.peek();
        TreeNode prevNode = nodeStack.peek();

        if (prevNode.isLeaf()) { // if previous stacked node is a leaf, go up the hierarchy
            return next();

        } else {

            String nextNodeId = null;
            TreeNode nextNode = null;

            if (prevNodeId.equals(treeData.getNodeId())) { // going down the hierarchy

                if (checkState) { // if checkState is true, check if the node is expanded and skip it if not.
                    if (!treeData.getDataModel().getTreeState().isNodeExpanded(prevNodeId)) {
                        return next();

                nextNode = (TreeNode)prevNode.getChildren().get(0);
                nextNodeId = prevNodeId + SEPARATOR + nextNode.getIdentifier();

            } else { // walk on the same level

                String currentNodeId = treeData.getNodeId();
                String currentNodeIdentifier = treeData.getNode().getIdentifier();
                String parentNodeId = StringUtils.substringBeforeLast(currentNodeId, SEPARATOR);
                TreeNode parentNode = treeData.getDataModel().getNodeById(parentNodeId);

                if (treeData.getDataModel().isLastChild(currentNodeId)) { // go up the hierarchy if last child
                    return next();

                boolean nextIsNext = false;
                for (TreeNode childNode : (List)parentNode.getChildren()) { // find next child
                    if (nextIsNext) {
                        nextNode = childNode;
                        nextNodeId = parentNodeId + SEPARATOR + nextNode.getIdentifier();
                    } else if (childNode.getIdentifier().equals(currentNodeIdentifier)) {
                        nextIsNext = true;



            return true;

    public String getRootNodeId() {
        return ((CustomTreeModel)treeData.getDataModel()).getRootTreeNode().getIdentifier();

    public void setTree(UITreeData treeData) {
        this.treeData = treeData;

    public void reset() {
        startedWalking = false;

CustomTreeWalker implementation uses naming schema based on node identifier, separated by colon(:) so it assumes that node identifier does not include any colon. next() method is the main method which walks through the tree nodes the same way as the default TreeWalkerBase does.


No download available, so just copy the code above.


Please use them for free!
posted by apptaro at 11:58 | Comment(3) | TrackBack(0) | JSF


Emulating Disabled Options in IE with DHTML Behaviors


Internet Explorer 6 does not implement disabled OPTION's in a SELECT. "Select, Option, Disabled And The JavaScript Solution" talks about a solution to emulate them using JavaScript. In this article, I will show a cleaner solution using DHTML Behaviors.


Advantages of my DHTML Behaviors solution over other JavaScript solutions are:
  • No mess with JavaScript
    You don't have to add JavaScript to every SELECT tag which may contain disabled options.
    If you already have some complicated JavaScript, just leave them as they are.
  • No mess with DOM operations
    If you already have some complicated DOM operations, just leave them as they are.
  • Only a small change in CSS
    To implement the solution, you only need to make a small change to existing CSS.
  • Works completely transparent
    The solution works as if disabled options are supported from the beginning.
    You can use this solution with JSF, with which it is difficult to change output HTML.

The Solution

To demonstrate the solution, look at the three files below:
  • sample.html
  • sample.css
  • sample.htc
The first two files are just to test the emulation. The last HTC file is the core of the solution. (Download is available at the bottom of this page.)
<link rel="stylesheet" type="text/css" href="sample.css">
<option>Option 1</option>
<option>Option 2</option>
<option disabled>Option 3</option>
Above is a simple HTML file with disabled options. Normally, disabled options are displayed as non-disabled options in IE6. Note that external stylesheet sample.css is loaded. If you like, you can internalize it.
select, option {
  behavior: url(sample.htc);
Above is a simple CSS file which will be loaded with the HTML file. DHTML Behaviors are attached to SELECT and OPTION. Actual behaviors are defined in sample.htc.
<?xml version="1.0" encoding="ISO-8859-1"?>
<PUBLIC:ATTACH EVENT="ondocumentready" ONEVENT="onDocumentReady()" />
<PUBLIC:ATTACH EVENT="ondetach" ONEVENT="onDetach()" />

<SCRIPT type="text/javascript">

var nLastSelectedIndex;
var fOnChangeOriginal;

// event handlers

function onDocumentReady() {
  var sTag = element.tagName.toLowerCase();
  if (sTag == "select") {
    attachEvent("onchange", onChangeSelect);
    attachEvent("onpropertychange", onPropertyChangeSelect);
    nLastSelectedIndex = element.selectedIndex;
  } else if (sTag == "option") {
    attachEvent("onpropertychange", onPropertyChangeOption);

function onDetach() {
  var sTag = element.tagName.toLowerCase();
  if (sTag == "select") {
    detachEvent("onchange", onChangeSelect);
    detachEvent("onpropertychange", onPropertyChangeSelect);
  } else if (sTag == "option") {
    detachEvent("onpropertychange", onPropertyChangeOption);


function onChangeSelect() {
  if (element.options[element.selectedIndex].disabled) {
    element.selectedIndex = nLastSelectedIndex;
  } else {
    nLastSelectedIndex = element.selectedIndex;
    if (fOnChangeOriginal != undefined) {

function onPropertyChangeSelect() {
  var sChangedPropertyName = event.propertyName.toLowerCase();
  if (sChangedPropertyName == "onchange") {
  } else if (sChangedPropertyName == "selectedindex") { // contributed by Zecc
    nLastSelectedIndex = element.selectedIndex;

function onPropertyChangeOption() {
  var sChangedPropertyName = event.propertyName.toLowerCase();
  if (sChangedPropertyName == "disabled") {

// hack onChange attribute of select tag

function hackOnChange() {
  detachEvent("onpropertychange", onPropertyChangeSelect);
  fOnChangeOriginal = element.onchange;
  element.onchange = null;
  attachEvent("onpropertychange", onPropertyChangeSelect);

// emulate disabled option

function emulateOption() {
  if (element.disabled) {
    element.style.color = "graytext";
  } else {
    element.style.color = "menutext";

Above is a core HTC file which defines the DHTML Behaviors for SELECT and OPTION. What it does are:
  • onDocumentReady, onDetach
    Initialization and cleaning up.
  • onChangeSelect
    When a selection is changed for a SELECT, check if the selected option is disabled. If it is disabled, revert the selection. If it is not disabled, save the selectedIndex for later use, and run the original onchange event handler set by user.
  • onPropertyChangeSelect
    When a onchange event handler is set or changed for a SELECT, save the event handler for later use and set the onchange to null. This ensures that onChangeSelect above is called, which then calls the onchange event handler set by the user. This mechanism is needed because, by the spec, a onchange event handler set in a HTML file is called before a onchange event handler in a HTC file. This makes it possible to work consistently when there is a onchange event handler in the HTML or there is JavaScript/DOM manipulations.
    Contributed by Zecc:
    When a selectedindex value is set or changed for a SELECT, save the value for later use. This makes it possible to work consistently when there is JavaScript/DOM manipulations.
  • onPropertyChangeOption
    When a disabled attribute is changed for a OPTION, change the text color of the OPTION, so it will look enabled or disabled. This makes it possible to work consistently when there is JavaScript/DOM manipulations.


You can download zipped files from here.
Download includes sample-javascript.html which is a little more complicated version of sample.html, to demonstrate how the solution works when there are some JavaScript/DOM manipulations.
Note that if you open HTML files from a local directory, IE will display a alert, but this will not happen when you open the files from a web server.


This solution is dedicated to the public domain.
posted by apptaro at 11:32 | Comment(39) | TrackBack(0) | HTML