\
Donate profile for Rudi at Stack Overflow, Q&A for professional and enthusiast programmers

05/05/2016

2441 views

Event Driven Development in Java EE7


Two gold rings resting one against the other

I recently finished reading Arun Gupta's Java EE7 Essentials and I was struck by how many features of Java EE there are that I had no idea existed. Not least of all are the ways that Java EE enables event driven development through annotations. There are lots of situations that would have been easier and simpler had I known these features existed. As such, I thought I should spread the wealth and share what I have learnt.


A first class example of where these annotations could be extremely useful is in EJBs. Session beans can have @AroundConstruct, @PostConstruct, @PreDestroy, @PostActivate, and @PrePassivate annotations that mark a method to be called at certain stages of an EJBs life-cycle. Simply annotate a method in the bean with one of these and it will get called during the associated life-cycle event. Marvelous.



@Stateless
public class YourStatelessSessionBean {
    @PostConstruct
    public void foo(){
        // Called after the bean is constructed and
        // all its dependencies are injected.
    }
    @PreDestroy
    public void bar(){
        // Called when the container removes this bean.
    }
}


@PostActivate and @PrePassivate can only be used by stateful session beans. Stateful EJBs can be passivated when memory needs freeing up and can then be activated again when they are needed.


So what kind of problem can be solved by these annotations? Well, imagine you have a stateful bean that needs some initialisation before it's ready to use. Normally your constructor does this, but imagine you need to use some injected beans to initialise that content. Now you have a problem, because content isn't injected until after the constructor runs. Well, that's where @PostConstruct saves the day. Put your initialisation in there and it runs after the constructor and after injected objects are instantiated.


Seeing as I wasn't previously aware of event based annotations, I thought those were pretty cool. But what I thought were even cooler were the event callback annotations for JPA Entity objects. @PostLoad, @PrePersist, @PostPersist, @PreUpdate, @PostUpdate, and @PreRemove can be added to an entity method to be called when those events are fired. Want a document to always be sent off for indexing after it's been created? No problem, just add a method annotated @PostPersist and put your logic there to run after the entity is persisted.



@Entity
public class YourDocumentEntity {
    @Id
    private long id;
    // Getters and setters etc here.
    @PostPersist
    public void sendForIndexing(){
        // Called after your entity is persisted.
    }
    @PreRemove
    public void removeFromIndex(){
        // Called just before removing this entity from the database.
    }
}


What if you want some logic that runs after many different entity types are persisted? You don't want to have to annotate a method in every entity and repeat your logic over and over. No problem, declare your annotations against a completely separate non-Entity class. Then you can register this as the listener for your entities with a single annotation, like so;



@Entity
@EntityListeners(YourClassWithTheAnnotations.class)
public class YourDocumentEntity {
    @Id
    private long id;
    // Getters and setters etc here.
}


Events in Java EE aren't just about declaring listeners for existing pre-determined events though. If those weren't enough, you can define your own Events and their Observers and fire those Events yourself from any managed bean in the application. That fired Event can then be observed and dealt with in any manner you like. Your new event can just be defined as a standard POJO and then injected into a managed bean like so;



@Stateless
public class EventFiringBean {
    @Inject
    private Event<YourEvent> event;
    public void doStuff(){
        event.fire(new YourEvent("Your event fired!"));
    }
}

class YourEvent {
    private String message;
    public YourEvent(String message){
        this.message = message;
    }
    // Getters and setters go here!
}


So you have injected your event by declaring it as the generic type of an injected Event object. You can then use it to fire events by simply creating one of your new POJOs and passing it into a call to the event objects fire method. Now somewhere in another bean a method can observe this event firing. These two beans don't need any knowledge of each other. They're as loosely coupled as they get. To me, this feels incredibly powerful. You can define events and fire them from anywhere and then observe them from anywhere. All without tightly binding the communicating classes together.



public void beanMethod(@Observes YourEvent even) {
    // Called when a YourEvent event is fired.
}


You can even change the relationship that this receiving method has with the transaction of the method that fired the event. You can declare your @Observer annotation with a small hand full of parameters such as @Observer(during = TransactionPhase.AFTER_SUCCESS). This example specifies that the method should fire after the transaction of the firing method has completed successfully without rolling back. The default is @Observer(during = TransactionPhase.IN_PROGRESS) which causes the method to run immediately after the event has fired during the transaction.


Events in Java EE seem really useful and I will be looking forward to putting them to use. I hope this article has helped or given you some ideas for how you can put them to use yourself. If you have any feedback feel free to drop a comment in the comments below. Until next time, keep on reading.


Rudi Kershaw

Web & Software Developer, Science Geek, and Research Enthusiast