Seam component events

Posted by: Max Katz on 01/04/2010

A very powerful feature in Seam that usually doesn’t get enough attention in my opinion is component-driven events. Seam component can raise or throw arbitrary event and any number of other Seam components can observe or listen to these events. This truly creates a loose coupled architecture. Components raise events and anyone who cares listens to the event. The components are not connected to each other in any way.

Let’s start with CourseManager component:

@Name("courseManager")
public class CourseManager {
 
   private String name; // setter and getter
 
   @Out(required=false)
   private String studentName;
 
   @Logger Log log;
 
   @RaiseEvent("courseDropped")
   public void drop() {
     studentName = name;
     log.info("course dropped");
   }
}

In component above when drop() method is invoked, courseDropped event will be raised via @RaiseEvent annotation. Once invocation is done, the component will outject studentName variable.

Although data can passed with the event, a better way is to use bijection in Seam. The name variable would most likely be submitted from a JSF page. Its value is assigned to studentName component variable and studentName is outjected after the method invokation. Anyone who is interested in this event can listen to it and also get the data associated with the event (via injection).

Below is studentAdvisor component that listens to courseDropped event. Every time a student drops a course, the student advisor is notified that a student dropped a course.

@Name("studentAdvisor")
public class StudentAdvisor {
 
   @Out
   private String studentAdvisorMessage;
 
   @In 
   private String studentName;
 
   @Logger Log log;	
 
   @Observer("courseDropped")
   public void courseDropped() {
      this.studentAdvisorMessage = "Student dropped course: "+studentName;
      log.info("advisor notified");
   }
}

This component observes or listens to the courseDropped event raised by courseManager via @Observer annotation. In other words, when courseDropped is raised, courseDropped() method is invoked. How do we get the data from the event? We use @In annotation to inject studentName into this component just before courseDropped is invoked.

This is very powerful and easy to use and creates a very nice loosely coupled architecture for the components. The components don’t know anything about other components. Components only raise or listen to events.

You can have more than one component listen to a particular event. For example, we can add parents component to be notified when a student drops a class:

@Name ("parents")
public class Parents {   	
   @In
   private String studentName;
 
   @Out
   private String parentsMessage;
 
   @Logger Log log;
 
   @Observer ("courseDropped")
   public void childrenParentTalk () {
      this.parentsMessage = studentName +"'s parents notified";                                 
      log.info("children parent talk");
   }
}

In above component, childrendParentTalk() method is invoked when courseDropped event is raised.

Components can also raise multiple events:

@RaiseEvent ({"courseDropped", "sendEmailConfirmation"})
public void drop (){
   log.info("course dropped");
}

Two different components observe the event:

@Name("courseManager")
public class CourseManager {
   ...
   @Observer ("courseDropped")
   public void drop (){
      log.info("course dropped");
   }
   ...
}
@Name("emailConfirmation")
public class EmailConfirmation {
   ...
   @Observer ("sendEmailConfirmation")
   public void sendEmail (){
      log.info("email confirmation sent");
   }
   ...
}

Instead of using @RaiseEvent annotation, it’s possible to raise an event programmatically:

Events.instance().raiseEvent("courseDropped");

Lastly, instead of using @Observer annotation, it’s possible to specify event listeners inside descriptor file:

<event type="courseDropped">
      <action execute="#{studentAdvisor.courseDropped}"/>
       <action execute="#{parents.childrenParentTalk}"/>
</event>
<event type="sendEmailConfirmation">
       <action execute="#{sendEmail.sendEmail}"/>
</event>

Enjoy this powerful feature in Seam.


  • Currently 5.0/5
  • 1
  • 2
  • 3
  • 4
  • 5
5.0 rating out of 1 votes

About Max Katz

Max Katz

Max Katz is a Senior Systems Engineer at Exadel. He has been helping customers jump-start their RIA development as well as providing mentoring, consulting, and training. Max is a recognized subject matter expert in the JSF developer community. He has provided JSF/RichFaces training for the past three years, presented at many conferences, and written several published articles on JSF-related topics. Max also leads Exadel's RIA strategy and writes about RIA technologies in his blog, http://mkblog.exadel.com. He is an author of "Practical RichFaces" book (Apress). Max holds a BS in computer science from the University of California, Davis.

More About Max »

NFJS, the Magazine

August Issue Now Available
  • Google Your Persistent Domain Model
    by John Griffin
  • Get Cooking in the Cloud with Chef, Part 2
    by Michael Nygard
  • Making Java Bearable with Guava
    by Daniel Hinojosa
  • HTML 5 Update
    by Brian Sletten
Learn More »