8.9. Component-driven events
Seam components interact by calling each other's methods. Stateful components can even implement the observer/observable pattern. However, to enable more loosely-coupled interaction, Seam provides component-driven events.
Specify event listeners (observers) in
components.xml.
<components> <event type="hello"> <action execute="#{helloListener.sayHelloBack}"/> <action execute="#{logger.logHello}"/> </event> </components>
Here, the event type is an arbitrary string.
When an event occurs, the actions registered for that event are called in the order they appear in
components.xml. Seam provides a built-in component to raise events.
@Name("helloWorld") public class HelloWorld { public void sayHello() { FacesMessages.instance().add("Hello World!"); Events.instance().raiseEvent("hello"); } }
You can also use an annotation, like:
@Name("helloWorld") public class HelloWorld { @RaiseEvent("hello") public void sayHello() { FacesMessages.instance().add("Hello World!"); } }
This event producer is not dependent upon event consumers. The event listener can now be implemented with absolutely no dependency upon the producer:
@Name("helloListener") public class HelloListener { public void sayHelloBack() { FacesMessages.instance().add("Hello to you too!"); } }
The method binding defined above in
components.xml maps the event to the consumer. You can also do this with annotations:
@Name("helloListener") public class HelloListener { @Observer("hello") public void sayHelloBack() { FacesMessages.instance().add("Hello to you too!"); } }
In Seam, event objects do not need to propagate state between the event producer and listener. State is held in the Seam contexts, and shared between components. However, you can pass an event object as:
@Name("helloWorld") public class HelloWorld { private String name; public void sayHello() { FacesMessages.instance().add("Hello World, my name is #0.", name); Events.instance().raiseEvent("hello", name); } }
@Name("helloListener") public class HelloListener { @Observer("hello") public void sayHelloBack(String name) { FacesMessages.instance().add("Hello #0!", name); } }