Archive for January, 2012

Easily disable sorting in PrimeFaces 3’s DataTable

16 January 2012

PrimeFaces provides a convenient and easy to use sorting facility for its DataTable. Together with Facelets, this facility allows us to create re-usable columns that are natural sortable by default. E.g.:

  1. <ui:composition xmlns="" 
  2.     xmlns:h=""
  3.     xmlns:ui="" 
  4.     xmlns:p=""
  5. >
  6.     <p:column headerText="#{headerText}" sortBy="#{value}">
  7.         <h:outputText id="#{id}" value="#{value}" />
  8.     </p:column>    
  9. </ui:composition>

Such a column can be used on a page inside a DataTable as follows:

  1. <my:sortableColumn id="foo" value="#{someBean.someValue}" />

The problem

The above is only a simple example, and real-life usage can be more complex with e.g. default styles and cell editing capabilities added. With such complex tags, it might be desirable to turn off sorting for certain columns programmatically. By default this does not seem to be possible in PrimeFaces. Setting the value attribute in the above example to null or the empty string via an expression prevents sorting, but still renders the sorting icon.

The reason for this is that the PrimeFaces renderer (org.primefaces.component.datatable.DataTableRenderer) checks for the presence of a value expression to determine whether the icon should be rendered, regardless of whether this expression evaluates to something non-empty. So nothing you pass into the value attribute of the above showed tag can make the value expression itself null, nor can any extra attribute accomplish this in the tag’s definition.

Custom helper tag

One solution is to build a simple helper tag that takes a parameter and based on that sets the value expression of its parent component to null. This tag can be nested inside a column. Taking it one step further, we can nest the tag inside a table and programmatically disable sorting on all columns. The following shows the implementation of such a tag:

  1. public class ColumnSorterDisabler extends TagHandler {
  3.     public ColumnSorterDisabler(TagConfig config) {
  4.         super(config);
  5.     }
  7.     @Override
  8.     public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
  9.         Boolean disableSorting = getRequiredAttribute("disableSorting").getBoolean(ctx);
  10.         if (disableSorting) {
  11.             if (parent instanceof Column) {
  12.                 parent.setValueExpression("sortBy", null);
  13.             } else if (parent instanceof DataTable) {
  14.                 for (UIComponent child : parent.getChildren()) {
  15.                     if (child instanceof Column) {
  16.                         child.setValueExpression("sortBy", null);
  17.                     }
  18.                 }
  19.             }
  20.         }        
  21.     }    
  22. }

After declaring this in a *-taglib.xml, we can use it as follows inside a Facelets tag:

  1. <ui:composition xmlns="" 
  2.     xmlns:h=""
  3.     xmlns:ui="" 
  4.     xmlns:p=""
  5. >
  6.     <my:columnSorterDisabler disableSorting="#{disableSorting}" />
  8.     <p:column headerText="#{headerText}" sortBy="#{value}">
  9.         <h:outputText id="#{id}" value="#{value}" />
  10.     </p:column>    
  11. </ui:composition>

We can now disable sorting on a per-column basis as follows:

  1. <my:sortableColumn id="foo" value="#{someBean.someValue}" disableSorting="true" />

or for an entire table:

  1. <p:dataTable value="#{someBean.someValues}" var="something">
  2.     <my:sortableColumn id="foo" value="#{}" />
  3.     <my:sortableColumn id="bar" value="#{}" />
  4.     <my:columnSorterDisabler disableSorting="true" />
  5. </p:dataTable>

One caveat to remember, TagHandlers exist only at ‘build-time’, so when using expressions to do the disabling the data these point to has to be available during build-time.

The f:attributes tag

Another solution, contributed by my co-worker Bauke Scholtz, is taking advantage of the <f:attribute> tag. This tag does the same thing as an actual tag attribute, but contrary to an actual attribute this one can be conditionally excluded using <c:if>. In that case the implementation of our re-usable column becomes this:

  1. <ui:composition xmlns="" 
  2.     xmlns:h=""
  3.     xmlns:ui="" 
  4.     xmlns:p=""
  5. >
  6.     <p:column headerText="#{headerText}">
  7.         <c:if test="#{empty sortable or sortable}">
  8.             <f:attribute name="sortBy" value="#{value}"/>
  9.         </c:if>
  10.         <h:outputText id="#{id}" value="#{value}" />
  11.     </p:column>    
  12. </ui:composition>

Notice how the tag attribute sortBy has been replaced by a child tag. This approach is really convenient since it simply uses JSF’s build-in functionality. To disable sorting for all columns at once, the helper tag based approach is still useful though. Note that just like the helper tag, a <f:attribute> tag only exists at build-time, so here too only data that’s available during that time can be used.

Arjan Tijms

Passing action methods into Facelets tags

6 January 2012

The problem

JSF, via Facelets, has various mechanisms to easily reuse view content. One of those is the Facelets tag, which allows one to reuse markup and/or components.

One notorious problem with these Facelets tags is that you can’t directly pass action methods (method expressions) into them. There’s a workaround where you break the expression into two parts, the base (which should be a value expression) and the name of the method as a plain string. Inside the tag these two are then combined again, e.g. via the array notation syntax. See e.g.

Another approach is to create a small helper tag that converts the value expression in some way into a method expression. There have been a couple of implementations of this idea:

Finding a solution

In this blog I would like to present another variant on the tag handler idea, which doesn’t require nesting the content and also doesn’t parse any embedded EL expression manually. It supports EL parameters provided by the calling view. It’s not perfect however, since it does not support parameters being passed into the method from the target component (e.g. an ActionEvent for an actionListener).

The idea is to wrap the value expression (which represents the original method expression passed into the Facelets tag) inside a custom method expression. This method expression simply gets the value from the embedded value expression, which as “side-effect” executes this method.

The resulting method expression has to be stored somewhere. The request scope would be an option, but then it would be directly available outside the Facelets tag, which isn’t a good example of encapsulation.

An alternative is the javax.el.VariableMapper, a “magic” little thing that is able to scope value expressions to the duration of a Facelets tag (it’s magical since remember that the tag doesn’t exist any more after the component tree has been build). This however requires a value expresion again, so in an odd twist we wrap the method expression that we just created in a value expression again.

So, how can this work? Wasn’t the entire point of this exercise to go to a method expression? Well, as it turns out a value expression can be accepted wherever a method expression is required, iff this value expression directly returns a method expression.

E.g. the Apache EL implementation’s org.apache.el.parser.AstIdentifier contains the following code fragment that accomplishes this:

  1. // case A: ValueExpression exists, getValue which must
  2. // be a MethodExpression
  3. VariableMapper varMapper = ctx.getVariableMapper();
  4. ValueExpression ve = null;
  5. if (varMapper != null) {
  6.     ve = varMapper.resolveVariable(this.image);
  7.     if (ve != null) {
  8.         obj = ve.getValue(ctx);
  9.     }
  10. }
  11. // (case B omitted)
  12. if (obj instanceof MethodExpression) {
  13.     return (MethodExpression) obj;
  14. }


Without further ado, here’s the code for the TagHandler that implements all the wrapping:

  1. public class MethodParamHandler extends TagHandler {
  3.     private final TagAttribute name;
  4.     private final TagAttribute value;
  6.     public MethodParamHandler(TagConfig config) {
  7.         super(config);
  8. = this.getRequiredAttribute("name");
  9.         this.value = this.getRequiredAttribute("value");
  10.     }
  12.     public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
  13.         String nameStr = name.getValue(ctx);
  15.         // The original value expression we get inside the Facelets tag, that's actually the method expression passed-in by the user.
  16.         ValueExpression valueExpression = value.getValueExpression(ctx, Object.class);
  18.         // A method expression that wraps the value expression and uses its own invoke method to get the value from the wrapped expression.
  19.         MethodExpression methodExpression = new MethodExpressionValueExpressionAdapter(valueExpression);
  21.         // Using the variable mapper so the expression is scoped to the body of the Facelets tag. Since the variable mapper only accepts
  22.         // value expressions, we once again wrap it by a value expression that directly returns the method expression.
  23.         ctx.getVariableMapper().setVariable(nameStr, ctx.getExpressionFactory().createValueExpression(methodExpression, MethodExpression.class));    
  24.     }
  26. }

The rather trivial adapter that wraps the value expression is shown below. The main method of interest here is invoke(). Note how unfortunately the params parameter has to be ignored.

  1. public class MethodExpressionValueExpressionAdapter extends MethodExpression {
  3.     private static final long serialVersionUID = 1L;
  5.     private final ValueExpression valueExpression;
  7.     public MethodExpressionValueExpressionAdapter(ValueExpression valueExpression) {
  8.         this.valueExpression = valueExpression;
  9.     }
  11.     @Override
  12.     public Object invoke(ELContext context, Object[] params) {
  13.         return valueExpression.getValue(context);
  14.     }
  16.     @Override
  17.     public MethodInfo getMethodInfo(ELContext context) {                
  18.         return new MethodInfo(null, valueExpression.getExpectedType(), null);
  19.     }
  21.     @Override
  22.     public boolean isLiteralText() {
  23.         return false;
  24.     }
  26.     @Override
  27.     public int hashCode() {
  28.         return valueExpression.hashCode();
  29.     }
  31.     @Override
  32.     public String getExpressionString() {
  33.         return valueExpression.getExpressionString();
  34.     }
  36.     @Override
  37.     public boolean equals(Object obj) {
  38.         if (obj == this) {
  39.             return true;
  40.         }
  42.         if (obj instanceof MethodExpressionValueExpressionAdapter) {
  43.             return ((MethodExpressionValueExpressionAdapter)obj).getValueExpression().equals(valueExpression);
  44.         }
  46.         return false;
  47.     }
  49.     public ValueExpression getValueExpression() {
  50.         return valueExpression;
  51.     }
  52. }

The tag handler has to be registered in a *-taglib.xml file, e.g.:

  1. <tag>
  2.     <tag-name>methodParam</tag-name>
  3.     <handler-class>com.example.MethodParamHandler</handler-class>
  4.     <attribute>
  5.         <name>name</name>
  6.         <required>true</required>
  7.         <type>java.lang.String</type>
  8.     </attribute>
  9.     <attribute>
  10.         <name>value</name>
  11.         <required>true</required>
  12.         <type>java.lang.String</type>
  13.     </attribute>
  14. </tag>

Using the tag handler

So the above takes care of implementing the converting tag handler. Let’s take a look at how we would use this.

Suppose we have a Facelets tag in the following using-view fragment, where the action attribute binds to a method in a backing bean taking an EL parameter:

  1. <p:dataTable id="table" value="#{someBean.someValues}" var="someValue">
  2.     <my:deleteActionColumn action="#{someBean.delete(someValue)}" update="table" />
  3. </p:dataTable>

The tag could then be defined as shown below. The interesting bit is the <my:methodParam> tag, which converts the value expression “action” to the method expression “actionMethod”. The tag can be placed at many locations, but reasonable choices would be as the first child of the root or directly above the component using it. I choose the latter here.

  1. <ui:composition
  2.     xmlns="" 
  3.     xmlns:ui="" 
  4.     xmlns:h=""
  5.     xmlns:p=""
  6.     xmlns:my=""
  7. >
  8.     <p:column styleClass="some_style">
  10.         <my:methodParam name="actionMethod" value="#{action}"/>
  12.         <p:commandLink id="someId" action="#{actionMethod}" process="@this" update="#{update}">
  13.             <h:graphicImage value="/icons/delete.png" alt="#{i18n['something.delete']}" title="#{i18n['something.delete.tooltip']}" width="15" height="15" />
  14.         </p:commandLink>
  15.     </p:column>
  17. </ui:composition>

This Facelets tag too again has to be explicitly declared in a *-taglib.xml, e.g.:

  1. <tag>
  2.     <tag-name>deleteActionColumn</tag-name>
  3.     <source>faces/tags/deleteActionColumn.xhtml</source>
  4.     <attribute>			
  5.         <name>action</name>        
  6.         <type>javax.el.MethodExpression</type>
  7.     </attribute>
  8. </tag>

Any other alternatives?

At first sight the composite component mechanism would seem to be an alternative, as it explicitly supports passing in method references. However, the composite component isn’t a true substitute for Facelets tags. Namely, it inserts a parent component in the tree instead of simply its content. This doesn’t work for tables, panel groups, and all other kinds of components that require children of a specific type or in a specific order to be present.

You can sometimes do some magic with composite components by using the componentType attribute (see e.g. JSF composite component binding to custom UIComponent), but this only gets you so far and sometimes you really simply need the raw body of a tag to be inserted into the using page.

Another alternative solution, arguably the one and only Real Solution™, is having this fixed by Facelets. Indeed, many years ago there was an issue created for this at the Facelets JIRA: with a similar issue even having a patch submitted for it: Unfortunately, neither of those issues ever got resolved.

Hopefully the alternative solution provided here is useful for those situations where the existing workarounds are not completely satisfactory. Do note again that the solution presented here is also not ideal, but seems to work nicely in a rather straightforward way for action methods that don’t use framework provided parameters, but can optionally take user supplied EL parameters.

An implementation of this is readily available in the new OmniFaces library, from where you can find the documentation and the full source code. There’s also a live demo available.

Arjan Tijms

css.php best counter