Thursday, May 17, 2012

Everest in WCF vs. WCF in Everest

The connector architecture in the Everest framework is designed to be consistent regardless of the underlying transport. The four patterns provided by the connectors in Everest (Listen/Wait, Listen/Wait/Respond, Send and Send/Receive) provide common patterns for communicating on a variety of transports including queues, http, files and others.

When it comes to communicating or hosting services that respond using the WCF framework, the current Everest connector pattern is implemented in the form of a WcfServerConnector and WcfClientConnector. While this is great for consistency with the rest of the Everest framework it is awkward for developers who are familiar with WCF. In this manner of speaking WCF is used within Everest. In order to be truly easy to use, we needed to make Everest in WCF.
The current development branch of Everest (1.1) includes this functionality. Consider the process of receiving a message on the WCF connector, the function looks something like this:

/// <summary>
/// Message is available
/// </summary>
static void connector_MessageAvailable(object sender, MARC.Everest.Connectors.UnsolicitedDataEventArgs e)
{

    var connector = sender as IListenWaitRespondConnector;
    var receiveResult = connector.Receive();

    // Determine the type of interaction
    if (receiveResult.Structure is PRPA_IN201305UV02)
        ; // Do something here
    if (receiveResult.Structure is PRPA_IN201307UV02)
        ; // Do something here

    connector.Send(transactionResult, receiveResult);
}

Which makes sense from an Everest connectors point of view, however it is quite awkward to a typical WCF developer. In the new Everest framework version we can use the familiar WCF pattern as illustrated below:
[EverestSerializerFormat(Formatter = typeof(XmlIts1Formatter), GraphAide = typeof(DatatypeFormatter), ValidateConformance = false)]
[ServiceContract(Namespace="urn:hl7-org:v3")]
public interface IServiceContract
{
    /// <summary>
    /// Do something
    /// </summary>
    [OperationContract(Action="*")]
    IGraphable Anything(IGraphable request);

}
public class ServiceBehavior : IServiceContract
{

    #region IServiceContract Members

    /// <summary>
    /// Default message
    /// </summary>
    /// <returns></returns>
    public IGraphable Anything(IGraphable request)
    {
     
         // Determine the type of interaction
       if (request is PRPA_IN201305UV02)
          ; // Do something here
         if (request is PRPA_IN201307UV02)
          ; // Do something here
                    
        return transactionResult;        
    }

    #endregion
}

The EverestSerializerFormat attribute is very similar in functionality to the XmlSerializerFormat attribute and instructs the WCF layer to use Everest as the serialization engine rather than the built-in XML or data contract serializer.

Alternatively, developers can now piggy-back on the other WCF services to classify operations that are to be executed:
[EverestSerializerFormat(Formatter = typeof(XmlIts1Formatter), GraphAide = typeof(DatatypeFormatter), ValidateConformance = false)]
[ServiceContract(Namespace="urn:hl7-org:v3")]
public interface IServiceContract
{
    /// <summary>
    /// Handle PRPA_IN201305UV02
    /// </summary>
    [OperationContract(Action="PRPA_IN201305UV02")]
    PRPA_IN201306UV02 DoSomething(PRPA_IN201305UV02 request);

    /// <summary>
    /// Handle PRPA_IN201307UV02
    /// </summary>
    [OperationContract(Action = "PRPA_IN201307UV02")]
    PRPA_IN201308UV02 DoSomethingB(PRPA_IN201307UV02 request);

}

One limitation of using the EverestSerializerFormat attribute is the lack of access to validation errors and the result details.

No comments:

Post a Comment