UnifySquare Logo
 
Nav Accent Bar
From technical articles to tid-bits of important news and information, stay up to date on the latest UC happenings. Unify Square Blog
Helping you deploy the world's leading platform for Unified Communications.
 

In this post, I’m going to demonstrate how to add automatic reconnection logic to UCMA applications, which is otherwise not well documented.

In an ideal world, one’s custom OCS 2007 R2 middle-tier applications never lose their connections to OCS front-end servers.  In the real world, however, unplanned network and server outages will disrupt these connections.  If you do not want to be responsible for manually restarting your UCMA 2.0 applications each time this happens, you need to add automatic reconnection logic to these applications.

How to do this is not fully documented.  And, as far as I know, there are no sample applications showing how to

1) Detect that you have lost the connection to the front-end server, and

2) Re-establish the connection to the front end server. 

So, I shall provide some code samples in this blog that help clarify how to accomplish these two important tasks.

In order to understand the solution, you need to understand how UCMA signals an application connection, disconnection and failure.  In particular, these three points are key:

1) The connection to the OCS front-end server is created when you establish the application endpoint via the LocalEndpoint.EndEstablish() method.  Any failure establishing the connection will be thrown by this method.

2) When the local endpoint is disconnected from the OCS front-end server, its state will transition to Terminating and then Terminated.

3) An attempt to establish a call using a disconnected endpoint via the Call.EndEstablish() method will throw a InvalidOperationException exception. 

Here are the code samples that you can add to your UCMA 2.0 application to detect a lost connection and re-establish it. 

Step 1: Detect that the application has lost its connection to the OCS front-end server

1.1) Register your local endpoint for state changes:

    LocalEndpoint _endpoint;

    ….

    _endpoint.StateChanged += new EventHandler<LocalEndpointStateChangedEventArgs>(_endpoint_StateChanged);

1.2) Implement the _endpoint_StateChanged event handler:

    /// <summary>
    /// Will be true if we need to re-establish the endpoint's connection to the front end server.
    /// </summary>
    bool needReConnect;

    /// <summary>
    /// Called when endpoint state changes.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    void _endpoint_StateChanged(object sender, LocalEndpointStateChangedEventArgs args)
    {
        try
        {
            if (args.State == LocalEndpointState.Terminated)
            {
                Console.WriteLine("endpoint state is now terminated.");

                // Endpoint lost connection to OCS server. Need to re-establish our endpoint.
                needReConnect = true;
            }
            else if (args.State == LocalEndpointState.Reestablishing)
            {
                Console.WriteLine("endpoint state is re-establishing.");
            }
            else if (args.State == LocalEndpointState.Established)
            {
                Console.WriteLine("endpoint state is now established.");

                needReConnect = false;
           }
        }
        catch (Exception e)
        {
            HandleException(e);
        }
    }

Step 2: Re-establish the connection with the front-end server

2.1) Before making your next call to the OCS server, add the following code:

    …

    // Do we need to re-establish our connection with the OCS front end server?
    if (needReConnect)
    {
        needReConnect = (ReestablishEndpoint() ? false : true);
    }

    if (false == needReConnect)
    {
        // Continue on with call, etc.
    }

    // Otherwise, try again the next time around

    …

2.2) Implement the ReestablishEndpoint() method.

    /// <summary>
    /// Returns true if get reconnected, false otherwise
    /// </summary>
    /// <returns>bool</returns>
    private static bool ReestablishEndpoint()
    {
        bool success = false;

        try
        {
            // Terminate the endpoint.
            // Terminate the platform.
            ShutdownPlatform();

            // Re-initialize the platform and endpoint
            InitPlatform();

            success = true;
        }
        catch (Exception e)
        {
            Console.WriteLine("Re-establish failed.");
            HandleException(e);
        }

        return success;
    }

2.3) Implement the ShutdownPlatform() method.

    CollaborationPlatform _collabPlatform;

    /// <summary>
    /// Uninitialize the UCMA platform.
    /// </summary>
    private static void ShutdownPlatform()
    {
        …

        // Terminate the endpoint.
       if (_endpoint != null)
        {

            …
            _endpoint.StateChanged -= _endpoint_StateChanged;
            _endpoint.EndTerminate(_endpoint.BeginTerminate(null, null));
            _endpoint = null;
        }

        if (_collabPlatform != null)
        {
            _collabPlatform.EndShutdown(_collabPlatform.BeginShutdown(null, null));
           _collabPlatform = null;
        }
    }

2.4) Implement the InitPlatform() method.

        /// <summary>
        /// Initializes the UCMA platform and endpoint.
        /// </summary>
        private static void InitPlatform()
        {
            …

                _collabPlatform = new CollaborationPlatform(platformSettings);

                Console.Write("Starting CollaborationPlatform... ");
                _collabPlatform.EndStartup(_collabPlatform.BeginStartup(null, null));
                Console.WriteLine("Complete");

      …

                _endpoint = new UserEndpoint(_collabPlatform, settings); // or ApplicationEndpoint, as appropriate

                Console.Write("Establishing Endpoint... ");
                _endpoint.EndEstablish(_endpoint.BeginEstablish(null, _endpoint));
                Console.WriteLine("Complete");

                // Register for state changes
                _endpoint.StateChanged += new EventHandler<LocalEndpointStateChangedEventArgs>(_endpoint_StateChanged);

     …

    }

Note that the local endpoint state must be Idle when BeginEstablish() is called. 

For this reason, this sample terminate both the local endpoint and the collaboration platform before trying to re-establish the endpoint’s connection with the OCS front-end server. 

Finally, it’s worth noting that you can catch the InvalidOperationException exception when attempting to establish a new call with the local endpoint.  This allows you to log a message with more complete context than the one that the collaboration platform provides:

Call call;

call.EndEstablish(call.BeginEstablish(null, null));

catch (InvalidOperationException e)
{
    // NOTE:
    // If the endpoint has been disconnected from the front end server, then the error message text is
    // "Endpoint is currently terminating or already terminated"

    if (e.ToString().Contains("Endpoint is currently terminating or already terminated"))
    {

        // Just in case we do not get the state change event on the local endpoint…
        // We need to re-establish a connection with the front end server.
        needReConnect = true;

        // TODO: Log a more informative error.
    }
}

Note that we are currently using this code in several of our internal UCMA 2.0 applications and the applications are successfully reconnecting after OCS front end server re-starts.

That is it!  Let me know if you find this useful!  Have fun coding…


August 19, 2009 07:24 by katyle Permalink | Comments (6) | Comment RSS RSS Button Image


The release of Office Communication Server 2007 R2 from Microsoft at the beginning of January 2009 was followed not long after by the release of a comprehensive book titled “Programming for Unified Communications with Microsoft Office Communications Server 2007 R2” in May.  The purpose of the book is to give developers both a reference and a road map for developing applications for OCS 2007 R2.  The authors, Rui Maximo, Kurt De Ding, Vishwa Ranjan, Chris Mayo and Oscar Newkerk do an excellent job of describing, in detail, how to develop an application which leverages OCS 2007 R2 from the ground up.

One of the things that I really like about this book is that it starts from the beginning and takes you through the end of the initial development cycle, taking into consideration the fact that this may be a platform that you have not used before. 

First, the book describes how to setup your machine to develop with the OCS 2007 R2 SDKs.  It details the hardware and software requirements and provides guidance on how to setup a test topology.

The above cannot be emphasized enough.  Office Communication Server is a complex product that is normally installed and maintained by an IT professional.  If you are a classically educated developer, you may not have had experience setting up many of the pre-requisites for OCS.  These pre-requisites include setting up a Domain Controller and DNS Server, installing a domain Certificate Authority (CA) for generated client and server certificates, creating necessary DNS SRV records, and guiding you through the multi-step OCS 2007 R2 setup program.  These tasks are all detailed in Chapter 9, “Preparing the UC Development Environment”.  I highly recommend that all developers whom are new to OCS read this chapter, especially if tasks such as “create and configure the desired user accounts in AD DS” scare you, as they did me.

The book will also help you to be aware of what SDKs exist for OCS 2007 R2 and help you to decide what SDK is best suited for your project.  Note that there are six SDKs to choose from.  The overview for the SDKs is in Chapter 2, “Microsoft Unified Communications APIs Foundation”.  I recommend reading this chapter before starting your first OCS project, and then referring to it every time that you start designing another.

Of course, the book also contains a chapter or chapters dedicated to each of the SDKs, each of which is very helpful.

Finally, the last highlight of the book is Chapter 10, “Debugging a Unified Communications Application”.  This is my second favorite chapter of the book (Chapter 9, “Preparing the UC Development Environment” being my number one favorite).  This chapter describes the various logging tools available with the OCS 2007 R2 SDKs and shows you how to use them.  This chapter also explains the exception hierarchy and gives examples of how to make use of the exception classes in your exception handling code.  I believe that many of the items covered in Chapter 10 are only touched on in the OCS 2007 R2 SDK documentation and may thus be unused by many developers.

How do I get this book, you ask?  It is available from Amazon.com via the following link:

http://www.amazon.com/gp/product/0735626235/ref=s9_sims_gw_s0_p14_i1?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0KXJAGNNF4X40SZ6XG9P&pf_rd_t=101&pf_rd_p=470938631&pf_rd_i=507846

Disclaimer:

The author of this review currently works with one of the authors, and is acquainted with one of the others.  My enthusiasm for the book, however, is genuine.  I wrote my first one and one-half UCMA 2.0 applications before reading this book, using the MSDN and SDK documentation and samples as my main reference.  Although these were “adequate”, they were not excellent.  I could have saved myself a lot of time and trouble by reading this book first, cover-to-cover, and then referring to the MSDN and SDK documentation purely as a API reference guide (which is all that they are really meant to be).

Have fun coding!

Katy Lynn McCullough-Leonard


June 26, 2009 08:34 by katyle Permalink | Comments (102) | Comment RSS RSS Button Image


Privacy  |  Contact  |  Terms of Use  |  www.unifysquare.com | Copyright © 2009 Unify2  -  All rights reserved.
Microsoft and the Microsoft Logos are trademarks of Microsoft, Inc.