Friday, October 28, 2022

Spring - Event Handling

  • In general, in GUI Applications, when we click on a button, when select an item in check boxes, radio buttons, List boxes, choice boxes ... automatically an event will be rised, where the generated event will not be handled by the respective GUI components, where the generated events are handled by some component internally called as "Listeners"[Handlers]
  • In Event Handling, the main intention of Listeners is to listen the events rised by the GUI Components, handle that events and generating results back to the GUI Applications.
  • Similarily, in spring applications, IOC Container is able to rise events when it was started, refreshed, stopped and closed. In this context, to handle the generated events Spring Framework has provided "Event Handling".

  • In Spring Framework, Event Handling capability is available with Application Context only, not with BeanFactory. In Spring Framework Event Handling all events are represented in the form of predefined classes in "org.springframework.context.event"  package like below.

    • 1.ContextRefreshedEvent 
    • 2.ContextStartedEvent 
    • 3.ContextStoppedEvent 
    • 4.ContextClosedEvent 
    • 5.RequestHandledEvent

  • Where ContextRefreshedEvent will be rised when we start ApplicationContext or when we access "refresh()" method on ApplicationContext.
  • Where ContextStartedEvent will be rised when we access "start()" method on ApplicationContext.
  • Where ContextStoppedEvent will be rised when we access "stop()" method on ApplicationContext.
  • Where ContextClosedEvent will be rised when we access "close()" method on ApplicationContext.
  • Where RequestHandledEvent will be rised in web applications when request is handled in Spring web applications.
  • To Handle all the above Events, Spring Framework has provided a Listener in the form of "org.springframework.context.ApplicationListener" interface and it is having the following to execute when the respective event is rised.

    • public void onApplicationEvent(XXXEvent e)

Note: 

  • ApplicationListener is able to listen all the events bydefault, if we want to filter the events then we have to provide the respective Event type as Generic parameter.
  • ApplicationListener<ContextStartedEvent> is able to listen only ContextStartedEvent .
In Spring applications, if we want to implement event handling then we have to use the following steps.

  • Create implementation classes for ApplicationListener interface and provide implementation for onApplicationEvent(--) method.
  • Configure all implementation classes as bean components in spring configuration file.

Note: 

  • To perform Event Handling in spring applications we have to use "org.springframework.context.ConfigurableApplicationContext" container , it is a chaild interface to ApplicationContext interface.

Example:

ContextRefreshedListenerImpl.java

package com.cloud.listeners;
import org.springframework.context.ApplicationListener; 
import org.springframework.context.event.ContextStartedEvent;

public class ContextStartedListenerImpl implements 
	ApplicationListener<ContextStartedEvent>{

    @Override
    public void onApplicationEvent(ContextStartedEvent e) {
        System.out.println("Application Context Started...."); 
    }
}


ContextStoppedListenerImpl.java

package com.cloud.listeners;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;

public class ContextStoppedListenerImpl implements ApplicationListener<ContextStoppedEvent>{
	@Override
	public void onApplicationEvent(ContextStoppedEvent e) {
		System.out.println("Application Context Stopped"); 
	}
}

HelloBean.java

package com.cloud.beans; 

public class HelloBean {
	private String uname;
	
	public String getUname() {
		return uname; 
	}
	
	public void setUname(String uname) {
		this.uname = uname; 
	}
	
	public String wish(){
		return "Hello "+uname+"!"; 
	}
}


applicationContext.xm

<beans>
	<bean id="helloBean" class="com.cloud.beans.HelloBean">
		<property name="uname" value="cloud"/> 
	</bean>
	<bean id="contextRefreshedEvent" class="com.cloud.listeners.ContextRefreshedListenerImpl"/> 
	<bean id="contextStartedEvent" class="com.cloud.listeners.ContextStartedListenerImpl"/> 
	<bean id="contextStoppedEvent" class="com.cloud.listeners.ContextStoppedListenerImpl"/> 
	<bean id="contextClosedEvent" class="com.cloud.listeners.ContextClosedListenerImpl"/>
</beans>

Test.java

package com.cloud.test;
import com.cloud.beans.HelloBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args)throws Exception {
		ConfigurableApplicationContext context=
			new ClassPathXmlApplicationContext("applicationContext.xml");
		
		HelloBean hello=(HelloBean)context.getBean("helloBean"); 
		System.out.println(hello.wish());
		
		context.start();
		context.refresh();
		context.stop();	
		context.close(); 
	}
}.


Custom Events in Spring Applications:

  • Custom Events are user defined events which are defined by the developers as per their application requirements.
  • To manage custom Events in Spring applications we have to use the following steps.
    • 1.Create User defined Event class
    • 2.Create User defined event Publisher class
    • 3.Create Event Handler class
    • 4.Configure Event Publisher class and Event Handler class in spring configuration file.
    • 5.Create Bean components as per the appl requirements and publish events 6.Create Test application and Execute Test application.

 1.Create User Event Class:

  • Declare an user defined class.
  • Extend org.springframework.context.ApplicationEvent abstract class to defined class.
  • Declare public and Object parameterized Constructor and access super parameterized constructors by using "super" keyword.
  • Define other methods as per the requirement in Event class.

2.Create User defined event Publisher class

  • The main intention of event publisher class is to publish the user defined event inorder to handle.
  • Steps:
    • Declare an user defined class.

    • Implement org.springframework.context.ApplicationEventPublisherAwareinterface in event class.

    • Provide implementation for setApplicationEventPublisher(--) method inorder to inject ApplicationEventPublisher object.
      • The main intention to implement ApplicationEventPublisherAware interface is to inject ApplicationEventPublisher object only.

    • Define a method to publish an event by using the following method from ApplicationEventPublisher .

      • public void publishEvent(ApplicationEvent ae)

3.Create User defined Event Handler Class:

  • The main intention of User defined Event Handler class is to handle the user defined Events.
  • Steps:
    • Create an User defined class
    • Implement org.springframework.context.ApplicationListener interface.
    • Implement onApplicationEvent(--) Method in user defined class with an application logic.

Note

  • onApplicationEvent(--) method is able to take the parameter which is specified as generic type to ApplicationListener interface.
  • Note: By default, Listeners are able to handle all the Listeners, but, if we want to filter the Listeners then we have to use Generic type to ApplicationListener
  • In Spring Event Handling, bydefault, ApplicationContext is able to handle the events synchronously, but, if we want to handle the events Asynchronously then we have to use ApplicationEventMustcaster interface.
  • Spring4.2 version has provided very good annotations support for Event Handling in the form of the following Annotations. 
    • @EventListener({Event1.class,Event2.class...})

      • Where Event1.class, Event2.class,... are Event class types wich we want to process.
      •  EX:@EventListener({ContextRefreshedEvent.class,ContextStoppedEvent.class}) 

    • @Async() : 

      • It will be used to prcess events asynchronously.

4)Prepare Bean components and publish events:

  • In the application, as per the requirement we are able to publish the events by using publishEvent(--) method.

AccountEvent.java

error.eid.invalid=Invalid Employee Id.
error.ename.empty=Employee Name is required. 
error.esal.invalid=Employee Salary is Invalid.
error.eage.minage=Employee Age must not be less than 18 years. 
error.eage.maxage=Employee Age must not be greater than 30 years.
error.eemail.empty=Employee Email Id is required.
error.eemail.invalid=Employee Email Id is Invalid.
error.emobile.empty=Employee Mobile is required. 
error.emobile.invalid=Employee Mobile is Invalid.

AccountEventPublisher.java


package com.cloud.events;

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

public class AccountEventPublisher implements ApplicationEventPublisherAware{ private ApplicationEventPublisher publisher;

@Override

public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {

this.publisher=publisher; }

public void publish(String message){

AccountEvent ae=new AccountEvent(this, message);

publisher.publishEvent(ae); }

}


AccountEventHandler.java

package com.cloud.events;
import java.io.FileOutputStream;
import java.util.Date;
import org.springframework.context.ApplicationEvent;

public class AccountEvent extends ApplicationEvent{ 
	static FileOutputStream fos;
	
	static{
		try {
			fos=new FileOutputStream("E:/logs/log.txt", true);
		} catch (Exception e) {
			e.printStackTrace(); }
		}

	private String message;
	
	public AccountEvent(Object obj, String message) {
		super(obj);
		this.message=message; 
	}

	public void generateLog(){ 
		//System.out.println("********"+message+"*******"); 
		try {
			message=new Date().toString()+":"+message; message=message+"\n";
			byte[] b=message.getBytes();
			fos.write(b);
		} catch (Exception e) {
			e.printStackTrace(); }
		} 
	}
}

AccountEventHandler.java

package com.cloud.events;
import org.springframework.context.ApplicationListener;
public class AccountEventHandler implements ApplicationListener<AccountEvent> {
	@Override
	public void onApplicationEvent(AccountEvent e) {
		e.generateLog(); 
	}
}

AccountEventHandler.java

package com.cloud.events;
import org.springframework.context.ApplicationListener;
public class AccountEventHandler implements ApplicationListener<AccountEvent> {
	@Override
	public void onApplicationEvent(AccountEvent e) {
		e.generateLog(); 
	}
}

Account.java

package com.cloud.beans;
import com.cloud.events.AccountEventPublisher;

public class Account {

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

	public void createAccount(){ 
		System.out.println("Account Created");
		publisher.publish("AccountCreated"); 
	}

	public void searchAccount(){ 
		System.out.println("Account Identified");
		publisher.publish("AccountIdentified"); 
	}

	public void updateAccount(){ 
		System.out.println("Account Updated");
		publisher.publish("AccountUpdated"); 
	}

	public void deleteAccount(){ 
		System.out.println("Account Deleted");
		publisher.publish("AccountDeleted");
	}
}

applicationContext.xml

<beans>
	<bean id="account" class="com.cloud.beans.Account">
		<property name="publisher" ref="accountEventPublisher"/> 
	</bean>
	<bean id="accountEventHandler" class="com.cloud.events.AccountEventHandler"/>
	<bean id="accountEventPublisher" class="com.cloud.events.AccountEventPublisher"/> 
</beans>

Test.java

package com.cloud.test;
import com.cloud.beans.Account;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; 

public class Test {
	public static void main(String[] args)throws Exception { 
		ConfigurableApplicationContext context=new

		ClassPathXmlApplicationContext("applicationContext.xml"); 
		Account account=(Account)context.getBean("account"); 
		account.createAccount();
		account.searchAccount();
		account.updateAccount();
		account.deleteAccount(); 
	}
}



You may also like

Kubernetes Microservices
Python AI/ML
Spring Framework Spring Boot
Core Java Java Coding Question
Maven AWS