An Example of a Loan Processing Service Using Globus Toolkit for Grid Services

1. Introduction

The article illustrates the use of the Open Grid Services Infrastructure (OGSI) software model. A simple application from the Mortgage Industry dealing with Loan Payment Processing is used as an example to show how using the Globus toolkit (GT3.2) can transparently offer a new way of deploying software within a corporation. Every month, a mortgage borrower remits a principal and interest payment based on the loan's amortization schedule. The Unpaid Principal Balance (UPB) of a loan is reduced by the scheduled principal payment amount, principal prepayment amount, and curtailment amount. Different services in a Mortgage Finance corporation will need access to this information. A typical example is the accounting resulting for the loan activity. This article will take the reader through a full implementation of a very simple Loan Processing Service using the Globus toolkit. The example simulates creating a loan, accepting principal payments for the loan, and querying the state of the loan. Although this is a very simple example, it can be extended to implement complex calculations or business scenario using the Globus toolkit.

You use the Top-Down Approach [1] to create the Grid Service. This approach starts by providing a GSWDL file that contains the abstract definition of the service including the types, message, and portType parts of WSDL. Using the tools that come with the GT3 installation generates the binding and service part. The next step with this approach is to provide the implementation of the interfaces. This article assumes familiarity with the concepts of Grid computing and Web services (see References for more information).

2. Port Type and Type Interfaces

These port types are defined in a file, loan.gwsdl. It describes the three operations: createLoan, processLoanPayment, and getLoan that the Loan Processing Service will provide:

Listing 1: loan.gwsdl file

   <xsd:element name="createLoan">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="loanNumber" type="xsd:int"/>
            <xsd:element name="amountUPB" type="xsd:double"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>
   <xsd:element name="createLoanResponse">
      <xsd:complexType>
         <xsd:sequence>
           <xsd:element name="returnValue" type="xsd:int"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>

   <xsd:element name="processLoanPayment">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="loanNumber" type="xsd:int"/>
            <xsd:element name="amount" type="xsd:double"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>
   <xsd:element name="processLoanPaymentResponse">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="returnValue" type="xsd:int"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>


   <xsd:element name="getLoan">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="loanNumber" type="xsd:int"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>
   <xsd:element name="getLoanResponse">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="returnValue" type="domain:LoanType"/>
         </xsd:sequence> 
      </xsd:complexType>
   </xsd:element>

</xsd:schema>
</types>

<message name="CreateLoanInputMessage">
   <part name="parameters" element="tns:createLoan"/>
</message>
<message name="CreateLoanOutputMessage">
   <part name="parameters" element="tns:createLoanResponse"/>
</message>

<message name="ProcessLoanPaymentInputMessage">
   <part name="parameters" element="tns:processLoanPayment"/>
</message>
<message name="ProcessLoanPaymentOutputMessage">
   <part name="parameters" element="tns:processLoanPaymentResponse"/>
</message>

<message name="GetLoanInputMessage">
   <part name="parameters" element="tns:getLoan"/>
</message>
<message name="GetLoanOutputMessage">
   <part name="parameters" element="tns:getLoanResponse"/>
</message>

<gwsdl:portType name="LoanPortType" extends="ogsi:GridService">
   <operation name="createLoan">
      <input message="tns:CreateLoanInputMessage"/>
      <output message="tns:CreateLoanOutputMessage"/>
      <fault name="Fault" message="ogsi:FaultMessage"/>
   </operation>
   <operation name="processLoanPayment">
      <input message="tns:ProcessLoanPaymentInputMessage"/>
      <output message="tns:ProcessLoanPaymentOutputMessage"/>
      <fault name="Fault" message="ogsi:FaultMessage"/>
   </operation>
   <operation name="getLoan">
      <input message="tns:GetLoanInputMessage"/>
      <output message="tns:GetLoanOutputMessage"/>
      <fault name="Fault" message="ogsi:FaultMessage"/>
   </operation>

</gwsdl:portType>

Additionally, you provide a loan.xsd file that defines the Loan Type that is used as a business object.

Listing 2: Loan Type schema file

<complexType name="LoanType">
   <sequence>
      <element name="loanNumber" type="int"/>
      <element name="UPB" type="double"/>
      <element name="status" type="string"/>
      <element name="createDate" type="string"/>
   </sequence>
</complexType>

An Example of a Loan Processing Service Using Globus Toolkit for Grid Services

3. Grid Directory Structure

You will assume throughout this article that the Globus toolkit software is installed in a separate directory than where you are doing your implementation. %GLOBUS_LOCATION will refer to this installation directory. The following directory structure is used for the Loan Processing example:

Table 1: Directory structure of the implementation

Directory Path Description
/loan Home directory of the implementation
/loan/schema/loan Schema path for the gswdl and xsd types files
/loan/src/loan/impl Implementation files

The two descriptor files, mortgage.gwsdl and loan.xsd, are stored under /loan/schema/loan.

4. Service Implementation

In the previous step, the LoanPortType endpoint interface was generated. All remotely available operations must be public and throw java.rmi.RemoteException as defined in the PortType interface.

The Loan Service implementation of the LoanPortType interface inherits from the GridServiceImpl class provided by the Globus framework and implements the OGSI defined GridService interface, along with other core Grid service behavior.

public class LoanServiceImpl extends GridServiceImpl
   implements LoanPortType {

The LoanServiceImpl class implement the methods defined in the LoanPortType interface:

public int createLoan(int loanNumber, double amountUPB)
   throws java.rmi.RemoteException{

   // Create the loan
   LoanType loan = new LoanType();

   loan.setLoanNumber(loanNumber);
   loan.setUPB(amountUPB);
   loan.setStatus("ACTIVE");
   loan.setCreateDate((new Date()).toString());

   loanActivity.put(new Integer(loan.getLoanNumber()), loan);

   return loanNumber;
}

public int processLoanPayment(int loanNumber, double amount)
   throws java.rmi.RemoteException{

   LoanType loan = (LoanType)
      loanActivity.get(new Integer(loanNumber));

   if (loan == null)
      return 0;

   System.out.println("Found loan " + loanNumber);

   // Update UPB
   loan.setUPB(loan.getUPB() - amount);

   // Change the status if the loan is paid off
   if (loan.getUPB() == 0)
      loan.setStatus("PAIDOFF");

   loanActivity.put(new Integer(loanNumber), loan);

   return loanNumber;
}


public LoanType getLoan(int loanNumber)
   throws java.rmi.RemoteException{

   LoanType loan = (LoanType) loanActivity.get(new Integer(loanNumber));
   if (loan == null){
      System.out.println("===> Loan " + loanNumber + " not found");
   }
   return loan;
}

An Example of a Loan Processing Service Using Globus Toolkit for Grid Services

5. Client Implemetation

try {
   LoanServiceLocator loanLocator = new LoanServiceLocator();
   OGSIServiceGridLocator gridLocator = new OGSIServiceGridLocator();
   GridService gridService =
      gridLocator.getGridServicePort(new HandleType(args[0]));
   LoanPortType loanPT =
      loanLocator.getLoanPort(gridLocator.getEndpoint());

   if (args[1].equalsIgnoreCase("createLoan")) {
      amount = Double.parseDouble(args[3]);
         System.out.println("Loan " + loanPT.createLoan(
            loanNumber, amount) + " created successfully.");
   }else if (args[1].equalsIgnoreCase("processLoanPayment")) {
      amount = Double.parseDouble(args[3]);
         System.out.println("Loan " + loanPT.processLoanPayment(loanNumber,
            amount) + " processed successfully.");
   } else if (args[1].equalsIgnoreCase("getLoanData")) {
      LoanType loan = loanPT.getLoan(loanNumber);
         System.out.println("Loan Data ");
         System.out.println("  Create Date " + loan.getCreateDate());
         System.out.println("  Unpaid Principal Balance " + loan.getUPB());
         System.out.println("  Status " + loan.getStatus());
   }
} catch (Exception e) {
   e.printStackTrace();
}

6. Build and Deployment

An ant build.xml file located in the /loan home directory is created. It uses the following tasks: (Note: Tll these tasks call gt3 tasks available in the build.xml that comes with the gt3 distribution.)

Generate WSDL from GWSDL

<target name="generateWSDL" depends="setenv">

   <ant antfile="${build.services}" target="GWSDL2WSDL">
      <property name="build.schema.dir" value="loan"/>
      <property name="wsdl.root" value="loan_port_type"/> 
   </ant>
   <ant antfile="${build.services}" target="generateBinding">
      <property name="binding.root" value="loan"/>
      <property name="build.schema.dir" value="loan"/>
      <property name="porttype.wsdl" value="loan_port_type.wsdl"/>
   </ant>
</target>

Generate Stubs from WSDL

<target name="stubs" unless="stubs.present"
        depends="setenv, generateWSDL">
   <ant antfile="${build.services}" target="generateStubs">
      <property name="schema.file.dir" value="loan"/>
      <property name="schema.file" value="loan_service.wsdl"/>
   </ant>
   <ant antfile="${build.services}" target="generateStubs">
      <property name="schema.file.dir" value="loan"/>
      <property name="schema.file" value="loan.xsd"/>
   </ant>
</target>

During the setup, it is important to provide a property file that maps the different namespaces to the packages that corresponds to your directory structure in Table 1.

Please refer to the full build.xml for the comple list of ant build tasks.

A deployment descriptor, loan-config.wsdd, located in the home directory, is created.

<service name="test/loan/LoanFactoryService" provider="Handler"
         style="wrapped">
   <parameter name="name" value="WSDL Loan Factory"/>
   <parameter name="instance-name" value="WSDL Loan"/>
   <parameter name="instance-schemaPath"
              value="schema/loan/loan_service.wsdl"/>
   <parameter name="instance-baseClassName"
              value="grid.loan.impl.LoanServiceImpl"/>
   <parameter name="persistent" value="true"/>
   <parameter name="schemaPath"
              value="schema/ogsi/ogsi_notification_factory_service.wsdl"/>
   <parameter name="baseClassName"
              value="org.globus.ogsa.impl.ogsi.GridServiceImpl"/>
   <parameter name="handlerClass"
              value="org.globus.ogsa.handlers.RPCURIProvider"/>
   <parameter name="className"
              value="org.gridforum.ogsi.NotificationFactory"/>
   <parameter name="allowedMethods" value="*"/>
   <parameter name="factoryCallback"
              value="org.globus.ogsa.impl.ogsi.DynamicFactoryCallbackImpl"/>
   <parameter name="operationProviders"
              value="org.globus.ogsa.impl.ogsi.FactoryProvider org.
                     globus.ogsa.impl.ogsi.NotificationSourceProvider"/>
</service>

Please refer to the loan-config.wsdd file for the complete configuration.

An Example of a Loan Processing Service Using Globus Toolkit for Grid Services

7. Testing the Loan Processing Example

  • Start the grid by calling:
    $GLOBUS_LOCATION/bin/globus-start-container
    to start a grid service container
  • Create a Loan Processing service instance by calling
    $GLOBUS_LOCATION/bin/ogsi-create-service
       http://localhost:8080/ogsa/services/test/loan/
              LoanFactoryService
    

    The factory service name test/loan/LoanFactoryService must be the same name as defined in loan-config.wsdd.

    Once the service is created successfully, a handle is returned; for example,

    Handle: http://localhost:8080/ogsa/services/test/loan/
                   LoanFactoryService/hash-8454539-1110606241421
    
  • To test the service using the client, consider the following scenario example:

    A loan with loan number 1001 is initially created with a UPB (unpaid principal balance) of 350,000.00. Two payment of 2,500.00 are made towards the reduction of the UPB. (No interest calculations are considered in this example for the sake of simplicity and clarity.) At this point, the status of the loan is viewed. The remaining UPB is then paid off, and the loan status shows that it is paid off.

    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
       createLoan 1001 350000.00
    Loan 1001 created successfully.
    
    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
       processLoanPayment 1001 2500.00
    Loan 1001 processed successfully.
    
    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
        processLoanPayment 1001 2500.00
    Loan 1001 processed successfully.
    
    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
       getLoanData 1001
    Loan Data
       Create Date Sat Mar 12 16:48:37 EST 2005
       Unpaid Principal Balance 345000.0
       Status ACTIVE
    
    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
        processLoanPayment 1001 345000.00
    Loan 1001 processed successfully.
    
    java loan.impl.Client http://68.100.194.114:8080/ogsa/services/test/
       loan/LoanFactoryService/hash-8454539-1110606241421
       getLoanData 1001
    Loan Data
       Create Date Sat Mar 12 16:48:37 EST 2005
       Unpaid Principal Balance 0.0
       Status PAIDOFF
    

8. Conclusion

This article introduces the basic architecture and programming concepts used by the Globus GT3 software through a simple business example. It demonstrates a pratical way to use the core capabilities of GT3. It does not discuss the more advanced concepts around the grid advanced services, notification, and security. These advanced features will be covered in subsequent articles.

References

  1. Java Programmer's Guide Core Framework, Globus GT3.2 Documentation
  2. OGSI WG and Specification are available at http://www.gridforum.org/ogsi-wg/.
  3. OGSA Architecture documents can be seen at http://www.ggf.org/ogsa-wg/.
  4. Globus Toolkit 3.2.1 Download can be gotten at http://www-unix.globus.org/toolkit/downloads/3.2.1/
  5. Apache AXIS documents are available at http://ws.apache.org/axis/.


About the Author

Birali Hakizumwami

Application Architect. Interests include grid computing, neural networks, autonomous computing.

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds