diff --git a/pom.xml b/pom.xml
index 1e6b6e98c..1a0a0c9b7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
visitor
double-checked-locking
servant
+ service-locator
diff --git a/service-locator/etc/model.ucls b/service-locator/etc/model.ucls
new file mode 100644
index 000000000..bf17e5eba
--- /dev/null
+++ b/service-locator/etc/model.ucls
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service-locator/etc/service-locator.png b/service-locator/etc/service-locator.png
new file mode 100644
index 000000000..72016b972
Binary files /dev/null and b/service-locator/etc/service-locator.png differ
diff --git a/service-locator/pom.xml b/service-locator/pom.xml
new file mode 100644
index 000000000..a7cb56f8e
--- /dev/null
+++ b/service-locator/pom.xml
@@ -0,0 +1,9 @@
+
+ 4.0.0
+
+ com.iluwatar
+ java-design-patterns
+ 1.0-SNAPSHOT
+
+ service-locator
+
\ No newline at end of file
diff --git a/service-locator/src/main/java/com/iluwater/App.java b/service-locator/src/main/java/com/iluwater/App.java
new file mode 100644
index 000000000..9905b68df
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/App.java
@@ -0,0 +1,20 @@
+package com.iluwater;
+/**
+ * Service locator pattern, used to lookup jndi services
+ * and cache them for subsequent requests.
+ * @author saifasif
+ *
+ */
+public class App {
+ public static void main(String[] args) {
+ Service service = ServiceLocator.getService("jndi/serviceA");
+ service.execute();
+ service = ServiceLocator.getService("jndi/serviceB");
+ service.execute();
+ service = ServiceLocator.getService("jndi/serviceA");
+ service.execute();
+ service = ServiceLocator.getService("jndi/serviceA");
+ service.execute();
+ }
+
+}
diff --git a/service-locator/src/main/java/com/iluwater/InitContext.java b/service-locator/src/main/java/com/iluwater/InitContext.java
new file mode 100644
index 000000000..8c6e0f8d1
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/InitContext.java
@@ -0,0 +1,29 @@
+package com.iluwater;
+
+/**
+ * For JNDI lookup of services from the web.xml. Will match name of the service name that
+ * is being requested and return a newly created service object with the name
+ * @author saifasif
+ *
+ */
+public class InitContext {
+
+ /**
+ * Perform the lookup based on the service name. The returned object will need to be
+ * casted into a {@link Service}
+ * @param serviceName
+ * @return
+ */
+ public Object lookup(String serviceName){
+ if( serviceName.equals("jndi/serviceA") ){
+ System.out.println("Looking up service A and creating new serivce for A");
+ return new ServiceImpl("jndi/serviceA");
+ } else if( serviceName.equals("jndi/serviceB") ){
+ System.out.println("Looking up service B and creating new serivce for B");
+ return new ServiceImpl("jndi/serviceB");
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/service-locator/src/main/java/com/iluwater/Service.java b/service-locator/src/main/java/com/iluwater/Service.java
new file mode 100644
index 000000000..cda1a9d7e
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/Service.java
@@ -0,0 +1,29 @@
+package com.iluwater;
+
+/**
+ * This is going to be the parent service interface which we will
+ * use to create our services. All services will have a
+ * service name
+ * unique id
+ * execution work flow
+ * @author saifasif
+ *
+ */
+public interface Service {
+
+ /*
+ * The human readable name of the service
+ */
+ public String getName();
+
+ /*
+ * Unique ID of the particular service
+ */
+ public int getId();
+
+ /*
+ * The workflow method that defines what this service does
+ */
+ public void execute();
+
+}
diff --git a/service-locator/src/main/java/com/iluwater/ServiceCache.java b/service-locator/src/main/java/com/iluwater/ServiceCache.java
new file mode 100644
index 000000000..ec727126b
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/ServiceCache.java
@@ -0,0 +1,46 @@
+package com.iluwater;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The service cache implementation which will cache services that are being created.
+ * On first hit, the cache will be empty and thus any service that is being requested, will be
+ * created fresh and then placed into the cache map. On next hit, if same service name will
+ * be requested, it will be returned from the cache
+ * @author saifasif
+ *
+ */
+public class ServiceCache {
+
+ private Map serviceCache;
+
+ public ServiceCache() {
+ serviceCache = new HashMap();
+ }
+
+ /**
+ * Get the service from the cache. null if no service is found matching the
+ * name
+ * @param serviceName
+ * @return {@link Service}
+ */
+ public Service getService(String serviceName){
+ Service cachedService = null;
+ for (String serviceJndiName : serviceCache.keySet()){
+ if( serviceJndiName.equals( serviceName ) ){
+ cachedService = serviceCache.get(serviceJndiName);
+ System.out.println("(cache call) Fetched service " + cachedService.getName() + "("+cachedService.getId()+") from cache... !");
+ }
+ }
+ return cachedService;
+ }
+
+ /**
+ * Adds the service into the cache map
+ * @param newService
+ */
+ public void addService(Service newService){
+ serviceCache.put(newService.getName(), newService);
+ }
+}
diff --git a/service-locator/src/main/java/com/iluwater/ServiceImpl.java b/service-locator/src/main/java/com/iluwater/ServiceImpl.java
new file mode 100644
index 000000000..335ebef78
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/ServiceImpl.java
@@ -0,0 +1,37 @@
+package com.iluwater;
+
+/**
+ * This is a single service implementation of a sample service. This is the actual
+ * service that will process the request. The reference for this service is to
+ * be looked upon in the JNDI server that can be set in the web.xml deployment descriptor
+ * @author saifasif
+ *
+ */
+public class ServiceImpl implements Service {
+
+ private String serviceName;
+ private int id;
+
+ public ServiceImpl(String serviceName) {
+ // set the service name
+ this.serviceName = serviceName;
+
+ // Generate a random id to this service object
+ this.id = (int)Math.floor(Math.random()*1000)+1;
+ }
+
+ @Override
+ public String getName() {
+ return serviceName;
+ }
+
+ @Override
+ public int getId() {
+ return id;
+ }
+
+ @Override
+ public void execute() {
+ System.out.println("Service " + getName() + " is now executing with id " + getId());
+ }
+}
diff --git a/service-locator/src/main/java/com/iluwater/ServiceLocator.java b/service-locator/src/main/java/com/iluwater/ServiceLocator.java
new file mode 100644
index 000000000..e2fbae2b8
--- /dev/null
+++ b/service-locator/src/main/java/com/iluwater/ServiceLocator.java
@@ -0,0 +1,37 @@
+package com.iluwater;
+
+/**
+ * The service locator module.
+ * Will fetch service from cache, otherwise creats a fresh service and update cache
+ *
+ * @author saifasif
+ *
+ */
+public class ServiceLocator {
+
+ private static ServiceCache serviceCache = new ServiceCache();
+
+ /**
+ * Fetch the service with the name param from the cache first,
+ * if no service is found, lookup the service from the {@link InitContext} and
+ * then add the newly created service into the cache map for future requests.
+ * @param serviceJndiName
+ * @return {@link Service}
+ */
+ public static Service getService(String serviceJndiName){
+ Service serviceObj = serviceCache.getService(serviceJndiName);
+ if ( serviceObj != null ){
+ return serviceObj;
+ } else {
+ /*
+ * If we are unable to retrive anything from cache, then
+ * lookup the service and add it in the cache map
+ */
+ InitContext ctx = new InitContext();
+ serviceObj = (Service) ctx.lookup(serviceJndiName);
+ serviceCache.addService(serviceObj);
+ return serviceObj;
+ }
+ }
+
+}