In an implementation using the JBoss RichFaces rich:dataScroller component, I noticed the first attribute of a UIData component is maintained even if the DataModel it is displaying has changed. It turns out, this is an issue with JSF. The UIData component does not track the DataModel it represents. Thus, when the DataModel is updated it has no effect on the first attribute of the UIData component. In defense of JSF, it would be difficult to know when a DataModel update should trigger an update of the UIData as this would require making some assumptions about the model.

As you can imagine, this can lead to consistency issues with data versus the state of the UI when pagination is used. For example, if I have a DataModel that wraps a List of 100 elements that are the results of a search. In the display, I can show 10 elements per page and allow the user to paginate freely with the rich:dataScroller component. If the user paginates to the fifth listing, the first attribute of the UIData component now points to 50. If the user then narrows the search (by changing some search criteria and re-submitting) the result set is reduced to 10. Now we have an issue. The user sees no results because the UIData is looking for index 50 to start the List. The first attribute does not get updated to reflect the change in the model.

So how can we resolve this? A simple Seam interceptor would do the trick (if you are already using stereotypes this will be a snap). Assuming you have not yet created a stereotype for your Action classes, the following steps can be taken,

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Interceptors(ActionInterceptor.class)
@Inherited
public @interface Action {}

This will ensure that any @Action class will be intercepted by the ActionInterceptor. Now create a method-level annotation similar to the following:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Search {
  String dataTableId();
}

The dataTableId is the component ID of the DataTable in your page. Note: This will require that you specify unique IDs for your components which is good practice in JSF anyway. Next, you must provide the interceptor which does the work of reseting the first attribute for the component. When an @Search action is executed that resets the DataModel, we want to reset the UIData:

@Interceptor(stateless=true)
public class ActionInterceptor implements Serializable
{
  ...
  @AroundInvoke
  public Object aroundInvoke(InvocationContext invocation)
      throws Exception
  {
    Method method = invocation.getMethod(); 

    if(method.isAnnotationPresent(Search.class))
    {
      UIComponent component = FacesContext
        .getCurrentInstance().getViewRoot()
        .findComponent(searchAnnotation.dataTableId()); 

      if(component != null && component instanceof UIData)
      {
        UIData dataTable = (UIData) component; 

        dataTable.setFirst(0);
      }
    } 

    result = invocation.proceed();
  }
...

You would probably want to add your own exception handling to this as well. Finally, we can use it in our application:

@Name("myAction")
@Stateful
@Action
public class MyActionBean implements MyAction {
  ...
  @DataModel
  List<myentity> searchResults;
  ...
  @Search(dataTableId="myForm:searchResults")
  public void search() throws Exception
  {
    searchResults = entityManager.createQuery(...)
       .getResultList();
  }
  ...

As I mentioned before, if stereotypes are already being used, this becomes a snap. Simply add the @Search annotation and add the code to handle the dataTable reset in your existing ActionInterceptor.