The integration server is at the center of the integration platform. While running, it processes incoming messages from source adapters, applies transformations, and forwards the results to the destination adapter. Building the integration server requires a common interface definition, the Windows service application code, and access to an external configuration file.
You need to add the integration server's interface definition to a new class file named IIntegrationServer.cs within the IntegrationCommon assembly. Listing 12-11 presents the interface code.
namespace IntegrationCommon { public interface IIntegrationServer { void ProcessRequest( string strData ); void SendToAdapter( string strDestination, string strData ); void LoadConfigurationData(); } }
The interface outlines three methods . The ProcessRequest method reads the incoming normalized data and performs the necessary data transformations. The SendToAdapter method takes the transformed data and forwards it to the target application adapter. The LoadConfigurationData method loads the externalized application-to-application mappings. All methods need to be packaged into a separate assembly that can be imported into the adapter project.
To create the integration server itself, create a new Windows service project named IntegrationServer . The administrator does not really need to directly interact with the integration server, so there is little need for a user interface. The Windows service simply starts, processes data mapping requests , and shuts down when instructed. Listing 12-12 presents a skeletal version of the integration server. Add project and code references to the IntegrationCommon namespace.
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.ServiceProcess; namespace LiquidServer { //changed class declaration other inherited interfaces public class System.ServiceProcess.ServiceBase { private System.ComponentModel.Container components = null; public IntegrationServer() { InitializeComponent(); } static void Main() { System.ServiceProcess.ServiceBase[] ServicesToRun; ServicesToRun = new System.ServiceProcess.ServiceBase[] { new IntegrationServer() }; System.ServiceProcess.ServiceBase.Run(ServicesToRun); } private void InitializeComponent() { components = new System.ComponentModel.Container(); this.ServiceName = "IntegrationServer"; } protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } protected override void OnStart(string[] args) { } protected override void OnStop() { } }
The integration server requires access to the collection of application-toapplication mappings. As requests come into the integration server, an ArrayList containing ApplicationMapping objects is searched for matches. When a match is found, the details of the mapping are forwarded to the transformation engine. Listing 12-13 presents the MappingEntry class added to the IntegrationServer project. It is used to store the application-to-application mappings in memory.
class MappingEntry { string _SourceSchema; string _DestinationSchema; string _DestinationAddress; string _TransformationFile; public string SourceSchema { get { return _SourceSchema; } set { _SourceSchema = value; } } public string DestinationSchema { get { return _DestinationSchema; } set { _DestinationSchema = value; } } public string DestinationAddress { get { return _DestinationAddress; } set { _DestinationAddress = value; } } public string TransformationFile { get { return _TransformationFile; } set { _TransformationFile = value; } } }
The application mappings are loaded from the external configuration file when the integration server is started. The _SourceSchema identifies the application data coming into the integration platform. The _TargetSchema identifies the how the data should appear after its transformation. The _TransformationFile points to the XSL Transformations (XSLT) document responsible for performing the data transformation. The _DestinationAddress identifies the target adapter to receive the transformed data.
The integration server needs to store configuration settings externally to keep itself flexible. Some of these settings include application-to-application mappings that are supported. Because XSLT will be the technology performing the transformations, then each application-to-application mapping will need to match a source XML document with a destination XML document and an XSLT style sheet. Add a new text file named App.config to the IntegrationServer project and add the values presented in Listing 12-14.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="AppMappings"> <section name="Integration" /> </sectionGroup> </configSections> <AppMappings> <Integration SourceSchema="appdemo.xml" DestinationSchema="issuetracker.xml" DestinationAddress="http://127.0.0.1:3202" Transformation="AppDemoToIssueTracker.xslt" /> </AppMappings> </configuration>
The integration adapter configuration file can contain any number of <Integration> elements. Each element represents a single mapping from one application to another. Each mapping is identified by a source XML schema name, a destination schema name, a destination address, and the XSLT style sheet used to perform the transformation. Listing 12-15 implements the LoadConfiguraionData method for the integration server. You also need to add code references to the System.Xml and System.Diagnostics namespaces.
private void LoadConfigurationData() { //object representing a single application-to-application mapping MappingEntry entry; //using XPath to retrieve the configuration data XmlDocument xmldoc = new XmlDocument(); xmldoc.Load( "IntegrationServer.exe.config" ); XmlNode root = xmldoc.DocumentElement; try { XmlNodeList xnodelist = root.SelectNodes( "/configuration/AppMappings/Integration" ); foreach( XmlNode xnode in xnodelist ) { //create a new entry object entry = new MappingEntry(); entry.SourceSchema = xnode.Attributes["SourceSchema"].Value; entry.DestinationSchema = xnode.Attributes["DestinationSchema"].Value; entry.DestinationAddress = xnode.Attributes["DestinationAddress"].Value; entry.TransformationFile = xnode.Attributes["Transformation"].Value; //add this mapping to the collection _ApplicationMappings.Add( entry ); } } catch( Exception x ) { EventLog systemLog = new EventLog(); systemLog.Source = "IssueTracker"; systemLog.WriteEntry( x.Message, EventLogEntryType.Error, 0 ); systemLog.Dispose(); } return; }
Unlike the adapter configuration settings, the integration server requires a more structured configuration file. XPath is used to navigate the configuration file and initialize a new MappingEntry object before adding it to the ArrayList. Each time a request arrives, the ArrayList is searched for a valid mapping to con-tinue processing.