Best-of-Both-Worlds Remote Services with Spring HTTP Invoker

emoting is an essential component of enterprise distributed computing. A service or class you call from within the same server (Java virtual machine) doesn’t need to be exposed as a remote service, but if you need to communicate with an external program (on a different server or in a different organization), it has to be implemented as a remote service. The Spring framework provides a unique and flexible way of exposing business classes as remote services.

At the heart of the Spring remoting architecture are service objects, which are POJOs also known as Spring beans. The Spring framework insulates these service objects from infrastructure details, such as how they are exposed as remote services, so the developer can concentrate on the business interface of the service object rather than getting bogged down with these details.

This remoting model provides remote abstraction to business services. It takes care of marshalling and unmarshalling method arguments and also handles any exceptions thrown in the service methods, wrapping them with unchecked RemoteAccessException. To implement a variety of services, Spring uses several design patterns. For example, it uses the proxy design pattern to translate your calls to HTTP POST requests to the URL pointing to the exported service.

This article explains how to implement a remote service using Spring. It demonstrates using the Spring Remoting API to convert a plain old Java object (POJO) into a remote service, which external programs can call for its business function. The demonstration uses a sample loan-processing application to implement a business service as a remote HTTP service and invoke the business methods in the class from a test client.

How Does Spring Remoting Work?
Let’s take a closer look at how the Spring remoting mechanism works. It provides the following elements to implement a Java class as a remote service:

  1. Remote Service Exporters ? These classes are used to create the remote service end-points for the client programs to call. Service exporters also manage any registries to look up the remote services.
  2. Proxy Factory Beans ? These are the factory classes used to create proxies that clients can use to connect to the remote services.
  3. HTTP Invoker ? As previously mentioned, Spring HTTP invoker employs a remoting model that you can use to make remote calls across HTTP and at the same time pass Java objects using Java serialization techniques. It makes implementing a remote service from a plain Java class a lot easier, and allows you to concentrate on the business interface of the remote service rather than remoting infrastructure details. It relies on the infrastructure of RMI invokers, but uses HTTP as the transport protocol.

On the client side, Spring HTTP invoker provides two types of clients: the standard API provided by Java SE and the Commons HttpClient API. By default, it uses HttpClient.

See Sidebar 1. Supported Remoting Technologies for a full listing of available remoting technologies for Spring.

Real-World Remoting Application
Let’s start the discussion of the sample application with a list of design goals:

  • Interface-based design: An interface-based design frees the clients from needing to know the implementation details of the remote service. The implementation can change without any modifications in the client code.
  • Test-driven development: All components in the application should be testable outside the container. The example will use JUnit to write simple unit tests to verify the design of each class as you write the code.
  • Layered architecture: A layered architecture provides loose coupling, isolation, and flexibility. A typical J2EE application has layers such as user interface (UI), application (or controller), domain (domain model or service), and infrastructure. The sample application has controller, service, and domain layers.
  • Separation of concerns: Since the remoting function has nothing to do with the business service, the separation of concerns plays an important role in implementing the service.
  • Lightweight services: The example uses the Spring HTTP Invoker API to implement the remote service. HTTP invoker is very lightweight compared with other component models.
  • Non-intrusive: Spring is an excellent framework for having a non-intrusive API in business applications. Using techniques such as Aspects and AOP, and design patterns such as Inversion of Control (IoC), Proxy, and Factory patterns, you can encapsulate the implementation details of a business task in the service class and expose only the interface to the clients.
  • Other than these goals, the example also follows an Agile software development approach in designing and coding the classes for the sample application (click here to download the source code).

    Business Requirements
    Now that you know the design goals of the application, let’s discuss the actual business requirements. The sample application is a loan-processing system (loanapp) that customers use to submit applications for home mortgage loans. The business use case for the remoting example is to process the flood certification check for a specified home property. A flood certification check is required for every home loan application to ensure the property is not located in a flood zone. If it is in a flood zone, the homeowner is required to obtain flood insurance by paying a “813 Fee” (813 is the code used to identify the flood certification fee).

    Flood maps refer to areas of high, medium, or low risk as “flood hazard zones” and the zones of highest risk as “special flood hazard areas”. The properties in high flood risk zones (AE, A, or AO zones) have a one percent chance of flooding in any year and a 26 percent chance of flooding over the life of a 30-year mortgage. Real estate properties in VE or V zones (also high risk) have a one percent chance of flooding in any year and also face hazards associated with coastal storm waves. And the homes in low or moderate flood risk zones (B or C zones) are outside the high-risk zones, where the flood risk is reduced but not removed.

    The flood certification check is triggered once the borrower has completed the home loan application and selects an interest rate for the loan amount. A flood check is required before the loan processing and underwriting phases of the mortgage process can begin.

    Use Case
    Here are the steps involved in the flood certification check use case:

    1. The customer completes the loan application, entering details such as borrower name, property name, property address, city, zip code, and loan amount.
    2. The user selects a loan product and interest rate and locks the loan for a specific period of time (e.g., 30 or 45 days).
    3. The loanapp program calls a flood certification check based on the property details, such as the address and zip code.
    4. Based on the client’s property zip code, the flood service determines if the specified property is in a flood zone and if it requires flood certification (This call is synchronous, so the client will wait for the response from the service before continuing with the loan application process).
    5. Once the flood check request comes back, the loan is submitted to an automated underwriting system (AUS) to get the credit history of the borrower as well as the risk assessment of the loan application.

    Technical Design
    Following the agile development process, the next step is a technical design for the requirements defined. The example uses the following design (classes and methods) to accomplish the requirements in the use case:

    1. The client class (FloodCertClient) calls the requestFloodCheck() method in the flood controller class (FloodCertController).
    2. The controller then calls the processFloodCheck() method in the service (FloodCertService) by sending the loan details in the HTTP request.
    3. The flood service calls the FloodDAO class to access the back-end database and check if the specified property needs the flood certification.
    4. The DAO returns a result object with the flood certification results, which is passed to the client to display on the Web page.

    Since remote services act as the entry points into the business domain model of an enterprise, the design of the service layer as a whole also is very important. Following are some of the general considerations you need to keep in mind when designing remote services:

    1. Remote call type (Should the remote call be stateless or stateful?)
    2. Remote call invocation type (Is the call synchronous or asynchronous?)
    3. Client type (Java, .NET, or some other type of client)
    4. Operating system (Windows, Unix, or another OS)
    5. Transactions (Do you need the remote service to be transactional so any database or JMS queue updates made in the service method are committed or rolled back as a single unit of work.)

    To fulfill all the requirements for the use case, the sample loan processing application will use the following technologies and frameworks:

    • Tomcat 5.5
    • Spring 2.0
    • JUnit
    • Commons HttpClient
    • Eclipse
    • Ant

    Spring Configuration
    The HTTP invoker remoting example uses two configuration XML files that define the Spring beans for the classes you wrote to implement the flood remote service: loanapp-servlet.xml and loanapp-client.xml.Implementation
    Following are the steps for implementing a remote service for the sample loan-processing application with the HTTP invoker:

    1. Create a HTTP invoker service exporter class (HttpInvokerServiceExporter).
    2. Create a HTTP proxy (using HttpInvokerProxyFactoryBean). You specify parameters like serviceUrl and serviceInterface in this class.
    3. Define a URL mapping for the clients to call the remote HTTP service.
    4. Configure the Spring beans in the loanapp-servlet.xml file.
    5. Configure the Spring Web layer (DispatcherServlet) in web.xml file.
    6. Write the client class (using HTTP or Commons HttpClient).
    7. Write a JUnit test case to call the method in the client class.

    Testing
    The source code download contains a JUnit test client (FloodCertClientTest) to test the client class calling the flood remote service. It calls the client with several different test loan applications for properties with different zip codes. Based on the property zip code submitted, the flood service returns the results of the flood certification analysis.

    Best-of-Both-Worlds Remoting
    Spring remoting offers a simple and flexible solution for exposing business domain services as remoting services. It also provides the flexibility of exposing the same service under multiple protocols (at different URLs, of course). For example, you can implement the flood certification check service in the sample application as a RMI service (for Java clients to take advantage of the faster Java-to-Java remoting), as well as a HTTP service for non-Java clients. This way, you would write the business service logic in only one place but expose the service as two remote service endpoints.

    The HTTP invoker framework provides the necessary proxies with plain Java service interfaces and a consistent usage and configuration style for implementing Java classes as remote services. This solution presents a best-of-both-worlds remoting solution that combines the simplicity of HTTP communication with Java’s built-in object serialization. This makes HTTP invoker a great alternative to either RMI or Hessian/Burlap.

    HTTP invoker’s one significant limitation is that it is offered only by the Spring framework. This means that both the client and the service applications must be implemented using Spring. But it is a good choice when you need a lightweight, easy-to-setup, and flexible remoting solution.

    Share the Post:
    Share on facebook
    Share on twitter
    Share on linkedin

    Related Posts