About Me
Facebook
Facebook
Linked In
Linked In
Twitter
Twitter
YouTube
YouTube
Google +
Google +

Thursday, April 17, 2014

Design Blueprint to implement a lightweight ESB

Introduction

This article introduces a design blueprint for implementing a homegrown, lightweight Enterprise Service Bus (ESB) that leverages commonly used Integrated Development Environments (IDEs) and middleware. The scenario uses IBM® WebSphere® Application Server V8, a robust deployment environment for Java EE applications, and IBM Rational® Software Architect, which provides tooling to design, develop, test, and package Java EE applications for deployment to an application server.

Business scenario Challenge

In order to meet business demands, a service provider is required to deliver multiple releases of its application within a year. Each release results in updating the existing service contract and deploying a new version of the web service into a production environment.

The most cost-effective solution would typically be a single instance of the service deployed in production to reduce maintenance costs. However, due to budget restrictions or maintenance schedules, service consumers are not always in a position to adopt new versions as soon as they are released. This scenario forces the service provider to host multiple versions of the service to support client needs.

Solution
WebSphere Enterprise Service Bus (WebSphere ESB) and WebSphere DataPower® Appliances both provide robust ESB capabilities that enable dynamic routing and transformation of requests between service consumers and providers. These capabilities enable the decoupling of service consumers from the instance of the service that processes the request. By leveraging an ESB, service providers can honor multiple service contracts without hosting multiple instances of the service in production.
When only a subset of the capabilities provided in WebSphere ESB and WebSphere DataPower are required, customers have the option of building lightweight ESB capabilities into their Java EE applications to meet their project-specific needs.

Blueprint for implementing a lightweight ESB:

A blueprint for implementing a lightweight ESB should consist of several layers to handle the different functions needed to receive, route, transform, and respond to requests from a client. The blueprint outlined in this article includes the following four layers:
Ø  Routing Layer -- A Java API for RESTful Web Services (JAX-RS) RESTful endpoint for URL pattern matching and request routing.
Ø  Mediation Layer -- Mediation and mapping modules for managing requests at the data content level between a client and a specific service version.
Ø  Service Invocation Layer -- Manager for the services contract that builds the required request, invokes a physical service endpoint, and returns the content with the response.

Ø  Multi-Protocol Listener Layer -- A listener service such as WebSphere MQ, Java Message Service (JMS), or another service for non-JAX- RS client applications to participate in the lightweight ESB.

Templates and guidelines for implementation

The following sections provide details about the templates and guidelines for each layer in the blueprint.

Routing Layer

The Routing Layer is the entry point into the lightweight ESB. The primary purpose of the Routing
Layer is to provide clients with well-known service endpoints and routing of client requests to the appropriate mediation logic. In doing so, the Routing Layer decouples the service consumers from the physical location of the service provider's endpoint.
The solution template provided for the Routing Layer is a JAX-RS RESTful web service. This layer intercepts client requests and reroutes them, based on URL, to the appropriate Mediation Layer entry point. Below Figure shows the following functions of the Routing Layer:
Ø  Two service consumers -- MyService version A client and MyService version B client -- which use different URLs when invoking the ESB.
Ø  Routing components for MyService version A client and MyService version B client which route requests based on URL to the appropriate mediation component.
The JAX-RS Routing Layer provides two URLs – one for MyService version A clients and one for MyService version B clients. Each URL refers to a method in the URL Routing Resource class that handles the routing of the client request to the appropriate mediation logic:
URL Routing Resource class
public class URL_Routing_Resource {
    private URLRouterImpl urlRouterImpl = new URLRouterImpl();
    // Constructor
    public URL_Routing_Resource() {}
    @GET
    @Path (value="myService/versionA/")
    @Produces("application/xml")
    public Response invokeMyServiceVersionA(String payload)
    {
        String content = null;
        System.out.println("");
        content = urlRouterImpl.myServiceVersionA(payload);
        return Response.ok(content).build();
    }
    @GET
    @Path (value="myService/versionB/")
    @Produces("application/xml")
    public Response invokeMyServiceVersionB(String payload)
    {
        String content = null;
        System.out.println("");
        content = urlRouterImpl.myServiceVersionB(payload);
        return Response.ok(content).build();
    }
    @GET
    @Path (value="otherService/versionX/")
    @Produces("application/xml")
    public Response invokeOtherServiceVersionX(String payload)
    {
        String content = null;
        System.out.println("");
        content = urlRouterImpl.otherServiceVersionX(payload);
        return Response.ok(content).build();
    }
 }
Listener Layer (optional)
The Listener Layer is an optional component of the blueprint and is dependent on the need for batch or non-HTTP type interfaces. The primary purpose of the Listener Layer is to provide ESB access to a broader range of clients that leverage common non-HTTP based transport mechanisms, such as WebSphere MQ, JMS, File Transfer Protocol (FTP), and Remote Method Invocation (RMI). You can create the Listener Layer to intercept an inbound non-HTTP request, build an HTTP request from the incoming data, invoke the Routing Layer via HTTP, and build a non-HTTP client response. Technologies to implement the Listener Layer can include an MQ Listener, JMS Listener, FTP Listener, or EJB Listener. Figure 3 shows the following functions of the Listener Layer:

Ø  Two non-HTTP clients -- An MQ service consumer for MyService version A client, and an FTP service consumer for MyService version B client.
Ø  Two Listener Layer mapping modules that map the incoming request to an HTTP JAX- RS request and invoke the Routing Layer. In addition, the response is also mapped as required by the client and the appropriate response returned to the client.

Mediation Layer

The Mediation Layer serves as the central data content mapping point for all incoming and outgoing service requests. The primary purpose of the Mediation Layer is to provide mapping capabilities between client-aware versions of a service and physical service endpoint versions. In addition, the Mediation Layer ensures that adequate data-related content required by a specific service version is present prior to calling the Service Invocation Layer.

The solution template provided for the Mediation Layer leverages Java classes to programmatically determine a service version, and perform inbound mapping to fill in missing data content required to call a physical service endpoint. This layer invokes the Service Invocation layer and performs outbound-related mapping for the client-specific response based on version. The Mediation Layer could also use XSLT or other mapping technologies or products, such as WebSphere Transformation Extender, to provide data content mapping. Figure 4 shows the following functions of the Mediation Layer:
Ø  An inbound mapping module for clients of MyService that supports versions A and B.
Ø  An outbound mapping module for clients of MyService that supports versions A and B.
Ø  An additional example of a mapping module for clients that would support multiple versions of a future service (depicted as OtherService).
The Mediation Layer provides an invocation entry point for MyService (version A clients and version B clients), in addition to an entry point for OtherService. The Invoke method uses the incoming service name to call the service-specific mediation logic:
Invoke method in Mediation Layer
/*
 * Entry point into Mediation Layer for all services
 */
    public MediationObject invoke(MediationObject mo)
    {
        if(mo.getServiceName().equalsIgnoreCase("myService"))
            return invokeMyService(mo);
        else if(mo.getServiceName().equalsIgnoreCase("otherService"))
            return invokeOtherService(mo);
        else
            return null;
    }
The logic within the service-specific mediation determines which version of client made the request, and executes mapping logic to transform the incoming message content prior to passing the message to the Service Invocation Layer. When the response is returned from the Service Invocation Layer, outbound mapping logic is performed to transform the message content into the format expected by the requesting client:
Mediation logic for MyService
/*
 * Mediation logic for MyService
 */
    private MediationObject invokeMyService(MediationObject mo)
    {
        Mapper mapper = new Mapper();
        MediationObject outgoingMO = new MediationObject();
        // 1. Determine service version
        if (mo.getVersion().equalsIgnoreCase("A"))
        {
        // 2. Invoke the Mapping Layer to perform any required outbound mapping
            ServiceInvocationObject sio =  mapper.serviceRequestMapper(mo);
        // 3. Call the Invocation Layer to physically invoke the service
            InvocationLayer invoke = new InvocationLayer();
            ServiceInvocationResponse sir = invoke.callService(sio);
        // 4. Invoke the Mapping Layer to perform any required inbound mapping
            outgoingMO = mapper.serviceResponseMapper(sir);
        }
        else
            if(mo.getVersion().equalsIgnoreCase("B"))
            {
                // Repeat Steps 2 - 4 above
            }
            else
                return null;
        return outgoingMO;
    }
Service Invocation Layer
The Service Invocation Layer serves as the entry point for calling a physical service. The primary purpose of the Service Invocation Layer is to implement the client code to invoke a physical service endpoint. The Service Invocation Layer takes the data content from the Mediation Layer and constructs the request required by the physical service endpoint. The physical service is then invoked, and the Service Invocation Layer constructs a response object that is returned to the Mediation Layer.
The solution template provided for the Service Invocation Layer leverages Java classes to implement the client code, which constructs the service endpoint request from the data content provided by the Mediation Layer. This Layer constructs the physical service request object, invokes the physical service endpoint, and converts the response object back to the format required by the Meditation Layer. Figure 5 shows the following functions of the Service Invocation Layer:
Ø  A module to construct the request object, invokes the physical service endpoint, and converts the response to the format required by the Mediation Layer.
Ø  An additional example of a module to construct the request object, invoke the physical service endpoint, and convert the response to the format required by the Mediation Layer for a future service (depicted as Other Service).
The Service Invocation Layer provides an invocation entry point for MyService and an entry point for OtherService. The callService method uses the incoming service name to call the service-specific invocation logic:
The callService method in the Service Invocation Layer
/*
 * Entry point for Service Invocation Layer
 */
    public ServiceInvocationResponse callService(ServiceInvocationObject sio)
    {
        if(sio.getServiceName().equalsIgnoreCase("myService"))
            return callMyService(sio);
    else if(sio.getServiceName().equalsIgnoreCase("otherService"))
            return callOtherService(sio);
        else
            return null;
    }
The logic within the Service Invocation Layer determines which version of a service is being requested by a client, constructs the endpoint-specific request, submits the request to the endpoint, and then converts the endpoint response to the format expected by the Meditation Layer:
/*
 * Service Invocation logic for myService
 */
    private ServiceInvocationResponse callMyService(ServiceInvocationObject sio)
    {
        ServiceInvocationResponse sir = new ServiceInvocationResponse();
        // 1. Build physical service endpoint specific object from SIO payload
        // 2. Call physical service endpoint
        // 3. Build SIR payload from endpoint specific response object
        // 4. Return SIR to Mediation Layer
        return sir;
    }
Conclusion
This article introduced a design blueprint for implementing a homegrown, lightweight ESB. The blueprint consists of four layers that outline the different functionalities needed to receive, route, transform, and respond to requests from a client. To illustrate the use of the blueprint, the article described a business scenario and provided code templates and guidelines for implementing a lightweight ESB. You can use this article to design and implement your own lightweight ESB to meet your specific project requirements.
Downloads
       File Name   
      Description
      Size
      Download
      Design blueprint to implement a lightweight ESB
      Document
      480 KB
      Download

0 comments :

Post a Comment

Designed By AMEER BASHA G