Adsense-HeaderAd-Script


Advertisement #Header

2 Jul 2014

Event Handling in Java using Spring Framework



For Handling of Events, there are first 3 core things that is necessary.
  1. Event
  2. Event Publisher
  3. Event Listener
Luckily in Spring Framework there is support for handling events.

In this blog, we will try 3 different ways to implement event handling using Spring. First from simple direct usage of Spring  and then to a method where the business logic is decoupled from direct Spring usage.


Method 1 : Simple Direct Usage of Spring Framework

 

 Event


Using Spring Framework ApplicationEvent  we will create a OfferEvent class.
package com.test2;

import org.springframework.context.ApplicationEvent;

public class OfferEvent  extends ApplicationEvent{

       private static final long serialVersionUID = 3029215982265408049L;

       public OfferEvent(Object source) {
              super(source);
              // TODO Auto-generated constructor stub
       }
      
       public String toString(){
              return "OfferEvent2";
       }
      

}

Event Publisher


Using ApplicationEventPublisherAware  Interface we will be able to set the ApplicationEventPublisher from the Spring Context to publish our events.

package com.test2;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

public class Service implements ApplicationEventPublisherAware {

   private ApplicationEventPublisher publisher;

  //implemented method
   public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
      this.publisher = applicationEventPublisher;
  }

   public void service(){
      OfferEvent event = new OfferEvent(this); 
      this.publisher.publishEvent(event);
  }
}

Event Listener


Using ApplicationListener of Spring Framework, we can listen to ApplicationEvents and perform actions when an event occurs.

package com.test2;

import org.springframework.context.ApplicationListener;

public class OfferEventListener implements ApplicationListener<OfferEvent> {

   //implemented method
   public void onApplicationEvent(OfferEvent event) {
     System.out.println("OfferEvent received =" + event.getClass()
        + "\n At =" + event.getTimestamp()
        + "\n Source =" + event.getSource().getClass()
        + "\n Msg =" + event.toString() );
   }

}

Main application

package com.test2;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

  public static void main(String[] args)
  {
   AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("springbeanconfig02.xml");
   Service serv = (Service)ctx.getBean("ServiceBean");
   serv.service();

   ctx.registerShutdownHook();
  }
}
 

 Spring Bean XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<bean id="ServiceBean" class="com.test2.Service"></bean>

<bean class="com.test2.OfferEventListener"></bean>

</beans>


Issue 


In this implementation the  ApplicationEvent  dependency is hardcoded into Service class which means  for this Service to use any different type of ApplicationEvent we have to rewrite the code. We can solve this using next Method.


Method2: Injecting ApplicationEvent Dependency using Spring


In Service class using setEvent we will inject ApplicationEvent from a Spring XML bean configuration.
package com.test3;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

 public class Service implements ApplicationEventPublisherAware {

  private ApplicationEventPublisher publisher;
  private ApplicationEvent event;

  public void setEvent(ApplicationEvent event) {
    this.event = event;
  }

  //implemented method
  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    this.publisher = applicationEventPublisher;
  }
  public void service(){
    this.publisher.publishEvent(this.event);
  }

}
 

 Spring Bean XML 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

 <bean id="ServiceBean" class="com.test3.Service">
   <property name="event">
        <ref bean="OfferEventBean" />
      </property>
 </bean>

 <bean id="OfferEventBean" class="com.test3.OfferEvent">
    <constructor-arg>
        <ref bean="ServiceBean" />
    </constructor-arg>
 </bean>

 <bean class="com.test3.OfferEventListener"></bean>
 
</beans>
 

 Issue

 In this implementation, the main business class Service is directly dependent on Spring ApplicationEventPublisherAware interface, ApplicationEventPublisher, and ApplicationEvent. So the issue is it would be difficult to change in future if we wish to use any other tool or framework. We can solve this using the next method.

Method3: Event Handling without Business Logic having Direct Dependence on Spring


Inorder to Decouple the Business Logic class from  the Spring framework, first we will create our version of ApplicationEvent.
package com.test4;

import org.springframework.context.ApplicationEvent;

public abstract class MyAppEvent extends ApplicationEvent{
   private static final long serialVersionUID = -6092666752131453519L;

   public MyAppEvent(Object source) {
       super(source);
   }
}
 
 Now for every ApplicationEvents which we wish to create we will extend that from MyAppEvent.

package com.test4;

public class OfferEvent extends MyAppEvent{
   private static final long serialVersionUID = -2857555740801485476L;

     public OfferEvent(Object source) {
        super(source);
  }

  public String toString(){
       return "OfferEvent4";
  }
}

 We will also create a our version of ApplicationEventPublisher.
package com.test4;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

public class MyAppEventPublisher implements ApplicationEventPublisherAware{
   private ApplicationEventPublisher publisher;
     public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){
        this.publisher = applicationEventPublisher;
   }

     public void publishEvent(ApplicationEvent event ) {
        this.publisher.publishEvent(event);
   }
}
 
 Now in our Business Logic Service class, we have freed it from any direct dependence on Spring framework.
package com.test4;

public class Service {

   private MyAppEvent event;
     private MyAppEventPublisher publisher;

     public void setEvent(MyAppEvent event) {
        this.event = event;
   }

     public void setPublisher(MyAppEventPublisher publisher) {
        this.publisher = publisher;
   }

   public void service(){
        this.publisher.publishEvent(this.event);
   }
}


Using Spring XML configuration we will inject the properties MyAppevent and MyAppEventPublisher to the Service class
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

 <bean id="ServiceBean" class="com.test4.Service">
    <property name="event">
       <ref bean="OfferEventBean" />
    </property>
    <property name="publisher">
       <ref bean="MyAppEventPublisherBean" />
    </property>
 </bean>

 <bean id="OfferEventBean" class="com.test4.OfferEvent">
    <constructor-arg>
       <ref bean="ServiceBean" />
    </constructor-arg>
 </bean>

 <bean class="com.test4.OfferEventListener" />

 <bean id="MyAppEventPublisherBean" class="com.test4.MyAppEventPublisher"/>

</beans>

No comments:

Post a Comment