Giorgi Moniava Giorgi Moniava - 5 months ago 16
Java Question

Event received only by one bean? (despite having several ones)

I am confused with this. I created three instances of beans which should listen to events, but only one of them catches the event. Why? Please see code and output below. PS. new to spring.

Event handler class

package customevents.di;

import org.springframework.context.ApplicationListener;

public class CustomEventHandler implements ApplicationListener<CustomEvent> {

private static int ID = 0;

public CustomEventHandler() {
ID++;
System.out.println("Constructor called CustomEventHandler " + ID);

}

public void onApplicationEvent(CustomEvent event) {
System.out.println(event.toString() + " " + ID); // Prints My Custom event and ID
}

}


Publisher

package customevents.di;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

public class CustomEventPublisher implements ApplicationEventPublisherAware {

private ApplicationEventPublisher publisher;

public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {

this.publisher = publisher;
}

public void publish() {
CustomEvent ce = new CustomEvent(this);
publisher.publishEvent(ce);
}
}


Usage

public static void main(String[] args) {
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");

CustomEventPublisher cvp =
(CustomEventPublisher) context.getBean("customEventPublisher");

// Scope of these beans is prototype
CustomEventHandler ce = (CustomEventHandler) context.getBean("customEventHandler");
CustomEventHandler ce1 = (CustomEventHandler) context.getBean("customEventHandler");
CustomEventHandler ce2 = (CustomEventHandler) context.getBean("customEventHandler");

cvp.publish();

}


Output

Constructor called CustomEventHandler 1
Constructor called CustomEventHandler 2
Constructor called CustomEventHandler 3
Constructor called CustomEventHandler 4
My Custom Event 4


Why only one bean received the event?

PS. Adding beans file as requested.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="customEventHandler" class="customevents.di.CustomEventHandler" scope="prototype">
</bean>

<bean id="customEventPublisher" class="customevents.di.CustomEventPublisher">
</bean>

</beans>

Answer

UPDATE1:

Staphanee Nicoll has described in spring blog post as below:

The actual processing of the event will respect the semantics you set on your bean. So if you set prototype we are going to create a new instance of the bean for you prior to call the method on it. And we're going to do that for every event. If you expect all your existing prototype instances to be called for a particular event, that's not going to happen (we never did multicast an event and that infrastructure is not meant to do that).


You have missed to add cvp.publish() for calling every custom event handler.

Another issue static section is already described by costi-ciudatu

Hope it will work.

 public static void main(String[] args) {
      ConfigurableApplicationContext context = 
      new ClassPathXmlApplicationContext("Beans.xml");

      CustomEventPublisher cvp = 
      (CustomEventPublisher) context.getBean("customEventPublisher");

      // Scope of these beans is prototype
      // CustomEventHandler ce =  (CustomEventHandler) context.getBean("customEventHandler");
      // CustomEventHandler ce1 =  (CustomEventHandler) context.getBean("customEventHandler");
      // CustomEventHandler ce2 =  (CustomEventHandler) context.getBean("customEventHandler");

      for(int i=0; i<3; i++) {
          CustomEventHandler ce =  (CustomEventHandler) context.getBean("customEventHandler");
          cvp.publish();
      }
   }

For learning more, you can go through this tutorial: Custom events in spring

Github Resource Link:

Spring app event demo

Comments