Saturday 16 September 2017

Spring bean post processors

BeanPostProcessor interface allows you to execute some code or perform some action on the bean before its initialization callbacks (afterPropertiesSet method of InitializingBean interface or method specified in init-method attribute is called) and after its initialization callbacks have executed.



Spring provides 28 implementations out of the box for BeanPostProcessors that handle standard functions like autowiring, applying AOP advice. So it is highly unlikely that you would be creating your own post processor. Instead you would be using 1 available out of the box. You would be using them indirectly by using standard spring features such as applying validation annotations on a method parameter which applies MethodValidationPostProcessor, or making method calls @Async which applies AsyncAnnotationBeanPostProcessor.

Here is a brief overview of the bean lifecycle.

  1. Create the bean instance either by a constructor or by a factory method.
  2. Set the values and bean references to the bean properties.
  3. Call the setter methods defined in the all the aware interfaces. (setBeanFactory() method for beans implementing BeanFactoryAware interface, setApplicationContext() method for beans implementing ApplicationContextAware interface.)
  4. Pass the bean instance to the postProcessBeforeInitialization() method of each bean post processor.
  5. Call the initialization callback methods.
  6. Pass the bean instance to the postProcessAfterInitialization() method of each bean post processor.
  7. The bean is ready to be used.
  8. When the container is shut down, call the destruction callback methods. (destroy() method of the DisposableBean interface method specified in destory-method attribute of bean declaration)

This post tries to give you a feel of BeanPostProcessor.
 We will be using Java configuration to create beans.
@Configuration
@ComponentScan(basePackages= {"com.rizwan.test.spring_bean_postprocessor_demo"})
public class AppConfig {

    @Bean(initMethod="init", destroyMethod="destroyMethod")
    public EmployeeDAO employeeDAO() {
       
        return new EmployeeDAO();
    }
 }
In the @Bean annotation above, initMethod specifies method name that must be called after creating a new instance of that. It will be called after bean has been instantiated and initialized. destroyMethod gives the name of method that will be called when container is shutdown. It can contain code that will allow us to free resources held by the bean.
Let us create a dummy bean which implements InitializingBean, DestroyableBean. This will allow us to see in exactly what sequence are all these methods called.
public class EmployeeDAO implements InitializingBean, DisposableBean {

    public void afterPropertiesSet() {
   
        System.out.println("Inside after properties set of InitializatingBean");
    }
   
    public void destroy() {
       
        System.out.println("Destroy method of Disposable bean");
    }
   
    // Check if init method can return value
    public void init() {

        System.out.println("Init method of EmployeeDAO");
    }

    public void destroyMethod() {

        System.out.println("Destroy method of EmployeeDAO");
    }

    public String getEmployeeName(String empId) {
         //for simplicity let me return a fixed string regardless of the empId passed in.
        return "Rizwan";
    }
}
Here is out CustomBeanPostProcessor.
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) {
      
        System.out.println("Post processing bean with name " + beanName + " before initialization.");
        return bean;
    }
  
    public Object postProcessAfterInitialization(Object bean, String beanName) {
      
        System.out.println("Post processing bean " + beanName + " after initialization");
        return bean;
    }
  
}
Please note that it must be declared as a @Component for spring to apply it to beans or it you need to a  bean of that type in AppConfig class.
public static void main( String[] args )
    {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        @SuppressWarnings("unused")
        EmployeeDAO employeeDAO = context.getBean(EmployeeDAO.class);
        context.close();
    }
Output:
Post processing bean with name employeeDAO before initialization.
Inside after properties set of InitializatingBean
Init method of EmployeeDAO
Post processing bean employeeDAO after initialization
Destroy method of Disposable bean
Destroy method of EmployeeDAO
Output clearly indicates that InitializingBean and DisposableBean interfaces are applied before init-method and destroy-method respectively.
Please note that the CustomBeanPostProcessor was applied to all the beans including AppConfig and an internalEventListenerProcessor created by Spring. For simplicity I have included output only for the employeeDAO.
Hope my post helps someone. Happy learning :)

Tuesday 18 July 2017

Communication between POJOs in Spring / Event publishing mechanism in Spring.



Sometimes we want beans to be able to communicate among themselves. This is typically done by Sender bean having access to Receiver bean, and then sender sends a message to receiver by using the reference to the receiver. This creates a tight coupling between sender and receiver. Sender is aware of the receiver. 


When using IoC POJOs can communicate by interface than by implementation. This model helps reduce coupling. However it is efficient only when the sender has to communicate with 1 receiver. When the sender has to communicate with multiple receivers it has to call the receivers 1 by 1. 


In Spring 1 component can send a message to another component by publishing an event without knowing who the receiver is. Receiver is also not aware of the sender. Receiver typically listens to an event. It can listen to multiple events from different senders. In this way, sender and receiver are loosely coupled.


First you must create an event, by extending ApplicationEvent class. It is an abstract class to prevent instantiation thus disallowing clients to create instances of ApplicationEvent class, prohibiting them from publishing generic event. Spring notifies a listener of all events, so you must filter the events yourself. If you use generics then Spring delivers the message to listener that listens specifically that event.



Create and event by extending ApplicationEvent class. Give it a constructor that accepts an object that describes the event and pass that object to super class ApplicationEvent. Application class is abstract and does not have default constructor, so subclasses are forced to provide a 1 or more arg constructor.



public class CheckoutEvent extends ApplicationEvent
{
    private Date checkoutTime;
    public CheckoutEvent(Object source, Date checkoutTime)
    {
        super(source);
        this.checkoutTime = checkoutTime;
    }
     //… some more code specific to the event
}

Create an event publisher by implementing ApplicationEventPublisherAware interface. It is the interface to be implemented by any object that wishes to be notified of the ApplicationEventPublisher (typically the ApplicationContext) that it runs in. ApplicationEventPublisher encapsulates the even publishing mechanism.


In the event publisher method just create the event and publish it by using calling publishEvent(event) on applicationEventPublisher instance.

@Component(value = "checkoutEventPublisher")
public class CheckoutEventPublisher implements ApplicationEventPublisherAware
{
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
    {
        this.applicationEventPublisher = applicationEventPublisher;
    }
    public void checkout(Object shoppingCart)
    {
        System.out.println("Checking out");
        CheckoutEvent checkoutEvent = new CheckoutEvent(shoppingCart, new Date());
        applicationEventPublisher.publishEvent(checkoutEvent);
    }
}

Create a listener  by implementing ApplicationListener interface and overriding onApplicationEvent(ApplicationEvent) method. Add the code for processing the event in it.

You must create a bean for the listener, else it won’t be notified.



Generic listener (Can listen to only 1 event)
As of Spring 3.0, an ApplicationListener can generically declare the event type that it is interested in. When registered with a Spring ApplicationContext, events will be filtered accordingly, with the listener getting invoked for matching event objects only.
@Component
public class CheckoutEventListener implements  ApplicationListener<CheckoutEvent>
{
    @Override
    public void onApplicationEvent(CheckoutEvent checkoutEvent) {
       
        System.out.println("Checkout event occured at " + checkoutEvent.getCheckoutTime());
    }
}

Raw listener(Can listen to several events from several publishers, so you need to check the type of event first before handling it)

@Component
public class CheckoutEventListener implements  ApplicationListener
{
    @Override
    public void onApplicationEvent(ApplicationEvent event)
    {
        if(event instanceof CheckoutEvent)
            System.out.println("Checkout event occured at " + ((CheckoutEvent)event).getCheckoutTime());
    }
}

Tuesday 11 July 2017

Today I was working on a new project in which the persistence layer was based on Hibernate 3.6.3. Was using maven for managing the dependencies.
When I ran the code, I got the error, Caused by: java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
    ...
    at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:77)
    ... 16 more
Caused by: java.lang.ClassNotFoundException: javassist.util.proxy.MethodFilter
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    ... 21 more

Solution is to add the maven dependency for javassist.
       <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.22.0-CR1</version>
        </dependency>
 
I started thinking why does Hibernate need javassist. BTW javassist is a library which simplifies Java bytecode manipulation. But why does hibernate need to manipulate Java bytecode. Googled a bit and realized that, Hibernate uses proxies to intercept method invocation on entities to implement lazy loading. Lazy loading is loading objects from the database upon first access.