RichFaces-Fast-JSF
From Resin 3.0
Contents |
Running RichFaces and Ajax4JSF applications in fast-jsf mode
Fast JSF
Resin allows running your JSF applications in fast jsf mode. Fast JSF mode is applied to JSP code generator making it bypass JSP tags and use the component classes directly to construct component tree defined in the JSP file. To enable fast JSF mode for a particular library Resin needs to know which components the tags bind to. E.g. in a standard JSF library a h:message component would bind to javax.faces.component.html.HtmlMessage and Resin knows it from the following binding included in Resin's distribution.
<jsf-taglib xmlns="http://caucho.com/ns/resin">
<uri>http://java.sun.com/jsf/html</uri>
...
<jsf-tag>
<name>messages</name>
<component-class>javax.faces.component.html.HtmlMessages</component-class>
</jsf-tag>
...
</jsf-tablib>
For RichFaces two bindings are needed: one for the base Ajax4JSF library and another for RichFaces UI. The bindings are loaded by web application class loader from resources that match META-INF/*.ftld naming pattern, thus they can be placed in my-app/WEB-INF/classes/META-INF or packaged into a jar and placed in my-app/WEB-INF/lib
Ajax4JSF
META-INF/ajax4jsf-3.1.5.ftld
<?xml version='1.0'?>
<jsf-taglib xmlns='http://caucho.com/ns/resin'>
<uri>http://richfaces.org/a4j</uri>
<jsf-tag>
<name>actionparam</name>
<component-class>org.ajax4jsf.component.html.HtmlActionParameter</component-class>
</jsf-tag>
<jsf-tag>
<name>commandButton</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxCommandButton</component-class>
</jsf-tag>
<jsf-tag>
<name>commandLink</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxCommandLink</component-class>
</jsf-tag>
<jsf-tag>
<name>form</name>
<component-class>org.ajax4jsf.component.html.AjaxForm</component-class>
</jsf-tag>
<jsf-tag>
<name>include</name>
<component-class>org.ajax4jsf.component.html.Include</component-class>
</jsf-tag>
<jsf-tag>
<name>jsFunction</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxFunction</component-class>
</jsf-tag>
<jsf-tag>
<name>loadBundle</name>
<component-class>org.ajax4jsf.component.html.AjaxLoadBundle</component-class>
</jsf-tag>
<jsf-tag>
<name>loadScript</name>
<component-class>org.ajax4jsf.component.html.HtmlLoadScript</component-class>
</jsf-tag>
<jsf-tag>
<name>loadStyle</name>
<component-class>org.ajax4jsf.component.html.HtmlLoadStyle</component-class>
</jsf-tag>
<jsf-tag>
<name>log</name>
<component-class>org.ajax4jsf.component.html.AjaxLog</component-class>
</jsf-tag>
<jsf-tag>
<name>mediaOutput</name>
<component-class>org.ajax4jsf.component.html.MediaOutput</component-class>
</jsf-tag>
<jsf-tag>
<name>outputPanel</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxOutputPanel</component-class>
</jsf-tag>
<jsf-tag>
<name>page</name>
<component-class>org.ajax4jsf.component.html.HtmlPage</component-class>
</jsf-tag>
<jsf-tag>
<name>poll</name>
<component-class>org.ajax4jsf.component.html.AjaxPoll</component-class>
</jsf-tag>
<jsf-tag>
<name>portlet</name>
<component-class>org.ajax4jsf.component.html.HtmlPortlet</component-class>
</jsf-tag>
<jsf-tag>
<name>push</name>
<component-class>org.ajax4jsf.component.html.AjaxPush</component-class>
</jsf-tag>
<jsf-tag>
<name>region</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxRegion</component-class>
</jsf-tag>
<jsf-tag>
<name>repeat</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxRepeat</component-class>
</jsf-tag>
<jsf-tag>
<name>status</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxStatus</component-class>
</jsf-tag>
<jsf-tag>
<name>support</name>
<component-class>org.ajax4jsf.component.html.HtmlAjaxSupport</component-class>
</jsf-tag>
</jsf-taglib>
RichFaces
META-INF/richfaces-3.1.5.ftld
<?xml version='1.0'?>
<jsf-taglib xmlns='http://caucho.com/ns/resin'>
<uri>http://richfaces.org/rich</uri>
<jsf-tag>
<name>calendar</name>
<component-class>org.richfaces.component.html.HtmlCalendar</component-class>
</jsf-tag>
<jsf-tag>
<name>column</name>
<component-class>org.richfaces.component.html.HtmlColumn</component-class>
</jsf-tag>
<jsf-tag>
<name>columnGroup</name>
<component-class>org.richfaces.component.html.HtmlColumnGroup</component-class>
</jsf-tag>
<jsf-tag>
<name>componentControl</name>
<component-class>org.richfaces.component.html.HtmlComponentControl</component-class>
</jsf-tag>
<jsf-tag>
<name>contextMenu</name>
<component-class>org.richfaces.component.html.HtmlContextMenu</component-class>
</jsf-tag>
<jsf-tag>
<name>dataDefinitionList</name>
<component-class>org.richfaces.component.html.HtmlDataDefinitionList</component-class>
</jsf-tag>
<jsf-tag>
<name>dataFilterSlider</name>
<component-class>org.richfaces.component.html.HtmlDataFilterSlider</component-class>
</jsf-tag>
<jsf-tag>
<name>dataGrid</name>
<component-class>org.richfaces.component.html.HtmlDataGrid</component-class>
</jsf-tag>
<jsf-tag>
<name>dataList</name>
<component-class>org.richfaces.component.html.HtmlDataList</component-class>
</jsf-tag>
<jsf-tag>
<name>dataOrderedList</name>
<component-class>org.richfaces.component.html.HtmlDataOrderedList</component-class>
</jsf-tag>
<jsf-tag>
<name>dataTable</name>
<component-class>org.richfaces.component.html.HtmlDataTable</component-class>
</jsf-tag>
<jsf-tag>
<name>datascroller</name>
<component-class>org.richfaces.component.html.HtmlDatascroller</component-class>
</jsf-tag>
<jsf-tag>
<name>dndParam</name>
<component-class>org.richfaces.component.html.HtmlDndParam</component-class>
</jsf-tag>
<jsf-tag>
<name>dragIndicator</name>
<component-class>org.richfaces.component.html.HtmlDragIndicator</component-class>
</jsf-tag>
<jsf-tag>
<name>dragSupport</name>
<component-class>org.richfaces.component.html.HtmlDragSupport</component-class>
</jsf-tag>
<jsf-tag>
<name>dropDownMenu</name>
<component-class>org.richfaces.component.html.HtmlDropDownMenu</component-class>
</jsf-tag>
<jsf-tag>
<name>dropSupport</name>
<component-class>org.richfaces.component.html.HtmlDropSupport</component-class>
</jsf-tag>
<jsf-tag>
<name>effect</name>
<component-class>org.richfaces.component.html.HtmlEffect</component-class>
</jsf-tag>
<jsf-tag>
<name>gmap</name>
<component-class>org.richfaces.component.html.HtmlGmap</component-class>
</jsf-tag>
<jsf-tag>
<name>inputNumberSlider</name>
<component-class>org.richfaces.component.html.HtmlInputNumberSlider</component-class>
</jsf-tag>
<jsf-tag>
<name>inputNumberSpinner</name>
<component-class>org.richfaces.component.html.HtmlInputNumberSpinner</component-class>
</jsf-tag>
<jsf-tag>
<name>insert</name>
<component-class>org.richfaces.ui.component.html.HtmlInsert</component-class>
</jsf-tag>
<jsf-tag>
<name>jQuery</name>
<component-class>org.richfaces.component.html.HtmlJQuery</component-class>
</jsf-tag>
<jsf-tag>
<name>listShuttle</name>
<component-class>org.richfaces.component.html.HtmlListShuttle</component-class>
</jsf-tag>
<jsf-tag>
<name>menuGroup</name>
<component-class>org.richfaces.component.html.HtmlMenuGroup</component-class>
</jsf-tag>
<jsf-tag>
<name>menuItem</name>
<component-class>org.richfaces.component.html.HtmlMenuItem</component-class>
</jsf-tag>
<jsf-tag>
<name>menuSeparator</name>
<component-class>org.richfaces.component.html.HtmlMenuSeparator</component-class>
</jsf-tag>
<jsf-tag>
<name>message</name>
<component-class>org.richfaces.component.html.HtmlRichMessage</component-class>
</jsf-tag>
<jsf-tag>
<name>messages</name>
<component-class>org.richfaces.component.html.HtmlRichMessages</component-class>
</jsf-tag>
<jsf-tag>
<name>modalPanel</name>
<component-class>org.richfaces.component.html.HtmlModalPanel</component-class>
</jsf-tag>
<jsf-tag>
<name>orderingList</name>
<component-class>org.richfaces.component.html.HtmlOrderingList</component-class>
</jsf-tag>
<jsf-tag>
<name>paint2D</name>
<component-class>org.richfaces.component.html.HtmlPaint2D</component-class>
</jsf-tag>
<jsf-tag>
<name>panel</name>
<component-class>org.richfaces.component.html.HtmlPanel</component-class>
</jsf-tag>
<jsf-tag>
<name>panelBar</name>
<component-class>org.richfaces.component.html.HtmlPanelBar</component-class>
</jsf-tag>
<jsf-tag>
<name>panelBarItem</name>
<component-class>org.richfaces.component.html.HtmlPanelBarItem</component-class>
</jsf-tag>
<jsf-tag>
<name>panelMenu</name>
<component-class>org.richfaces.component.html.HtmlPanelMenu</component-class>
</jsf-tag>
<jsf-tag>
<name>panelMenuGroup</name>
<component-class>org.richfaces.component.html.HtmlPanelMenuGroup</component-class>
</jsf-tag>
<jsf-tag>
<name>panelMenuItem</name>
<component-class>org.richfaces.component.html.HtmlPanelMenuItem</component-class>
</jsf-tag>
<jsf-tag>
<name>recursiveTreeNodesAdaptor</name>
<component-class>org.richfaces.component.html.HtmlRecursiveTreeNodesAdaptor</component-class>
</jsf-tag>
<jsf-tag>
<name>scrollableDataTable</name>
<component-class>org.richfaces.component.html.HtmlScrollableDataTable</component-class>
</jsf-tag>
<jsf-tag>
<name>separator</name>
<component-class>org.richfaces.component.html.HtmlSeparator</component-class>
</jsf-tag>
<jsf-tag>
<name>simpleTogglePanel</name>
<component-class>org.richfaces.component.html.HtmlSimpleTogglePanel</component-class>
</jsf-tag>
<jsf-tag>
<name>spacer</name>
<component-class>org.richfaces.component.html.HtmlSpacer</component-class>
</jsf-tag>
<jsf-tag>
<name>subTable</name>
<component-class>org.richfaces.component.html.HtmlSubTable</component-class>
</jsf-tag>
<jsf-tag>
<name>suggestionbox</name>
<component-class>org.richfaces.component.html.HtmlSuggestionBox</component-class>
</jsf-tag>
<jsf-tag>
<name>tab</name>
<component-class>org.richfaces.component.html.HtmlTab</component-class>
</jsf-tag>
<jsf-tag>
<name>tabPanel</name>
<component-class>org.richfaces.component.html.HtmlTabPanel</component-class>
</jsf-tag>
<jsf-tag>
<name>toggleControl</name>
<component-class>org.richfaces.component.html.HtmlToggleControl</component-class>
</jsf-tag>
<jsf-tag>
<name>togglePanel</name>
<component-class>org.richfaces.component.html.HtmlTogglePanel</component-class>
</jsf-tag>
<jsf-tag>
<name>toolBar</name>
<component-class>org.richfaces.component.html.HtmlToolBar</component-class>
</jsf-tag>
<jsf-tag>
<name>toolBarGroup</name>
<component-class>org.richfaces.component.html.HtmlToolBarGroup</component-class>
</jsf-tag>
<jsf-tag>
<name>toolTip</name>
<component-class>org.richfaces.component.html.HtmlToolTip</component-class>
</jsf-tag>
<jsf-tag>
<name>tree</name>
<component-class>org.richfaces.component.html.HtmlTree</component-class>
</jsf-tag>
<jsf-tag>
<name>treeNode</name>
<component-class>org.richfaces.component.html.HtmlTreeNode</component-class>
</jsf-tag>
<jsf-tag>
<name>treeNodesAdaptor</name>
<component-class>org.richfaces.component.html.HtmlTreeNodesAdaptor</component-class>
</jsf-tag>
<jsf-tag>
<name>virtualEarth</name>
<component-class>org.richfaces.component.html.HtmlVirtualEarth</component-class>
</jsf-tag>
</jsf-taglib>
Switching the Fast JSF mode on and off
Fast JSF mode can be turned on globally or for particular context by setting fast-jsf flag to true in $RESIN-HOME/conf/resin.xml or my-app/WEB-INF/resin-web.xml. In Resin 3.2 fast-jsf mode is turned on by default.
Example of $my-app/WEB-INF/resin-web.xml that turns fast JSF mode on
<web-app xmlns='http://caucho.com/ns/resin'>
<jsf fast-jsf='true'/>
</web-app>
Sample code for generating .ftld files
The code below was used to generate the .ftld files for RichFaces and given for reference. It will use faces-config.xml and ajax4jsf.taglib.xml with rich.taglib.xml to generate both files.
import com.caucho.vfs.Path;
import com.caucho.vfs.Vfs;
import com.caucho.xml.DOMBuilder;
import com.caucho.xml.QDocument;
import com.caucho.xml.Xml;
import com.caucho.xpath.XPath;
import com.caucho.xpath.XPathException;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class RichFacesFastJsfGen {
public static void main(String[] args)
throws IOException, XPathException, SAXException
{
Path path = Vfs.lookup(
"/Users/alex/Documents/jars/richfaces-ui-3.1.5.GA/ui/assembly/target/classes/META-INF/faces-config.xml");
QDocument facesConfig = parse(path);
Iterator it = XPath.select("/faces-config/component", facesConfig);
Map<String, String> typeToClass = new HashMap<String, String>();
while (it.hasNext()) {
Element e = (Element) it.next();
String componentType = XPath.evalString("component-type/text()", e)
.trim();
String componentClass = XPath.evalString("component-class/text()", e)
.trim();
typeToClass.put(componentType, componentClass);
}
path = Vfs.lookup(
"/Users/alex/Documents/jars/richfaces-ui-3.1.5.GA/ui/assembly/target/classes/META-INF/ajax4jsf.taglib.xml");
QDocument taglib = parse(path);
it = XPath.select("/facelet-taglib/tag", taglib);
StringBuilder builder = new StringBuilder("<?xml version='1.0'?>\n");
builder.append("<jsf-taglib xmlns='http://caucho.com/ns/resin'>\n");
builder.append("\t<uri>http://richfaces.org/a4j</uri>\n");
while (it.hasNext()) {
Element e = (Element) it.next();
String tagName = XPath.evalString("tag-name", e).trim();
String componentType = XPath.evalString("component/component-type/text()",
e).trim();
String componentClass = typeToClass.get(componentType);
if (componentClass != null && !"".equals(componentClass)) {
builder.append("\t<jsf-tag>\n");
builder.append("\t\t<name>");
builder.append(tagName);
builder.append("</name>\n");
builder.append("\t\t<component-class>");
builder.append(componentClass);
builder.append("</component-class>\n");
builder.append("\t</jsf-tag>\n");
}
}
builder.append("</jsf-taglib>");
System.out.println(builder);
path = Vfs.lookup(
"/Users/alex/Documents/jars/richfaces-ui-3.1.5.GA/ui/assembly/target/classes/META-INF/rich.taglib.xml");
taglib = parse(path);
it = XPath.select("/facelet-taglib/tag", taglib);
builder = new StringBuilder("<?xml version='1.0'?>\n");
builder.append("<jsf-taglib xmlns='http://caucho.com/ns/resin'>\n");
builder.append("\t<uri>http://richfaces.org/rich</uri>\n");
while (it.hasNext()) {
Element e = (Element) it.next();
String tagName = XPath.evalString("tag-name", e).trim();
String componentType = XPath.evalString("component/component-type/text()",
e).trim();
String componentClass = typeToClass.get(componentType);
if (componentClass != null && !"".equals(componentClass)) {
builder.append("\t<jsf-tag>\n");
builder.append("\t\t<name>");
builder.append(tagName);
builder.append("</name>\n");
builder.append("\t\t<component-class>");
builder.append(componentClass);
builder.append("</component-class>\n");
builder.append("\t</jsf-tag>\n");
}
}
builder.append("</jsf-taglib>");
System.out.println(builder);
}
public static QDocument parse(Path file)
throws IOException, SAXException, XPathException
{
QDocument doc = new QDocument();
DOMBuilder builder = new DOMBuilder();
builder.init(doc);
Xml xml = new Xml();
xml.setOwner(doc);
xml.setNamespaceAware(false);
xml.setContentHandler(builder);
xml.parse(file);
return doc;
}
}
Running RichFaces Calendar Sample
Below is an outline of steps needed in order to run RichFaces Calendar Sample
- Deploy the Calendar Sample application into $RESIN-HOME/webapps/calendar-sample
- Change to the calendar-sample's WEB-INF/lib directory and delete the following files: calendar-3.1.*.jar, jsf-api-1.2_*.jar, jsf-impl-1.2_*.jar, jstl-1.*.jar, xercesImpl-2.*.jar
- Locate richfaces-ui-3.1.*.GA.jar in RichFaces's distribution and copy it into the WEB-INF/lib directory
- Open for editing pages/Calendar.jsp page of the web application and change taglib uri="http://labs.jboss.com/jbossrichfaces/ui/calendar" to taglib uri="http://richfaces.org/rich"
- Create WEB-INF/resin-web.xml file with the following content
<web-app xmlns='http://caucho.com/ns/resin'> <jsf fast-jsf='true'/> </web-app>
- Create ajax4jsf-3.1.5.ftld and richfaces-3.1.5.ftld files in WEB-INF/classes/META-INF by copying content from above
- Start Resin
- Navigate to http://localhost:8080/calendar-sample/pages/Calendar.jsf
- For deeper understanding of what goes on under the hood:
- explore WEB-INF/work/_jsp/pages/_Calendar__jsp.java
- delete the WEB-INF/work directory
- set fast-jsf to false
- navigate to http://localhost:8080/calendar-sample/pages/Calendar.jsf
- explore WEB-INF/work/_jsp/pages/_Calendar__jsp.java again