Search This Blog

Service Locator Design Pattern in Java

The service locator design pattern is used when we want to locate various services using JNDI lookup. Considering high cost of looking up JNDI for a service, Service Locator pattern makes use of caching technique. For the first time, a service is required, Service Locator looks up in JNDI and caches the service object. Further lookup or same service via Service Locator is done in its cache which improves the performance of application to great extent The Service Locator Pattern is to transparently locate business components and services in a uniform manner.

Spring Framework internally uses Service Locator pattern to manage Dependency Injection.These days, Service Locator isn’t of much use anymore, except in very small proprietary projects. For the rest, use a good dependency injection framework like spring or guice.

Let's discuss how Service Locator Pattern transparently locates business components and services in a uniform manner.

Reading theory is always boring so maybe we can jump to source code section to understand this pattern step by step implementation.

This pattern is divided into a number of sections for simplicity like problem, forces, solution etc.

Table of contents

Problem

Forces

Solution

Structure - Class Diagram, Sequence Diagram

Participants and Responsibilities

Implementation

Consequences

Applicability

References

Problem

(Problem section describes the design issues faced by the developer)

You want to transparently locate business components and services in a uniform manner.

Forces

(This section describes Lists the reasons and motivations that affect the problem and the solution. The list of forces highlights the reasons why one might choose to use the pattern and provides a justification for using the pattern)

You want to use the JNDI API to look up and use business components, such as enterprise beans and JMS components, and services such as data sources.

You want to centralize and reuse the implementation of lookup mechanisms for J2EE application clients.

You want to encapsulate vendor dependencies for registry implementations and hide the dependency and complexity from the clients.

You want to avoid performance overhead related to initial context creation and service lookups.

You want to reestablish a connection to a previously accessed enterprise bean instance, using its Handle object.

Solution

Use a Service Locator to implement and encapsulate service and component lookup. A Service Locator hides the implementation details of the lookup mechanism and encapsulates related dependencies.

Application clients can reuse the Service Locator to reduce code complexity, provide a single point of control, and improve performance by providing a caching facility.

Structure

Let's use UML class diagram to show the basic structure of the solution and the UML Sequence diagram in this section present the dynamic mechanisms of the solution.

Below is the class diagram representing the relationships for the Service Locator pattern.

Class diagram

Sequence Diagram

Participants and Responsibilities

Client - Client represents a client of the Service Locator that needs to locate and access a component or service in the business or integration tier.

ServiceLocator - The ServiceLocator encapsulates the API lookup (naming) services, vendor dependencies, lookup complexities, and business object creation, and provides a simple interface to clients. This reduces the client’s complexity and increases reuse.

Cache - Cache represents an optional ServiceLocator to hold onto references that have been previously looked up. The sole purpose of using the Cache is to optimize the ServiceLocator by reducing redundant lookups.

InitialContext - The InitialContext object is the starting point in the lookup and creation process. Service providers provide the context object, which varies depending on the type of Target looked up by the ServiceLocator.

Target - Target represents the service or component, in the business or integration tiers, that the Client is looking up using the ServiceLocator.

RegistryService -RegistryService represents the registry implementation that holds the references to the services or components that are registered as service providers for Clients.

Implementation

(This section includes example implementations and code listings for the patterns and the strategies)

Let's create source code step by step with reference to the class diagram.

Step 1 : This is parent service interface which we will use to create our services. All services will have a service name, uniqueId, and execution workflow.

publicinterfaceService {
/* * The human readable name of the service*/StringgetName();
/* * Unique ID of the particular service*/intgetId();
/* * The workflow method that defines what this service does*/voidexecute();
}

Step 2: 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.

For JNDI lookup of services from the web.xml. Will match the name of the service name that is being requested and return a newly created service object with the name.

publicclassInitContext {
/** * Perform the lookup based on the service name. The returned object will need to be casted into a * {@link Service} * * @param serviceName a string * @return an {@link Object}*/publicObjectlookup(StringserviceName) {
if (serviceName.equals("jndi/serviceA")) {
System.out.println("Looking up service A and creating new service for A");
returnnewServiceImpl("jndi/serviceA");
} elseif (serviceName.equals("jndi/serviceB")) {
System.out.println("Looking up service B and creating new service for B");
returnnewServiceImpl("jndi/serviceB");
} else {
returnnull;
}
}
}

Step 4: Create Cache.

The service cache implementation which will cache services that are being created. On the 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.

Applicability

The service locator pattern is applicable whenever we want to locate/fetch various services using JNDI which, typically, is a redundant and expensive lookup.

The service Locator pattern addresses this expensive lookup by making use of caching techniques ie. for the very first time a particular service is requested, the service Locator looks up in JNDI, fetched the relevant service and then finally caches this service object. Now, further lookups of the same service via Service Locator is done in its cache which improves the performance of the application to a great extent.