JavaServer Faces has always been sold as a piece of flexible and extensible code. It really is. Through its factory facilities you can bend and twist that web framework until it fits. Today I tried to resolve something that has bothered me a long time. For a showcase I have implemented a few supporting lines of code that come handy in lots of places. When prototyping something, that code often ends up in some abstract base class from which managed bean are subclassed or it even ends up in some “helper” class with static methods. In the end you don’t feel that it is at the right place.

The example I’m showing now is trying to detect if a request validated with some severe message.

1
2
3
4
public boolean isSevereMessage() {
  Severity severity = FacesContext.getCurrentInstance().getMaximumSeverity();
  return severity == null ? false : severity.compareTo(FacesMessage.SEVERITY_INFO) > 0;
}

Seems that could go into the FacesContext implementation, right? In order to get there you need a FacesContextFactory that instantiates your FacesContext implementation.

The FacesContextFactory is setup by a FactoryFinder which supports quite a few strategies for picking up the factory.

1
2
3
4
5
6
7
8
9
10
11
12
public class BlueprintFacesContextFactory extends FacesContextFactory {
  private final FacesContextFactory factory;
  public BlueprintFacesContextFactory(FacesContextFactory factory) {
      super();
      this.factory = factory;
  }
  @Override
  public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle)
          throws FacesException {
      return new BlueprintFacesContext(factory.getFacesContext(context, request, response, lifecycle));
  }
}

By implementing a constructor that takes a FacesContextFactory as argument we can easily get hold of the factory provided by the JSF implementation and delegate.

For our FacesContext implementation the deal is to wrap the existing FacesContext with your own implementation. Therefore it also implements a constructor taking a Facescontext as argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class BlueprintFacesContext extends FacesContext {
  private final FacesContext context;
  public BlueprintFacesContext(FacesContext context) {
      super();
      this.context = context;
      setCurrentInstance(this);
  }

  /**
  * Test if a request processing resulted in a severe message. A message is
  * considered severe if it is more severe than INFO.
  *
  * @return true if
  *         <code>maximumSeverity.compareTo(FacesMessage.SEVERITY_INFO) > 0</code>
  */
  public boolean isSevereMessage() {
      Severity severity = getMaximumSeverity();
      return severity == null ? false : severity.compareTo(FacesMessage.SEVERITY_INFO) > 0;
  }
  @Override
  public ELContext getELContext() {
      ELContext elContext = context.getELContext();
      elContext.putContext(FacesContext.class, this);
      return elContext;
  }
  //other methods stripped for brevity, they only delegate to context!

With JSF2 a FacesContextWrapper is provided so only those methods need to overridden that are required to add the desired behaviour. Here I needed to override getELContext in order to make the custom FacesContext available in EL expressions.

Comments