JSR-299 spec of JEE6 platform defines a simple yet very powerful event notification model. It has three significant parts; event producer, event payload and event observer. In this blog I will explain how ZK developers can leverage this model to write UI event handlers. Lets take a look at the example demo first.

It is a simple zul file with three textboxes for entering first name, last name and full name and a button to clear all three textboxes. Whenever first name or last name textbox values are changed full name textbox is updated with first name followed by a space followed by last name value. Below you can see the index.zul file source.

— index.zul —

<?page title="Zk Events using CDI event notification model" contentType="text/html;charset=UTF-8"?>
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver" ?>
<zk>
<window id="win1" apply="${eventComposer}" border="normal" 
title="Handling ZK Events using CDI event notification model" width="500px">
  <label value="First Name:" width="150px"></label>
  <textbox id="firstName" width="150px"></textbox><separator></separator>
  <label value="Last Name:" width="150px"></label>
  <textbox id="lastName" width="150px"></textbox><separator></separator>
  <label value="Full Name:" width="150px"></label>
  <textbox id="fullName" width="300px"></textbox><separator></separator>
  <button id="clearBtn" label="Clear"></button>
</window>
</zk>

To make things little bit more interesting I follow standard ZK MVC approach in this example to separate the view from the controller. So you can see index.zul file contains only view part of the application while controller code is written separately in a composer class. In previous article Henri showed us how to use DelegatingVariableResolver to resolve CDI managed beans by their EL names. I use the same approach to resolve the composer and apply to window component. Here EventComposer is annotated with @Named annotation and according to JSR-299 CDI spec by default it will be resolved for “eventComposer” EL name.

— index.zul —


<window id="win1" apply="${eventComposer}" border="normal" 
title="Handling ZK Events using CDI event notification model" width="500px">

— EventComposer.java —


@Named
@IdSpaceScoped
public class EventComposer extends GenericCDIComposer implements Serializable {
}

Now all I need is event handling methods for firstName/lastName onChange events and clearBtn onClick event. Event handling methods can be defined either by GenericForwardComposer way of writing event handling methods using naming convention (for eg. onClick$myButton) or registering them using addEventListener on individual components. In addition to these two approaches I can now also use CDI event notification model as shown below.


public void resetAllFields(@Observes @ZKEvent("clearBtn.onClick") Event evt) {
     Textbox firstName = ((Textbox)evt.getTarget().getFellow("firstName"));
     firstName.setValue("");
     Textbox lastName = ((Textbox)evt.getTarget().getFellow("lastName"));
     lastName.setValue("");
     Textbox fullName = ((Textbox)evt.getTarget().getFellow("fullName"));
     fullName.setValue("");
}

public void updateFullName(@Observes @ZKEvent("firstName.onChange, lastName.onChange") Event evt) {
     Textbox firstName = ((Textbox)evt.getTarget().getFellow("firstName"));
     Textbox lastName = ((Textbox)evt.getTarget().getFellow("lastName"));
     Textbox fullName = ((Textbox)evt.getTarget().getFellow("fullName"));
     fullName.setValue(firstName.getValue() + " " + lastName.getValue());
}

Here I mark method parameter Event evt with @Observes annotation. In other words Event which is a ZK org.zkoss.zk.ui.event.Event type is an observed event type. In addition to @Observes I have a custom annotation @ZKEvent to distinguish between different ZK events. @ZKEvent annotation should be supplied with a value that indicates for which component and for what event this method needs to be invoked. In above example updateFullName method is an event handling method for two events; firstName textbox onChange and lastName textbox onChange.

Note that EventComposer class extends from GenericCDIComposer class which is responsible for the event dispatching. In this example EventComposer is both CDI event producer and CDI event observer whereas org.zkoss.zk.ui.event.Event instance is the actual CDI event payload.

Typical event flow in above example is like this

  1. A ZK UI event is fired whenever firstName/lastName textbox value is changed or clearBtn button is clicked
  2. EventComposer will receive those ZK org.zkoss.zk.ui.event.Event and in turn fire(org.zkoss.zk.ui.event.Event evt) with appropriate ZKEvent annotation
  3. CDI container takes over and notifies any methods with @Observes annotation for org.zkoss.zk.ui.event.Event type AND with correct ZKEvent annotation

More?

You will notice in this example EventComposer do not hold any references to ZK components. In next article I will demonstrate how you can @Inject ZK components into your Composer. Currently I can do it with some limitations due to zul parsing and correct time to inject componets. That would require developers to follow some convention but ease of development using ZK is one of our core values so we plan to resolve the issues and get rid of those limitations first. Until then stay tuned. In the meantime any feedback or thoughts on this article is most welcome.

References

ZK MVC smalltalk

Weld – JSR-299 Reference Implementation

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.

4 Responses to “Handling ZK Events using CDI event notification model”

  1. Manish says:

    Hi Ashish,

    This is a nice and helpful article.

    Thanks,
    Manish

  2. Prashant says:

    AshD —
    Good collection of facts, examples and video! I can begin with JEE6 from this 🙂

    Thank you!
    Prashant

  3. When I initially commented I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get several e-mails with the same comment. Is there any way you can remove people from that service? Many thanks!

  4. Alejandro says:

    I´m still learning zk, but i keep reciving errors in my code when i type this (@Named
    @IdSpaceScoped @Observes @ZKEvent), i know that it must be quite simple to solve it, but even if already imported the jars from the JSR-299 my code is still wrong. T.T

Leave a Reply