JSF components with the Ajax4jsf cdk

The Ajax4jsf cdk (component development kit) from the Richfaces/Ajax4jsf development team makes the monotonous coding and complexities of developing JSF components for both JSP and Facelets almost non-existent. With a small amount of setup and a little framework knowledge (covered below), you can generate a complete JSF component that allows the developer to focus on what is most important to them.

Getting Started

Make sure you are using the latest version of Maven (I'm on 2.0.5)
If you don't have Maven...

  • Download here and install on your machine.
  • Add Maven bin folder to your PATH

Add the following to your <profile> section in [your maven directory]/conf/settings.xml

 
<profile> 
<id>ajax4jsf</id> 
<repositories> 
<repository> 
<releases> 
<enabled>true</enabled> 
</releases> 
<snapshots> 
<enabled>false</enabled> 
<updatePolicy>never</updatePolicy> 
</snapshots> 
<id>repository.jboss.com</id> 
<name>Jboss Repository for Maven</name> 
<url> 
http://repository.jboss.com/maven2/ 
</url> 
<layout>default</layout> 
</repository> 
<repository> 
<releases> 
<enabled>false</enabled> 
</releases> 
<snapshots> 
<enabled>true</enabled> 
<updatePolicy>always</updatePolicy> 
</snapshots> 
<id>maven2-snapshots.jboss.com</id> 
<name>Jboss Repository for Maven Snapshots</name> 
<url>http://snapshots.jboss.com/</url> 
<layout>default</layout> 
</repository> 
</repositories> 
<pluginRepositories> 
<pluginRepository> 
<id>maven2-snapshots.jboss.com</id> 
<name>Jboss Repository for Maven Snapshots</name> 
<url>http://snapshots.jboss.com/</url> 
<releases> 
<enabled>false</enabled> 
</releases> 
<snapshots> 
<enabled>true</enabled> 
<updatePolicy>always</updatePolicy> 
</snapshots> 
</pluginRepository> 
<pluginRepository> 
<releases> 
<enabled>true</enabled> 
</releases> 
<snapshots> 
<enabled>false</enabled> 
<updatePolicy>never</updatePolicy> 
</snapshots> 
<id>repository.jboss.com</id> 
<name>Jboss Repository for Maven</name> 
<url> 
http://repository.jboss.com/maven2/ 
</url> 
<layout>default</layout> 
</pluginRepository> 
</pluginRepositories> 
</profile> 

...Just after the closing </profile> add the following:

 
 
 <activeProfiles> 
 <activeProfile>ajax4jsf</activeProfile> 
 </activeProfiles> 
 

Project Setup and Installation

You will need to checkout the RichFaces project before you begin development.

RichFaces

  • Use Subversion and checkout the trunk from RichFaces(https://svn.jboss.org/repos/richfaces/trunk)
  • Run mvn install in the root richfaces project, also navigate to the richfaces/assembly directory and run mvn install again.

To start the initial component development, in [richfaces project root]/richfaces, run create.bat (or create.sh on *nix) "and the name of your component" - i.e. create.bat MyComponentName. This command creates an empty project and now you need to add at least one component to it.

First thing is to compile your project by navigating to its root directory and running mvn install. *Note - I had to remove 2 dependencies from the pom.xml file that were generated (This should be fixed soon)...

 
 
<dependency> 
 <groupId>javax.servlet</groupId> 
 <artifactId>jsp-api</artifactId> 
 <version>2.0</version> 
</dependency> 
<dependency> 
 <groupId>javax.faces</groupId> 
 <artifactId>jsf-api</artifactId> 
 <version>1.1_02</version> 
</dependency> 
 

Once you are able to install/compile your new project you are almost done with the setup. **This would be a great time to install the maven Idea or Eclipse plugin to generate your project files if you haven't already done so, trust me... this is one of the best things about Maven.

Now lets add a component to your new project:

  • Navigate to [richfaces project root]/richfaces/MyComponentName and run mvn cdk:create -U -cpu -Dname=<MyComponentName>
  • *Note - This command creates a component based on UIComponentBase. To use another base class, you can add the additional parameter to the command:
    DbaseClass=<baseClass>
    Where <baseClass> is a full class name, for example:
    -DbaseClass=org.richfaces.MyComponentName

Again, lets compile to make sure everything went as planned...navigate to the component project home directory, and perform: mvn install -e.
If the job is done you should see "BUILD SUCCESSFUL" on the console. The "MyComponentName"/target folder appears and it should contain MyComponentName-1.0-SNAPSHOT.jar file. If so, the component is created and you can now get "down and dirty" developing it.

**One quick developer note: After this little setup is done, you will see the major benefits of developing components with this cdk. It really is better/faster IMO than doing things from scratch. For instance, the xhtml for your renderer is in a template file! You won't have to build your tags and attributes in a java file, the cdk allows you to have a seperate template to make things a little more comfortable on the UI side. And you can mix the two, some conditional code that is better left in the renderer class can stay there, and the UI tags/markup can go in the template.

Component Development Overview

Okay, so now we get to the "fun" stuff. First thing is the design of your component, so you need to answer/do the following:

  • Design a XHTML mockup of your component. Create all the necessary functional html,css and javascript. Don't worry about form submits or ajax yet (if possible). Just play the role of someone who only knows HTML and Javascript for this part.
  • What attributes is your component going to have? All of the basic passthrough attributes are automatically provided, so just decide what functionally you want the end user to be able to control through the use of component attributes. This entity table is your reference for attributes that are accessible through the RichFaces cdk.
  • Do you want your component to fire custom events?

Project Structure

Next, you need to understand the project structure and what is editable and what isn't. Following is the structure of your project:

 
 
pom.xml - component project Maven configuration 
velocity.log - log file from velocity engine (must be ignored, will be removed) 
src/main/config/component/<components>.xml - your component descriptor file 
src/main/java/* - java sources for your component classes, by default the only abstract component class is generated 
src/main/resources - your resources (images, css, java script) must be there. 
src/main/template - your rendering templates must be there. By default .jspx is generated. 
 

Templates

This is what I was talking about earlier, instead of writing all the code for your HTML in a renderer class, you can develop it in a .jsp and the cdk will convert it into the renderer for you. Here a few features:

Resource Handling

Important! You must use org.ajax4jsf.framework.renderer.HeaderResourcesRendererBase as a base renderer class in order to use resources.

  • <f:resource name=“/org/richfaces/renderkit/html/images/your_image_file.gif” var=“arrow” /> allows your component to serve image resource direclty from the jar. This way all dependencies are located in one location.
  • To add javascript files to your template use:
    <h:scripts>new org.ajax4jsf.framework.resource.PrototypeScript(),“your_custom_script.js”</h:scripts> I am adding Prototype (which is managed by the RichFaces/A4J framework) and a custom script demo file name. **Note the format of this line, don’t add line breaks or they won’t be included, it must all be on one line.

To get a better understanding and more complete references, look at source for the Panel or dataFilterSlider component. Each component uses different techniques and features so if you are stuck, it is good to look at each component’s source, or the one that is closest in features to what you are trying to accomplish.

These are the basics of developing with the RichFaces cdk, now I will go over implementing the skeleton you created in the previous steps.


Developing a Richfaces Component

If you havent already done so, see setup. Here we are going to develop a simple output component. If you followed along above and generated a different project, just use what you have and ignore steps 1-6 below. Most of the work will been done through the cdk generation, which leaves us with the following tasks:

  1. Navigate to [richfaces project root]/richfaces
  2. run create.bat outputExample
  3. Navigate to [richfaces project root]/richfaces/outputExample
  4. run mvn cdk:create -U -cpu -Dname=OutputExample
  5. **Optional I'm using Idea so I run mvn idea:idea at the project root to re-generate my project files.
  6. Dont forget to remove the dependencies mentioned here from your pom.xml in your newly generated project.
  7. Add the component attributes to <MyComponent>.xml
  8. Take the html from our prototype and add to the renderer template/class.

Adding Attributes

Go ahead and open config/component/OutputExample.xml. Since this is a very basic component, I am going to add the following to : (Don't forget to reference the entity table for other attributes)

  • &html_events;
  • &html_style_attributes;

Let's also add a custom attribtue for the ouput value:

Just add these lines under &ui_component_attributes;. This will give you basic style passthrough attributes and html events like onclick handlers.

Now lets do a build... run mvn install -e. If all is success ful, take a look at your OutputExampleRenderer in the target/generated-component folder. You should see the following generated code:

You should never change anything here. I just wanted you to see how these things are generated. Just by adding those few lines to your config, you automagically have a div with passthrough elements being generated as a component.

Creating a Sample Project

First, we need a sample project that we can test our component on. To create the outputExample-sample project that uses jetty for a testing server, navigate to the richfaces-samples directory and run createProject.bat outputExample-sample. From here, all we have to do is add our component as a dependency to this project’s pom.xml file:

Implementing the Renderer

In templates/org/richfaces/htmlOuputExample.jspx you will see the xhtml code for your renderer. This is where we will add the html from our prototype to be rendered as a component. All I did is add one line to output the value of the attribute “stringValue”…

<?xml version="1.0" encoding="UTF-8"?>
<f:root
 xmlns:f="http://ajax4jsf.org/cdk/template"
 xmlns:c=" http://java.sun.com/jsf/core"
 xmlns:ui=" http://ajax4jsf.org/cdk/ui"
 xmlns:u=" http://ajax4jsf.org/cdk/u"
 xmlns:x=" http://ajax4jsf.org/cdk/x"
 class="org.richfaces.renderkit.html.OutputExampleRenderer"
 baseclass="org.ajax4jsf.framework.renderer.AjaxComponentRendererBase"
 component="org.richfaces.component.UIOutputExample"
 >
 <f:clientid var="clientId"/>
 <div id="#{clientId}"
 name="#{clientId}"
 x:passThruWithExclusions="value,name,type,id"
 >
 <p>#{component.attributes[‘stringValue’]}</p>
 </div>
</f:root>

Now we can write a simple Jsp or Facelets page that will render our component in our outputExample-sample app. I am using jsp because that is supported by default in the generated sample app's web.xml file. If you want both Facelets and JSP's to render, check out some of the other sample projects web.xml file.

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://richfaces.ajax4jsf.org/outputExample" prefix="output"%>

<html>
 <head>
 <title></title>
 </head>
 <body>
 <f:view>
 <output:OutputExample stringValue="this is a test value"/>
 </f:view>
 </body>
</html>

That's It!!! Just run mvn jetty:run from your sample app root directory. You may want to clean things up in your component project and in your sample by running mvn clean install first.

So what's the eagsiest way to develop your component then test it out? I usually keep 2 terminal windows open, one at my component project root, and the other at the sample project root. This will allow you to run mvn install if you make changes to your component that can't be picked up by jetty. Also, one great thing about jetty is that it allows you to make changes to your project (xhtml and JSPs) and will automatically pick the changes up and deploy.

Don't forget - Look at other components if you need a reference. This guide is just to get you up and running.

The following documents were used as references:
Creating Components with Components Factory
Component Factory RoadMap