Don’t you know this: You have an application using some dialogs and each dialog contains some required fields and some, whiche are not mandatory. To disinguish these two kinds of fields, the required fields should be marked, e.g. with an asterisk. Now, what we want to do, is to write a central function which might be used in all pages. The idea is quite simple: Before rendereing, check all labels and theis associated input components. If the input is required, mark it.

The central place might be a faclets template.

<f:metadata>
     <f:phaseListener type="calculator.LifeCycleListener"/>
 </f:metadata>

This registers a phase listener with it’s full qualified name. Within this listener, we will check all components and modify the label.

package calculator;

import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

/**
 *
 * @author mmueller
 */
public class LifeCycleListener implements PhaseListener {
  UIViewRoot _root;

  @Override
  public void beforePhase(PhaseEvent event) {
    _root = event.getFacesContext().getViewRoot();
    if (_root != null && event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
      markLabels4Required(_root);
    }
  }

  @Override
  public void afterPhase(PhaseEvent event) {
  }

  @Override
  public PhaseId getPhaseId() {
    return PhaseId.ANY_PHASE;
  }

  private void markLabels4Required(UIComponent parent) {
    String marker = " *";
    for (UIComponent child : parent.getChildren()) {
      if (child instanceof HtmlOutputLabel) {
        HtmlOutputLabel label = (HtmlOutputLabel) child;
        String targetId = label.getNamingContainer().getClientId() +
                          ":" + label.getFor();
        UIComponent target = _root.findComponent(targetId);
        if (target instanceof UIInput) {
          UIInput input = (UIInput) target;
          String labelText = label.getValue().toString();
          if (input.isRequired() && !labelText.endsWith(marker)) {
            label.setValue(labelText + marker);
          }
          if (!input.isRequired() && labelText.endsWith(marker)) {
          label.setValue(labelText.substring(0,
                         labelText.length() - marker.length()));
          }
        }
      }
      markLabels4Required(child);
    }
  }
}

The PhaseListener may follow all phases. Here, we only use before RenderResponse. In this special case there is an alternative available:

<f:metadata>
 <f:event type="preRenderView" listener="#{phaseBean.preRenderView}"/>
</f:metadata>

PhaseBean:

[...]
UIViewRoot _root;

public void preRenderView(ComponentSystemEvent e) {
  _root = FacesContext.getCurrentInstance().getViewRoot();
  markLabels4Required(_root);
}
[...]

This article is just to give you a quick information. Later on, I might include this in my JSF tutorial and add some more explanation.

Update: The code shows you an approach I used once ago. At the end of 2011 I switched to manipulate CSS. The principal approach is still the same, but instead of exchanging content (the “*”), I simply change style.

To web development content.