SOA and Reference Data


  • What is the best way to handle exposing refernce data in a Service Oriented Architecture?


    For example, I'm creating a service that has a method which takes parameters such as Gender, Marital Status, and so on.  In our database, this information is all stored in lookup tables that are in the form of Id, Description (ex. 1: Male, 2:Female).  Should I be exposing the IDs that are mapped to the database records as my request parameters (so making the gender parameter GenderId)? In that case, should I be exposing another function called GetGenders to provide a list of gender Ids that should be used by whoever is calling the service?  In that case though, Gender is not really something that belongs to this service and can also be used in the future by other services. I have about 15 fields that are following this approach, which all need to be passed in to my main service function in order for the business logic to do the proper calculations.  And some of the lists are very large lookup lists (such as a listing of different vehicle makes, models, submodels).  What's the best way to handle this situation and make it flexible enough for external business partners and other services to easily communicate with our service and reference the lookup values?





    Friday, April 20, 2007 7:23 PM

All replies

  • I have a similar problem and while I don’t claim to have the correct answer, I’ll share with you an approach I’ve taken.


    If the reference data is small or constant then I prefer to use an Enumeration ( Some examples of constant reference data are States, Gender (Male, Female, Unknown), Days of the week, etc. You may also have business reference data like DocumentType, LoanProduct, etc.


    A few problems with Enumerations:

    - You cannot represent parent/child relationships

    - I believe you need a custom serializer if your Enumeration values have spaces (ex: “Commercial Loan”)

    - If your Enumeration values change, consumers may need to regenerate proxy classes (a.k.a Versioning issues)


    In general, I use ComplexTypes and expose “Get” operations/methods for the consumer to retrieve the reference data. Additionally, I never expose the reference data “ID’s” only the reference data values. The reference data ID’s have no meaning to the consumer. Finally, I always validate the incoming request and appropriately cache the reference data.


    As an example, I have a Document Management web service that exposes a Search operation/method. The search operation/method accepts a SearchCriteria request and responds with a collection of DocumentInfo types. Below is SearchCriteria schema that contains a few reference data types. One reference type is LineOfBusiness. LineOfBusiness contains about 100+ values that may change frequently. The corresponding “Get” operation/method is “GetLineOfBusiness” that returns a collection of LineOfBusiness types. The consumer can now populate SearchCriteria with an appropriate LineOfBusiness by calling the “GetLineOfBusiness” operation/method. Find the LineOfBusiness in the collection they want to search and send the SearchCriteria request to the web service. 


    On the server tier, I validate the LineOfBusiness value against a LineOfBusiness collection (which is usually cached), retrieve the "ID" from my collection and pass it to the Data tier to execute the appropriate stored procedure. 


    - Dave


    Code Snippet

                searchCriteria = new SearchCriteria();


                LineOfBusiness lob = new LineOfBusiness();

                lob.Name = service.GetLineOfBusiness()[3];

                searchCriteria.LineOfBusiness = lob;


    DocumentInfo[] response =service.Search(searchCriteria);


          <s:complexType name="SearchCriteria">


              <s:element minOccurs="0" maxOccurs="1" name="DocumentIdList" type="tns:ArrayOfDecimal" />

              <s:element minOccurs="0" maxOccurs="1" name="FileNetId" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="CustomerName" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="NaicsCode" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="DocumentStatus" type="tns:DocumentStatus" />

              <s:element minOccurs="0" maxOccurs="1" name="Description" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="DocumentType" type="tns:DocumentType" />

              <s:element minOccurs="0" maxOccurs="1" name="SsnTaxId" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="GlobalCustomerId" type="s:string" />

              <s:element minOccurs="0" maxOccurs="1" name="LineOfBusiness" type="tns:LineOfBusiness" />

              <s:element minOccurs="1" maxOccurs="1" name="FromDate" type="tns:SmartDate" />

              <s:element minOccurs="1" maxOccurs="1" name="ToDate" type="tns:SmartDate" />






          <s:complexType name="LineOfBusiness">


              <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />





    Saturday, April 21, 2007 4:42 PM