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> |
<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.
}
}
} |
@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> |
<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);
}
} |
@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);
}
} |
@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);
} |
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> |
<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());
} |
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!
Wow, that’s… convoluted. A great example of what’s wrong with J2EE.
I’m sorry you feel that way. This is a relatively complex solution (for technical reasons that I stated in the conclusion) to an issue that ALSO has a simple solution. If you had read the entire article, you might have seen that. Fortunately, you’re right about one thing. I can stand to make this clearer so that future readers don’t miss that fact 😉 Thanks!
While I agree it is quite a bit of work for performing one action, it really starts to shine when you need to perform multiple actions, as you stated in the article. Decoupling logic in your application is something that is really a must as soon as you get an application of any decent sized complexity, like you will find in most “enterprise applications”. Sure, you could add all of the necessary code and actions as you go in different iterations, but you’d had best have a good test suite for those methods / app to make sure you don’t break anything. Let’s face it, most applications don’t do as much testing as they should. When you can simply fire an event and have x number of observers and have each action being performed it’s own observers, even a poorly tested application can ensure it doesn’t break the previously coded action. Of course this all takes discipline.
Good job Lincoln, thanks for showing that way of doing things!
Decoupling with events is nice but you need some sort of tooling to keep track of observers otherwise you will sooner or later shoot yourself in the foot when you have forgotten about some observer somewhere that kicks in…
Very true! JBoss Tools for Eclipse has a very nice set of tools that allows you to navigate between and discover all CDI observers for a given event 🙂
http://jboss.org/tools
A bit heavy but such a cool solution. Nice article.
There is a few small points that I want to ask about :
1) Inside the ui:repeat, why do you use “stories.current” instead of “s” var ? (I said it was small points 🙂 )
2) In the f:ajax tag, why do you execute @form and not @this ? Since we only want to track the value change of this particular input, is there any necessity to submit all the form ?
3) In your f:ajax tag, you render “pr”, is that the whole list ? Not enough to render only the input ? (or a decorate around it)
4) Wouldn’t it be better if the f:ajax event was specified ? Like ‘event=”valueChange”‘ ?
That’s not very important questions, the main point was the full pattern you explain, but if you have time, I would be glad to know the answers.
Thanks.
Note that with Omnifaces, you can use:
Faces.evaluateExpressionGet("#{s}");
MUCH EASIER!