I read on some blogs or articles, that some guys compare the (class based) renderers for the JSF UI components with the *good old* servlet time :-)
This statement has a truth, with the current renderers we have (again) the process of rendering markup (e.g. HTML) inside of clazzes.
If you want to change the behaivor/look-and-feel of the UI component you have to create a custom renderer that fits your needs.

So why not using a template language for rendering, that is easy to read and to maintain?
In my current day job, I have worked (a bit) with Jakarta Velocity and I like what I saw there. So I just decided to create a Renderer that uses a velocity template to renderer the content of a JSF component.
Note, that this is a very simple renderer in its first version. But I'll look again at this stuff. This is just to share my results/toughts...

I started with the simplest renderer out there in jsf space. The renderer for the HtmlOutputText component.
I have a simple jsf file like:


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<f:view>
<h:outputText value="Hello JSF" style="color:red"/>
</f:view>



Also my template is very simple. I focused only on value and style attribute. Here the template goes:


<span #if($component.style) style="$component.style" #end onclick="alert('Velocity rendered');">#if ($component.value) $component.value #end</span>


that's all. Keep in mind, that no style attribute is rendered, if you haven't set the style attribute in your JSF page.

However, my VelocityRenderer for the <h:outputText> looks like:


package net.wessendorf.jsf.renderer;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Properties;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;

public class VelocityRenderer extends Renderer {

    private VelocityContext ctx = null;
    private Template template = null;
    private StringWriter sw = null;
   
    public VelocityRenderer() {
        super();
        Properties p = new Properties();
       
        p.put("file.resource.loader.path", "/home/matzew/");
       
        try {
            Velocity.init(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        ctx = new VelocityContext();

    }
   
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        try {
            template = Velocity.getTemplate("htmltext.vm");
        } catch (ResourceNotFoundException e) {
            e.printStackTrace();
        } catch (ParseErrorException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        sw = new StringWriter();
        ctx.put("component", component);
       
        try {
            template.merge(ctx, sw);
        } catch (ResourceNotFoundException e) {
            e.printStackTrace();
        } catch (ParseErrorException e) {
            e.printStackTrace();
        } catch (MethodInvocationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
       
       
        ResponseWriter writer = context.getResponseWriter();
        writer.write(sw.toString());
       
        sw = null;
    }
}


Here is the place where Velocity meets JSF ;) The construtor is called on startup of the web app, since the Renderers are singletons. Here is the place we init the Velocity infrastructure. The Velocity.init() takes some properties. In my case I told it where my templates are located. Yes... that place is hard coded currently...

The encodeEnd() is the place where the rendering will be done. I lookup the template for the <h:outputText> component. Velocity uses a StringWriter to merge the templates. After creating the StringWriter I  put the UI component to the VelocityContext and call now merge() method on the template. The calculated result I put to the JSF ResponseWriter object. The reason for putting the component into the context is that you now can access all attributes for the JSF UI component in your template to render it (e.g. style, id, ...).

To enable this (plain) renderer you have to configure it. In my faces-config.xml I made this statement:

<faces-config>
...
<render-kit>
  <renderer>
    <component-family>javax.faces.Output</component-family>
    <renderer-type>javax.faces.Text</renderer-type>
    <renderer-class>
net.wessendorf.jsf.renderer.VelocityRenderer
    </renderer-class>
  </renderer>
</render-kit>
...
</faces-config>


That's all.

If you now start your web container and surf to the page you'll see the rendered markup. Clicking on the rendered text will cause the java script 'alert()' method.

On runtime you are now able to change the behaivor like:


<h3 #if($component.style) style="$component.style" #end>#if ($component.value) $component.value #end</h3>

After editing you'll see a red headline instead.

I hope this informations are valuable for you. My next step will be creating of a *better* designed renderer and creating a template for the dataTable component.