Wednesday, May 1, 2013

Factory pattern in Spring


Recently, I was working on a requirement to send notifications via email and sms in my project. My initial design was to have a common interface (NotificationService) with these methods - sendNotification and validateRequest. Both the SmsNotifier and EmailNotifier would implement the interface NotificationService and access to the notification interface would be through a rest end point (post).


And since I’d auto wired dependencies in the Resource class, I’d to figure out a way to inject implementations dynamically. So, I opted for a factory pattern design. This is a straight forward requirement but let’s see how to achieve this with spring.

package com.spring.prototype.service;

public interface NotificationService {
 String sendNotification();
}

@Component("email")
public class EmailNotificationService implements NotificationService {

 public String sendNotification() {
  return "Send notifications via email";
 }

}

package com.spring.prototype.service;

import org.springframework.stereotype.Component;

@Component("sms")
public class SmsNotificationService implements NotificationService {

 public String sendNotification() {
  return "Send notifications via sms";
 }

}

Solution: ServiceLocatorFactoryBean which takes two inputs
serviceLocatorInterface – which is responsible for creating classes based on the input
mappings – which maps names to actual implementations.

Add these configurations in the context xml.
Autowire factory class instead of the interface and let the input decide which implementation to choose.

<beans:bean
  class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"
  id="printStrategyFactory">
  <beans:property name="serviceLocatorInterface"
   value="com.spring.prototype.factory.NotificationFactory">
  </beans:property>
  <beans:property name="serviceMappings">
   <beans:props>
    <beans:prop key="email">email</beans:prop>
    <beans:prop key="sms">sms</beans:prop>
   </beans:props></beans:property>
</beans:bean>


Resource Class:
------------------

@Component
@Path("/notification")
@Produces(MediaType.TEXT_PLAIN)
public class NotificationResource {

 @Autowired
 NotificationFactory factory;

 @POST
 @Path("{type}")
 public String sendNotification(@PathParam("type") String type) {
  return factory.getNotificationService(type).sendNotification();
 }

}

Full project is available on github.

Note: You would actually end up writing a lot more code to send mail/sms. This post deals only with implementing a factory pattern in Spring and autowiring dependencies. Let me know what you think.
 
Happy coding :)

~ cheers.!

No comments:

Post a Comment