Implement inbound integration

What you'll be learning:

  • How to create a WDX-compliant web service client from a custom WSDL file

  • How to associate a workflow script with an integration message instead of a form submission

  • How to use the trace statement in a workflow script

So far, you've set up the integration messages that carry the data across your hopeful integration solution, and you've created an inbound endpoint on the Mobilengine side to welcome the arriving messages. Now you'll be putting the final element of your integration solution in place: the web service client that receives the integration messages from Rocky Jupiter, and sends them along to the Mobilengine Cloud.

Most of the heavy lifting has been done for you: you get the WSDL file that you can use to set up the web service client. The WSDL is a generic type of web service service contract, a collection of metadata relating to, in this particular case, the custom WDX web service protocol and the details of the dacs-es that you want your web service client to handle.

Armed with the service contract for the web service client, you'll use an IDE to generate the service contract code for the web service client, and use the operations declared in the code.

The implementation that you set up will serve purely to test the integration solution, nothin more: you'll write a dummy dacs, and make the client send it across the wire to the Cloud every time you manually start up the web service client. You'll need some proof that the message really did reach the Cloud, so the final step is to set up a workflow script that runs when a newTask dacs arrives.

After that, you'll just start up the freshly minted web service client, see the contents of the incoming integration message show up in the Cloud log, and smile. Let's begin then, shall we?

  1. Open Visual Studio, and add a new Windows C# project. Name it RockyJupiter.Mobilengine.Client, and pick Console Application as the project template: you'll be starting the web service client manually via the console, so this template is just the ticket. Set the project target framework to .NET Framework 4.5.

  2. Reference the WSDL service contract in the project to generate the web service client contract code: right-click RockyJupiter.Mobilengine.Client, and click Add Service Reference.

    In the Add Service Reference dialog box: enter the path to the WSDL file that you downloaded in the previous tutorial in the Address box; select IWdx in the Services list; enter Wdx in the Namespace box; and click OK.

    This is what the Add Service Reference dialog box should look like when you click OK

    Figure 205. This is what the Add Service Reference dialog box should look like when you click OK


  3. Staying in Visual Studio, open the project's Program.cs file, and make use of the single EnqueueDacs operation of the referenced IWdx web service contract. Set the key of the associated inbound endpoint to be the dacs's Key property, make the operation send a specific hard-coded newPO dacs, and stick the dacs-sending method inside a retry loop to account for the inevitable temporary network errors.

    If the key sent along with an integration message does not match the endpoint key of the inbound endpoint, the Cloud will send back an EnqueueDacsFail SOAP response. Your retry loop needs to prepare for the possibility of this happening, and move on to the next integration message, abandoning the dacs in question.

    using System;
    using System.Globalization;
    using System.ServiceModel;
    using System.Threading;
    //Don't forget to reference
    //your newly-created project-specific namespace
    using RockyJupiter.Mobilengine.Client.Wdx;
    
    namespace RockyJupiter.Mobilengine.Client
    {
        class Program
        {
            //Inbound endpoint key
            //in a real-world scenario this would come from configuration
            private const string Key = "333da03781b04fbbb78ad991d4986c78";
    
            //Set up a retry pattern in case the EnqueueDacs() operation fails
            private const int MaxRetryCount = 5;
            private static readonly TimeSpan RetryInterval = TimeSpan.FromSeconds(10);
    
            static void Main(string[] args)
            { 
                //Create the do-while retry loop
                var retryCount = 0;
                bool shouldRetry;
                do
                {
                    var wdxClient = new WdxClient();
                    try
                    {
                        retryCount++;
                        wdxClient.EnqueueDacs(CreateDacs());
                        wdxClient.Close();
                        Console.WriteLine("EnqueueDacs succeeded.");
                        shouldRetry = false;
                    }
                    catch (FaultException<EnqueueDacsFail>)
                    {
                        Console.WriteLine("EnqueueDacsFail fault received, giving up.");
                        shouldRetry = false;
                    }
                    catch (Exception ex)
                    {
                        wdxClient.Abort();
                        shouldRetry = retryCount < MaxRetryCount;
                        Console.WriteLine("EnqueueDacs failed: {0}", ex.Message);
                        if (shouldRetry)
                        {
                            Console.WriteLine("Will retry in {0} seconds.",
                                              RetryInterval.TotalSeconds);
                            Thread.Sleep(RetryInterval);
                        }
                        else
                        {
                            Console.WriteLine("Giving up after {0} retries", retryCount);
                        }
                    }
                } while (shouldRetry);
            }
    
            static Dacs CreateDacs()
            {
                return new Dacs
                {
                    dacsid = Guid.NewGuid().ToString("N"),
                    dtu = DateTime.UtcNow,
                    Key = Key,
                    meta = DacsMeta.rockyJupiternewPO,
                    Content = new DacsContent
                    {
                        Item = CreateNewPo()
                    }
                };
            }
    
            static newPO CreateNewPo()
            {
                return new newPO
                {
                    //Generate a guid for the test dacs
                    //and hard-code the contents of the test message.
                    assignmentId = Guid.NewGuid().ToString("N"),
                    admin = "Connie Lowe",
                    driver = "petar.hoyt@gmail.com",
                    client = "Sonky Rubber Goods",
                    loadAddress = "Napierstraat 33 1972 EE IJmuiden",
                    unloadAddress = "Edisonstraat 57 5615 GA Eindhoven",
                    dueDate = (DateTime.UtcNow + TimeSpan.FromDays(5)).ToString
                                ("MM/dd/yyyy HH:mm:ss.fffK", CultureInfo.InvariantCulture),
                    loadType = NewPOLoadType.Shippingcontainer,
                };
            }
        }
    }

    When you enter the hard-coded content for the test dacs, make sure that you make the driver field equal to the username that you are currently using on the Mobilengine mobile client.

  4. Test the basic retry loop that you implemented: disconnect or disable your network connection, and start the web service client in Visual Studio. Your console should read:

    Will retry in 10 seconds.
    Will retry in 10 seconds.
    Will retry in 10 seconds.
    Will retry in 10 seconds.
    Will retry in 10 seconds.
    Giving up after 5 retries.

    Fix your network connection. Now go back to Program.cs, and deliberately mess up the Key on line 13, then run the project. Your console should read:

    EnqueueDacsFail fault received, giving up.
  5. The error handling retry loop in your code seems to work perfectly. Let's see if it does what it's supposed to when nothing goes wrong.