Server side action methods on JSF ValueChange events using AJAX listeners

Posted by: Lincoln Baxter III on 01/28/2012

I’m about to show you a pattern that will make your heart sing. I have to thank Brian Leathem for his original idea to use CDI events in the ValueChangeListener, but when combined with a little <f:ajax> magic, there’s almost no limit to what you can do without writing a single line of JavaScript. ValueChangeListeners are also the perfect opportunity to build an Event driven model into your application.

The following example code was taken from our latest Project: SocialPM, a budding Agile Project Management tool. The first problem that CDI events will help us with is the fact that in this loop, you may come to find find that you have no way of accessing the loop variable (in this case, ‘s’) in your ValueChangeListener. CDI can help.

The other issue that comes up as a minor inconvenience is not related to JSF, but is purely programming related. How would you track all of these changes in order to populate something like a status feed? You would have to add logic to each listener – this would increase complexity and make testing more difficult. So let’s get started…

<ui:repeat value="#{stories.list}" var="s">
   ...
   <h:inputText id="priority" value="#{s.priority}" size="2" style="width: 20px;">
       <f:valueChangeListener binding="#{storyPriorityChanged}"/>
   </h:inputText>
   ...
</ui:repeat>
@RequestScoped
@Named("storyPriorityChanged")
public class StoryPriorityChanged implements ValueChangeListener
{
   @Override
   public void processValueChange(final ValueChangeEvent event) throws AbortProcessingException
   {
      if(...)
      {
         // do something with our event, but, we have no reference to '#{s]'
         // only to the old and new values of '#{s.priority}'. We also need
         // to integrate extra logic here in order to track our change events.
      }
   }
}

A ValueChangeListener will execute before data is populated in the Model

And the ValueChange event is not an ActionEvent, so we cannot attach an <f:setPropertyActionListener> to set the value in a backing bean where we would be able to access it from a nested listener. There really should be an <f:setPropertyOnValueChangedListener>, and while we could write one ourselves, that would be somewhat inconvenient.

Fortunately, there’s a better way to do both of these things, and it all hinges on our friend CDI… Oh and <f:ajax> can help too. There are better ways to both make sure our loop instance variable is accessible, and also better ways to aggregate change events into a feed.

A viable, reliable solution

Our code looks something like this, and before you start worrying about the fact that you need to write “more” or “more complicated” Java code, I’ll explain why this method actually loosens the coupling between your UI and your Model/Controller:

Notice that we are using the same ValueChangeListener, and we are still not passing the value of ‘s’, our Story, into the listener. We are going to add an AJAX listener="", which will execute after our tag, and it will be responsible for receiving our Story. The listener allows us to invoke any server-side EL method when the Ajax event occurs; Using EL 2.0, we can pass our Story 's' into the method as a parameter.

<ui:repeat value="#{stories.list}" var="s">
   ...
   <h:inputText id="priority" value="#{stories.current.priority}" class="span1">
      <f:valueChangeListener binding="#{storyPriorityChanged}"/>
      <f:ajax execute="@form" render="pr" listener="#{storyCommandListener.save(stories.current)}" />
   </h:inputText>
   ...	
</ui:repeat>

But we still don't have access to 's' in our ValueChangeListener, so what?

This is where we need to pull out a few tricks from our CDI and Java Patterns playbook, so the first thing we need to do is re-think our strategy.

We know that the ValueChangeListener will be executed before our AJAX listener, so we need a way of performing our value change logic without the Story 's'. Wait, how are we going to do that? The answer is our good friend the Command pattern.

The command pattern "is a design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters."

We will combine the command pattern with CDI Events in order to pass this event to a listener which will later invoke all queued commands when we trigger it with our AJAX listener method. This also handles the problem of capturing our ValueChangeEvents so we can create our status feed. How? We'll get to that soon.

Our updated ValueChangeListener looks like the code below. Notice how we are not actually performing the operation yet, we are simply storing all information that we will need to perform this operation at a later time, when we do have access to our Story 's'. Once we have prepared the StoryCommand instance, we will fire it as a CDI event, using the the built in injected Event changeEvent mechanism.

@RequestScoped
@Named("storyPriorityChanged")
public class StoryPriorityChanged implements ValueChangeListener
{
   @Inject
   private Event<StoryCommand> changeEvent;
 
   @Override
   public void processValueChange(final ValueChangeEvent event) throws AbortProcessingException
   {
      StoryCommand command = new StoryCommand() {
 
         private final Integer oldVal = (Integer) event.getOldValue();
         private final Integer newVal = (Integer) event.getNewValue();
 
         @Override
         public void perform(Story story)
         {
            if(...)
            {
               // perform some action with the values from our event
            }
         }
      };
 
      changeEvent.fire(command);
   }
}

The events fired by our ValueChanceListener are captured by a method which @Observes StoryCommand command events, and stores them in a list until we are ready to use them.

The same class which observes these events is going to perform all queued commands when triggered by our AJAX listener: listener="#{storyCommandListener.save(stories.current)}". Now that we have access to our Story 's', we can run each command passing in the Story on which it will operate.

@Named
@Stateless
@RequestScoped
public class StoryCommandListener
{
   @PersistenceContext
   private EntityManager ss;
 
   private final List<StoryCommand> commands = new ArrayList<StoryCommand>();
 
   protected StoryCommandListener()
   {}
 
   public void capture(@Observes StoryCommand command)
   {
      this.commands.add(command);
   }
 
   @TransactionAttribute
   public void save(Story s)
   {
      for (StoryCommand c : commands) {
         c.perform(s);
      }
      em.save(s);
   }
}

Just for Reference, this is what our StoryCommand class looks like:

public abstract class StoryCommand
{
   public abstract void perform(Story story);
}

Problem solved

We now have access to our Story object in the logic that needs to be executed, but why is this better than simply updating the database in our AJAX listener method itself? We could just do this, after all:

<ui:repeat value="#{stories.list}" var="s">
   ...
   <h:inputText id="priority" value="#{stories.current.priority}" class="span1">
      <f:ajax execute="@form" render="pr" listener="#{storyCommandListener.save(stories.current)}" />
   </h:inputText>
   ...
</ui:repeat>

Status updates

When you want to log change events into a notification feed as we are doing in SocialPM, this is where our new pattern really starts to shine.

It is easier to have a second @Observes method (below) that creates a status update when users perform operations, as opposed to integrating the notification service with every method call (i.e. adding code to each ValueChangeListener.) In the end, it is a trade-off, but the real benefit is that this approach, using AJAX listeners and CDI events is a quick, reliable, and decoupled way to extend functionality to your JSF user interfaces.

   public void capture(@Observes StoryCommand command)
   {
      // update status feed with the User, and the type of changes he/she made.
      notifications.updateStatus(user, command.getType());
   }

Cheers! If you want to check out more of this type of code in action, grab the SocialPM Source Code on GitHub, and give us a shout. We'd love to have some more hands in this project!

About Lincoln Baxter III

Lincoln Baxter III

Creator of PrettyFaces - Url Rewriting for JSF, PrettyTime - Social-style date & time formatting for Java, and a community contributor to the JSF2 Expert Group; his latest project is ScrumShark, an open-source agile project management tool.

Beginning his career in C, C++ development for hardware signal testing automation, Lincoln soon moved on to Perl, dynamic programming languages, artificial intelligence and, more recently - web application frameworks such as Java Server Faces and Groovy on Grails for financial and small business solutions.

When he is not swimming, running, or playing Ultimate Frisbee, Lincoln is focused on improving the openness of Java, the Java Community Process(JCP), and bringing the J2EE platform to small businesses and freelancers.

More About Lincoln »

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 7
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 3
  • Automation Tools: Git, Hudson, Sonar
  • HTML5, Ajax, jQuery, Usability
  • Mobile Applications - iPhone and Android
  • More...
Learn More »

NFJS, the Magazine

May Issue Now Available
  • Client-Side MVC with Spine.js, Part 1

    by Craig Walls
  • On Prototypal Inheritance, Part 2

    by Raju Gandhi
  • Making use of Scala Lazy Collections

    by Venkat Subramaniam
  • Integration Testing Web Applications Using Gradle

    by Kenneth Kousen
Learn More »