Search  
Tuesday, December 02, 2008 ..:: MINA's Blog ::.. Register  Login
 SiteMap Minimize

    

 Blog_List Minimize

      

 New_Blog Minimize

    

   Minimize
Keystroke IT

    

 Sample Adaptors and Configuration Minimize
Location: BlogsMINA's BlogSOA and ESB.NET    
Posted by: Minas Casiou 3/17/2004
An example of an adaptor and relevant configuration...

To help you get started with ESB.NET, both from the point of view of verifying the deployment as well as to help you get started adding your own services, there's a test adaptor that ships with ESB.NET.

Steps required to implement a service

After defining our service, there are 3 main items we need to do to setup our service with ESB.NET

  1. Prepare a Request to send to the service. This is done using any text editor or XSD tool such as Turbo XML, XMLSpy, BizTalk XML Editor etc.
  2. Create an adaptor and handler - or just add a new handler to an existing adaptor. This is done by creating an assembly implementing a specific interface (IProcessMsg).  This can be done by either:
    • writing code - where you code up the logic in VB.NET or C# etc.
    • configuring in one of the WWF Adaptor handlers and implementing the functionality using WWF assemblies - by using WWF to build the functionality and deploy the
  3. Configure the handler to handle a particular request (map request to handler). This is done using the InteropPipelineCfg.xml config file.

The ESB.NET Test Adaptor

The test adaptor is a basic one, and is written directly in code using VB.NET. It's purpose is to do nothing much other than get any old message to the service bus, have it routed to a handler and get a response back. It is configured in a few ways to test various basic functions of the ESB.NET service bus. As such, the message is minimalist in nature.

 

1. Request Message

Navigate to:

...\5.0\5.0.1.0\Source\ESB\Base\Solutions\Main\Management\ESB.Management.Portal\Testing\XMLRequests\ESBCore

and view the file called:

   ESBTest1_Sync.xml

It looks somethng like this:


  1. <xml version="1.0" encoding="utf-8" ?>
  2. <ESBEnvelope xmlns="urn:keystroke-com-au:ESB:Envelope:ESBEnvelope:Version:1-0-3">
  3.  <header> <delivery><senderMessageID /><receiverMessageID /><sent /> <callSynchronizationType>0<callSynchronizationType> <delivery>
  4. <manifest>
        <document>
            <name>BuildCmd2<name>
            <description>Test Document<description>
            <documentNamespace>urn:schemas-biztalk-org:biztalk:BuildCmd2:BuildCmd2<documentNamespace>
      <document>
    <manifest>
  5.  <systems> <system><adminID /><systemID>Some System ID<systemID> <service><name />  <version />  <context /> <description>Test Servicedescription> service>
  6.  header>
  7.  <body>
  8.        <documentBody>

               <BuildCmd2 xmlns="urn:schemas-biztalk-org:biztalk:BuildCmd2:BuildCmd2">
        <BuildCmdString>0<BuildCmdString>
          <BuildCmd2>
       <documentBody>
<body>
ESBEnvelope>


Not all fields are mandatory. In the XML Fragment above, you can see the ESBEnvelope and various header fields.

The most interesting parts are the manifest and the body. The manifest lists the contents of the message, inline XML documents, and any attachments that are transported outside of the ESB Envelope - such as DIME or MTOM etc. or may just be URL's.

The body section contains the core service request data. A similar ESBEnvelope will be used for the response.

In the above case, the document is called: BuildCmd2 (remnants from an remotely operated & automated build process... :) ). It has only one parameter, being the BuildCmdString. This example does not contain much service data as it's for testing core functionality. In general, the body will contain XML data conforming to an XSD, and may be a few hundred lines long. Bigger amounts of XML data, eg, MBytes or hundreds of KBytes, are best included as attachments, so as to minimise handling of large data. For example, handling employee contributions for a superannuation fund, which may contain say, 10MBytes of XML data, is best treated as an attachment, with an inline document specifying any general information about the attachment, as pertaining to the business function. This improves system performance, and also makes it clear as to the business service that is being executed.

 

2. Adaptor and Handler

Navigate to the following directory in the ESB build.

...\5.0\5.0.1.0\Source\ESB\Base\Solutions\Main\Testing\ESB.Testing.TestTxn

Here you'll find a Service Adaptor (ESB.Testing.TestTxn) containing 2 handlers (TestTxn1.vb and ReturnSpecifiedFileHandler.vb).

These 2 handlers show how to manipulate the ESBEnvelope header properties and how to return an ErrorXML document in the response. They also show how to invoke XSLT functionality. XSLT, much like the Service Handlers, is configured in a config file that contains the path to the XSLT files. An XSLT operation is performed in the Service Handling code by invoking a defined XSLT Service for the particular XSLT operation. This Service is defined in another configuration file - InteropDocumentTransformCfg.xml. Note that in the XSLT configuration, you can chain XSLT operations together. Once the service is setup, the XSLT calling code does not need to change if you change file names or if you need to do multiple XSLT operations etc.. Lines 1-10 show how to call the XSLT Service in code.


  1. If oEnv.GetCustomParam("ESBCore", "XsltTest") = "1" Then
  2. Try
  3. 'do some xslt testing...
  4. 'Dim oContext As ESB.Core.Interfaces.ServerContext.IServerContext
  5. Dim sResolveName As String = "TestResolveName"
  6. Dim sContext As String = "TestContext"
  7. Dim sXmlToTransform As String = oEnv.GetDocument(0).GetAsString()
  8. Dim sTransformResult As String
  9. 'CType(ESB.Core.Services.ContextManager.getContextManager(True).GetExistingContext, IServerContext).Transform(sResolveName, sContext, sXmlToTransform, sTransformResult)
  10. GetContext.Transform(sResolveName, sContext, sXmlToTransform, sTransformResult)
  11. If ShouldLog(LogDefs.eLogLevel.eLOG_DATAXFER) Then : LogMsg(eLogLevel.eLOG_DATAXFER, "sTransformResult=" & sTransformResult) : End If
  12. oEnvRs.AddDocument(New InlineDocument(sTransformResult))
  13. Catch ex As Exception
  14. ExceptionManager.Publish(ex)
  15. LogError(eLogLevel.eLOG_ERROR, ex.tostring)
  16. End Try
  17. End If
  18. If oEnv.GetCustomParam("ESBCore", "ConfigTest") = "1" Then
  19. Try
  20. 'do some Config Application Block testing...
  21. 'Dim oContext As ESB.Core.Interfaces.ServerContext.IServerContext
  22. Dim sTmp As String
  23. GetConfigData()
  24. sTmp = m_oCfgData.ContextManager.ClientContextManagerObjectImplementation.AssemblyPath()
  25. Dim oWarningEntry As New ErrorXML.WarningEntry
  26. With oWarningEntry
  27. .Code = "testcode"
  28. .Description = "if you get this message then the test txn worked."
  29. .Description = .Description & "ConfigTest Value=" & sTmp
  30. .Source = System.Reflection.Assembly.GetExecutingAssembly.ToString
  31. End With
  32. oErr.WarningEntry.Add(oWarningEntry)
  33. If ShouldLog(LogDefs.eLogLevel.eLOG_DATAXFER) Then : LogMsg(eLogLevel.eLOG_DATAXFER, "sTmp=" & sTmp) : End If
  34. Catch ex As Exception
  35. ExceptionManager.Publish(ex)
  36. LogError(eLogLevel.eLOG_ERROR, ex.tostring)
  37. End Try
  38. End If
  39. If oEnv.Context = "TestAddToPipelineTransitionData" Then
  40. Dim sPTD As String = oEnv.GetCustomParam("ESBCore", "TestAddToPipelineTransitionData")
  41. Try
  42. Dim oWarningEntry As New ErrorXML.WarningEntry
  43. With oWarningEntry
  44. .Code = sPTD
  45. .Description = "PipelineTransitionData instance " & sPTD
  46. .Source = System.Reflection.Assembly.GetExecutingAssembly.ToString
  47. End With
  48. oErr.WarningEntry.Add(oWarningEntry)
  49. Catch ex As Exception
  50. ExceptionManager.Publish(ex)
  51. LogError(eLogLevel.eLOG_ERROR, ex.tostring)
  52. End Try


 

The code below is an excerpt from the SAP Adaptor. It shows how you would get a business document out of the ESBEnvelope (Line 2).

Excerpt from SAP Adaptor - EnqPOSummaryDetails service handler


  1. m_oPlgRs = New PurchaseOrderSummaryRs.PurchaseOrderSummaryRs
  2. m_oPlgRq = oEnv.GetDocumentAsObject(GetType(PurchaseOrderSummaryRq.PurchaseOrderSummaryRq))
  3. m_oPlgRs.PONumber = m_oPlgRq.PONumber
  4. GetPOItemsFromSAP()
  5. 'Create a response envelope using the request envelope as a starting point. This preserves routing information etc.
  6. 'but strips out the original documents, attachments & relevant manifest entries.
  7. oEnvRs = oEnv.CreateResponse()
  8. 'Add the response document to the response envelope
  9. oEnvRs.AddDocument(New InlineDocument(m_oPlgRs))
  10. Return oEnvRs


 

3. Configuration

As you can see above, the services request and the service handler are defined separately. This step is where we tie in steps 1 & 2. i.e. marry the Service Request to the Service Handler(s) that implement the service. The Request and Handlers are decoupled in this way. Because of ths decoupling, a service can change implementation without the client having to change. The client will only need to change if the Request or Response require changes in the data being transferred.

You can swap out adaptors/handlers implementing a particular service without restarting the service bus.

The generic interface of the service bus makes it a simple task for a BPM tool to call into any ESB.NET based service, and then re-map the service calls within the tool, as only the business data for a particular request needs to be considered on the BPM tool side.

 

To view the configuration entries, navigate to the following directory in the ESB build.

..\5.0\5.0.1.0\Source\ESB\Base\Solutions\Main\Configuration\XMLConfigFiles

Open up InteropPipelineCfg.xml

This file contains the mappings between service request and implementation.

A mapping entry consists of the addition of a PipelineEntry into this file. An example of a simple PipelineEntry is shown below.

The Context and ResolveName are the keys into the service handler.

The Context is a concatenation of the ESBEnvelope Service fields. In our example, it's left blank.

The Context is derived as follows for the ESBEnvelope:

      [SystemType][SystemVersion].[Context].[ServiceType][ServiceVersion]

Note the periods between some of the fields.

The reason for this is that ESB.NET can support custom envelopes. Out of the box comes support for the BizTalk Jumpstart Kit envelope - the JSKEnvelope. It has a different mapping to the ESBEnvelope as it has a different set of fields in the envelope header.

This scheme can be fulfilled by custom envelope implementations and the one PipelineEntry configuration can then be used to handle all envelopes. This is addressed by the Envelope's IEnvelopeProvider implementation. Each envelope has it's own scheme for this mapping. Fortunately, there is seldom need to implement your own EnvelopeProvider, so this is less of a problem in real life Note that an EnvelopeProvider model is the preferred method of supporting multiple envelopes as opposed to XSLT, as it encapsulates all the issues related to different envelopes.

The ResolveName is the name of the primary document in the ESBEnvelope.

The MultiLevelOverrides node is used to define a handler for this PipelineEntry. In the example below, the ESB.Testing.TestTxns.TestTxn1 class is the handler specified to handle the request for this entry. You can have multiple PipelineEntry nodes with the same key fields. This is how you specify multpile handlers being executed for a particular request. There are also some parameters to specify whether you want to chain the handlers together using the original request or the outpur of the previous handler etc., whether to execute a particular handler asynchronously, and which queue(s) you want responses to go to.

There are also properties to keep a list of handler inputs/outputs in case you want to create more cohesive handlers.


  1. <PipelineEntry>
  2. <ResolveNameEntry>
  3. <ContextEntry>
  4. <Context>Context>
  5. <ResolveName>BuildCmd2ResolveName>
  6. <PipelineID>1PipelineID>
  7. <ProcessInParallel>0ProcessInParallel>
  8. <ResponseIsRequestForNextPipelineItem>1ResponseIsRequestForNextPipelineItem>
  9. <MultiLevelOverrides>
  10. <RequestQ />
  11. <TransactionComponent>ESB.Testing.TestTxns.TestTxn1TransactionComponent>
  12. <UseObjectBroker>0UseObjectBroker>
  13. <ObjectBroker>ObjectBroker>
  14. <ObjectBrokerServer />
  15. MultiLevelOverrides>
  16. ContextEntry>
  17. ResolveNameEntry>
  18. PipelineEntry>


 

Below is a more complex example. It consists of 4 Handlers executed sequentially to implement a service.

The first writes some data to a database, the second does a generic XSLT operation, the third kicks off a BPM process and the fourth updates a database.


  1. <PipelineMapSection>
  2. <PipelineEntry>
  3. <ResolveNameEntry>
  4. <ContextEntry>
  5. <Context>Staffware10i..StartCreateClaimCaseContext>
  6. <ResolveName>WfMessageResolveName>
  7. <PipelineID>1PipelineID>
  8. <ResponseIsRequestForNextPipelineItem>0ResponseIsRequestForNextPipelineItem>
  9. <MultiLevelOverrides>
  10. <ComponentServer suffix="yes">LobSystems\Staffware\Source\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims\bin\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims.dllComponentServer>
  11. <TransactionComponent suffix="yes">CopyRequestToDatabaseTransactionComponent>
  12. MultiLevelOverrides>
  13. ContextEntry>
  14. <ContextEntry>
  15. <Context>Staffware10i..StartCreateClaimCaseContext>
  16. <ResolveName>WfMessageResolveName>
  17. <PipelineID>2PipelineID>
  18. <ResponseIsRequestForNextPipelineItem>1ResponseIsRequestForNextPipelineItem>
  19. <MultiLevelOverrides>
  20. <ComponentServer suffix="yes">LobSystems\Staffware\Source\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims\bin\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims.dllComponentServer>
  21. <TransactionComponent suffix="yes">TranslateAcordToWfXmlTransactionComponent>
  22. MultiLevelOverrides>
  23. ContextEntry>
  24. <ContextEntry>
  25. <Context>Staffware10i..StartCreateClaimCaseContext>
  26. <ResolveName>WfMessageResolveName>
  27. <PipelineID>3PipelineID>
  28. <ResponseIsRequestForNextPipelineItem>1ResponseIsRequestForNextPipelineItem>
  29. <MultiLevelOverrides>
  30. <TransactionComponent>ESB.Adaptors.Application.Workflow.Staffware.CreateProcessInstanceRequestTxnTransactionComponent>
  31. <ComponentServer suffix="yes">LobSystems\Staffware\Source\ESB.Adaptors.Application.Workflow.Staffware\bin\ESB.Adaptors.Application.Workflow.Staffware.dllComponentServer>
  32. MultiLevelOverrides>
  33. ContextEntry>
  34. <ContextEntry>
  35. <Context>Staffware10i..StartCreateClaimCaseContext>
  36. <ResolveName>WfMessageResolveName>
  37. <PipelineID>4PipelineID>
  38. <MultiLevelOverrides>
  39. <ComponentServer suffix="yes">LobSystems\Staffware\Source\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims\bin\ESB.Adaptors.Application.Workflow.Staffware.AcordClaims.dllComponentServer>
  40. <TransactionComponent suffix="yes">UpdateDatabaseWithCaseIDTransactionComponent>
  41. MultiLevelOverrides>
  42. ContextEntry>
  43. ResolveNameEntry>
  44. PipelineEntry>


 

The following example is still more complex, and shows off many of the ESB.NET features.

It consists of 4 handlers implementing the unrelated tasks required to process claims forms scanned in and have been OCR'd etc. to extract some key information.

The first handler invokes a claims processing system to inform it of a new claim having been lodged. This is a generic handler, and has been built to further invoke a series of XSLT operations via some custom parameters passed to the handler on a per request basis. The XSLT services are defined in the InteropDocumentTransformCfg.xml file. The XSLT services are defined in the section below.


  1. <Custom>
  2. <ParamName>XSLTResolveNameAddressINParamName>
  3. <ParamValue>XSLTResolveNameAddressINValueParamValue>
  4. Custom>
  5. <Custom>
  6. <ParamName>XSLTContextAddressINParamName>
  7. <ParamValue>XSLTContextAddressINValueParamValue>
  8. Custom>
  9. <Custom>
  10. <ParamName>XSLTResolveNameAddressOUTParamName>
  11. <ParamValue>XSLTResolveNameAddressOUTValueParamValue>
  12. Custom>
  13. <Custom>
  14. <ParamName>XSLTContextAddressOUTParamName>
  15. <ParamValue>XSLTContextAddressOUTValueParamValue>
  16. Custom>
  17. <Custom>
  18. <ParamName>XSLTResolveNameAddClaimINParamName>
  19. <ParamValue>XSLTResolveNameAddClaimINValueParamValue>
  20. Custom>
  21. <Custom>
  22. <ParamName>XSLTContextAddClaimINParamName>
  23. <ParamValue>XSLTContextAddClaimINValueParamValue>
  24. Custom>
  25. <Custom>
  26. <ParamName>XSLTResolveNameAddClaimOUTParamName>
  27. <ParamValue>XSLTResolveNameAddClaimOUTValueParamValue>
  28. Custom>
  29. <Custom>
  30. <ParamName>XSLTContextAddClaimOUTParamName>
  31. <ParamValue>XSLTContextAddClaimOUTValueParamValue>
  32. Custom>


The second handler is a message router. It asynchronuosly <ProcessInParallel>1ProcessInParallel forwards the request (in this case containing attachments) to a dedicated ESB.NET instance on another server, which has an image processing handler configured. This ESB.NET instance queues the request and processes it in due time. This is a CPU intensive and low priority task.

Note that the async processing here is async amongst handlers. The client request dictates whether the client<=>server interaction is synchronous or asynchronous, and where responses are to go if it's asynchronous. This is done via the <callSynchronizationType>0callSynchronizationType> node in the request envelope. Responses are usually sent to the URL specified in the <from><address>address> node in the request, however can be further controlled in the server side service definition.

The third handler, creates a standards based Workflow request, based upon the original business process oriented request, with the intent to forward it off to the next handler which will invoke the Workflow Server. The <ResponseIsRequestForNextPipelineItem>1ResponseIsRequestForNextPipelineItem> tag will ensure that the output of this handler is used as the input for the next handler.

The fourth handler merely invokes the workflow server via a standards based (WfXml) workflow message.


  1. <PipelineEntry>
  2. <ResolveNameEntry>
  3. <ContextEntry>
  4. <Context>Claims1.0..CreateClaimContext>
  5. <ResolveName>OLifEResolveName>
  6. <PipelineID>1PipelineID>
  7. <ResponseIsRequestForNextPipelineItem>0ResponseIsRequestForNextPipelineItem>
  8. <MultiLevelOverrides>
  9. <ResponseIsOverallPipelineResponse>1ResponseIsOverallPipelineResponse>
  10. <ComponentServer suffix="yes">LobSystems\Figtree\Source\ESB.Adaptors.Application.Figtree\bin\ESB.Adaptors.Application.Figtree.dllComponentServer>
  11. <TransactionComponent>ESB.Adaptors.Application.Figtree.CreateClaimTransactionComponent>
  12. <Custom>
  13. <ParamName>XSLTResolveNameAddressINParamName>
  14. <ParamValue>XSLTResolveNameAddressINValueParamValue>
  15. Custom>
  16. <Custom>
  17. <ParamName>XSLTContextAddressINParamName>
  18. <ParamValue>XSLTContextAddressINValueParamValue>
  19. Custom>
  20. <Custom>
  21. <ParamName>XSLTResolveNameAddressOUTParamName>
  22. <ParamValue>XSLTResolveNameAddressOUTValueParamValue>
  23. Custom>
  24. <Custom>
  25. <ParamName>XSLTContextAddressOUTParamName>
  26. <ParamValue>XSLTContextAddressOUTValueParamValue>
  27. Custom>
  28. <Custom>
  29. <ParamName>XSLTResolveNameAddClaimINParamName>
  30. <ParamValue>XSLTResolveNameAddClaimINValueParamValue>
  31. Custom>
  32. <Custom>
  33. <ParamName>XSLTContextAddClaimINParamName>
  34. <ParamValue>XSLTContextAddClaimINValueParamValue>
  35. Custom>
  36. <Custom>
  37. <ParamName>XSLTResolveNameAddClaimOUTParamName>
  38. <ParamValue>XSLTResolveNameAddClaimOUTValueParamValue>
  39. Custom>
  40. <Custom>
  41. <ParamName>XSLTContextAddClaimOUTParamName>
  42. <ParamValue>XSLTContextAddClaimOUTValueParamValue>
  43. Custom>
  44. MultiLevelOverrides>
  45. ContextEntry>
  46. <ContextEntry>
  47. <Context>Claims1.0..CreateClaimContext>
  48. <ResolveName>OLifEResolveName>
  49. <PipelineID>2PipelineID>
  50. <ProcessInParallel>1ProcessInParallel>
  51. <ResponseIsRequestForNextPipelineItem>0ResponseIsRequestForNextPipelineItem>
  52. <MultiLevelOverrides>
  53. <RequestQ>MSMQ:.\private$\ESBRequestQRequestQ>
  54. <TransactionComponent>ESB.Core.Adaptors.Transport.RequestHandlerProxy.SenderTransactionComponent>
  55. <ComponentServer suffix="yes">Base\Solutions\Main\TransportAdaptors\ESB.Core.Adaptors.Transport.RequestHandlerProxy\bin\ESB.Core.Adaptors.Transport.RequestHandlerProxy.dllComponentServer>
  56. <Custom>
  57. <ParamName>OverrideDestinationServerURLParamName>
  58. <ParamValue>http://asp02s01c11a01vm.aunz.Keystroke.com/ESB/ClaimsPh2/CoreInternetTransportAdaptors/ESBSoapRpcTransport.asmxParamValue>
  59. Custom>
  60. <Custom>
  61. <ParamName>OverrideTransportTypeParamName>
  62. <ParamValue>SOAPParamValue>
  63. Custom>
  64. <Custom>
  65. <ParamName>EnvelopeTypeParamName>
  66. <ParamValue>E3ParamValue>
  67. Custom>
  68. MultiLevelOverrides>
  69. ContextEntry>
  70. <ContextEntry>
  71. <Context>Claims1.0..CreateClaimContext>
  72. <ResolveName>OLifEResolveName>
  73. <PipelineID>3PipelineID>
  74. <ResponseIsRequestForNextPipelineItem>1ResponseIsRequestForNextPipelineItem>
  75. <MultiLevelOverrides>
  76. <ComponentServer suffix="yes">LobSystems\Facade\Source\ESB.Adaptors.Application.Facade.Claims\bin\ESB.Adaptors.Application.Facade.Claims.dllComponentServer>
  77. <TransactionComponent>ESB.Adaptors.Application.Facade.Claims.CreateWfXmlDocumentFromOLifEDocumentTransactionComponent>
  78. MultiLevelOverrides>
  79. ContextEntry>
  80. <ContextEntry>
  81. <Context>Claims1.0..CreateClaimContext>
  82. <ResolveName>OLifEResolveName>
  83. <PipelineID>4PipelineID>
  84. <ResponseIsRequestForNextPipelineItem>0ResponseIsRequestForNextPipelineItem>
  85. <MultiLevelOverrides>
  86. <TransactionComponent>ESB.Adaptors.Application.Workflow.Staffware.CreateProcessInstanceRequestTxnTransactionComponent>
  87. <ComponentServer suffix="yes">LobSystems\Staffware\Source\ESB.Adaptors.Application.Workflow.Staffware\bin\ESB.Adaptors.Application.Workflow.Staffware.dllComponentServer>
  88. MultiLevelOverrides>
  89. ContextEntry>
  90. ResolveNameEntry>
  91. <MultiLevelOverrides>
  92. <ResponseIsOverallPipelineResponse>0ResponseIsOverallPipelineResponse>
  93. MultiLevelOverrides>
  94. PipelineEntry>

 

Permalink |  Trackback

Your name:
Title:
Comment:
Add Comment   Cancel 

  

 Text/HTML Minimize
Listed on BlogShares

      

 Search_Blog Minimize

    

 Blog_Archive Minimize

    

Copyright 2006 Keystroke IT   Terms Of Use  Privacy Statement
DotNetNuke® is copyright 2002-2008 by Perpetual Motion Interactive Systems Inc.