Question

There are a couple of things that I am having a difficult time understanding with regards to developing custom components in JSF. For the purposes of these questions, you can assume that all of the custom controls are using valuebindings/expressions (not literal bindings), but I'm interested in explanations on them as well.

  1. Where do I set the value for the valuebinding? Is this supposed to happen in decode? Or should decode do something else and then have the value set in encodeBegin?
  2. Read from the Value Binding - When do I read data from the valuebinding vs. reading it from submittedvalue and putting it into the valuebinding?
  3. When are action listeners on forms called in relation to all of this? The JSF lifecycle pages all mention events happening at various steps, but its not completely clear to me when just a simple listener for a commandbutton is being called

I've tried a few combinations, but always end up with hard to find bugs that I believe are coming from basic misunderstandings of the event lifecycle.

Was it helpful?

Solution

There is a pretty good diagram in the JSF specification that shows the request lifecycle - essential for understanding this stuff.

The steps are:

  • Restore View. The UIComponent tree is rebuilt.
  • Apply Request Values. Editable components should implement EditableValueHolder. This phase walks the component tree and calls the processDecodes methods. If the component isn't something complex like a UIData, it won't do much except call its own decode method. The decode method doesn't do much except find its renderer and invokes its decode method, passing itself as an argument. It is the renderer's job to get any submitted value and set it via setSubmittedValue.
  • Process Validations. This phase calls processValidators which will call validate. The validate method takes the submitted value, converts it with any converters, validates it with any validators and (assuming the data passes those tests) calls setValue. This will store the value as a local variable. While this local variable is not null, it will be returned and not the value from the value binding for any calls to getValue.
  • Update Model Values. This phase calls processUpdates. In an input component, this will call updateModel which will get the ValueExpression and invoke it to set the value on the model.
  • Invoke Application. Button event listeners and so on will be invoked here (as will navigation if memory serves).
  • Render Response. The tree is rendered via the renderers and the state saved.
  • If any of these phases fail (e.g. a value is invalid), the lifecycle skips to Render Response.
  • Various events can be fired after most of these phases, invoking listeners as appropriate (like value change listeners after Process Validations).

This is a somewhat simplified version of events. Refer to the specification for more details.

I would question why you are writing your own UIComponent. This is a non-trivial task and a deep understanding of the JSF architecture is required to get it right. If you need a custom control, it is better to create a concrete control that extends an exisiting UIComponent (like HtmlInputText does) with an equivalent renderer.

If contamination isn't an issue, there is an open-source JSF implementation in the form of Apache MyFaces.

OTHER TIPS

Action listeners, such as for a CommandButton, are called during the Invoke Application phase, which is the last phase before the final Render Response phase. This is shown in The JSF Lifecycle - figure 1.

It is the only framework that I've ever used where component creation is a deep intricate process like this. None of the other web frameworks (whether in the .net world or not) make this so painful, which is completely inexplicable to me.

Some of the design decisions behind JSF start to make a little more sense when you consider the goals. JSF was designed to be tooled - it exposes lots of metadata for IDEs. JSF is not a web framework - it is a MVP framework that can be used as a web framework. JSF is highly extensible and configurable - you can replace 90% of the implementation on a per-application basis.

Most of this stuff just makes your job more complicated if all you want to do is slip in an extra HTML control.

The component is a composition of several inputtext (and other) base components, btw.

I'm assuming JSP-includes/tooling-based page fragments don't meet your requirements.

I would consider using your UIComponentELTag.createComponent to create a composite control with a UIPanel base and creating all its children from existing implementations. (I'm assuming you're using JSPs/taglibs and making a few other guesses.) You'd probably want a custom renderer if none of the existing UIPanel renderers did the job, but renderers are easy.

The best article I've found is Jsf Component Writing, as for 2 where do I read the value for a value binding in your component you have a getter that looks like this


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

how did this get into the getValueBinding? In your tag class setProperties method

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top