Message Composition for SwitchYard Gateways

Version 2

    Overview

    There are four paths where message composition (or decomposition) occurs in SwitchYard:

    • Composing a service request (CSR) : a native protocol message is received by a gateway and normalized to the SY Message API.  This is the first, or "in", phase of an exchange for a service binding.
    • Decomposing a service response (DSR) : a normalized SY Message is converted to a native protocol representation by a gateway.  This is the second, or "out", phase of an exchange for a service binding.
    • Decomposing a reference request (DRR) : a normalized SY Message is converted to a native protocol representation by a gateway.  This is the first, or "in", phase of an exchange for a reference binding.
    • Composing an reference response (CRR) : a native protocol message is received by a gateway and normalized to the SY Message API.  This is the second, or "out", phase of an exchange for a reference binding.

     

    Type Awareness

    While each gateway has its own native type that it deals with, two of the paths outlined above require a gateway to convert from its native content to the type defined in the service or reference interface related to the binding.

    • CSR : in this case, the gateway has received a message and the content is in its native form.  In this situation, the gateway's composer needs to convert the content to the type defined in the composite service interface for a given operation.  As an example, the HTTP component currently uses byte[] as its native content representation.  If the composite service associated with binding.http has an interface definition which defines an input type of java.lang.String, the HTTP component should attempt a conversion between byte[] and String in its message composer.
    • CRR : in this case, the gateway has received a reply message with content in its native representation.  The same rules regarding conversion in CSR apply here, but the output type of a reference interface is used instead.

     

    Determining Content Type

    The following code can be used to determine the type being used in an exchange:

     

    QName msgType;
    if (exchange.getPhase() == null) {
        // Composing a service request (CSR) path
        msgType = exchange.getContract().getConsumerOperation().getInputType();
    } else {
        // Composing an reference response (CRR) path
        msgType = exchange.getContract().getProviderOperation().getOutputType();
    }
    
    

     

    Once you have the message type, you need to figure out whether the output type can be determined with some code like this:

     

    QName msgType = getMessageType(exchange);
    if (QNameUtil.isJavaMessageType(msgType)) {
        Class<?> clazz = QNameUtil.toJavaMessageType(msgType);
        // attempt conversion here
    }
    
    

     

    Converting Content

    As of now, we don't have an easy way to access the transformer/converter registry from a message, but the following is functionally what we want to do:

     

    byte[] content = getBindingContent();
    QName msgType = getMessageType(exchange);
    Class<?> clazz = QNameUtil.toJavaMessageType(msgType);
    // this sets the native content type
    message.setContent(content);
    // the getContent() call triggers a conversion from that native content type and the result is set as the new body
    message.setContent(message.getContent(clazz));
    

     

    Yes, that's yucky, but you can see how the logic plays out here with the message instance itself being used to convert between the native type and the type specified on the service interface.  We could easily clean this up to introduce a convenience/utility method to eliminate the extra call to setContent.