Skip to main content
Previous sectionNext section

Adding and Using Custom Header Elements

This chapter describes how to add and use custom SOAP header elements.

This chapter discusses the following:

For information on adding header elements when faults occur, see the chapter “SOAP Fault Handling,” earlier in this book.

A later chapter discusses WS-Addressing header elements. For information on WS-Security header elements, see Securing Caché Web Services.

Introduction to SOAP Header Elements in Caché

A SOAP message can include a header (the <Header> element), which contains a set of header elements. For example:

<SOAP-ENV:Envelope>
   <SOAP-ENV:Header>
      <MyHeaderElement>
         <Subelement1>abc</Subelement1>
         <Subelement2>def</Subelement2>
      </MyHeaderElement>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
...
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Copy code to clipboard

Informally, each header element is often referred to as a “header.” This is not strictly accurate, because the message itself can contain at most one header, which is always <Header>, with an appropriate namespace prefix. The header can contain WS-Security header elements, WS-Addressing header elements, and your own custom header elements.

A header element carries additional information for possible use by the web service or web client that receives the SOAP message. In the example shown here, this information is carried within XML elements. A header element can also include XML attributes, although none are shown in the previous example. The SOAP standard specifies three standard attributes (mustUnderstand, actor, and encodingStyle) to indicate how a recipient should process the SOAP message.

How Caché Represents SOAP Headers

Caché represents each header element as an instance of %SOAP.Header or one of its subclasses. %SOAP.Header is an XML-enabled class with properties that correspond to the standard header element attributes (mustUnderstand, actor, and encodingStyle).

Caché provides specialized subclasses of %SOAP.Header for use with WS-Addressing and WS-Security. To represent custom header elements, you create your own subclasses of %SOAP.Header.

When a Caché web service or client receives a SOAP message, it imports and processes the message. During this step, if the message contains a header with custom header elements, Caché compares the header elements to the list of supported header elements (discussed in the next subsection).

Then the service or client creates an instance of each applicable header element class, inserts those into an array, and places that array in its own HeadersIn property:

generated description: headers in

To use these header elements, your Caché web service or client can access the HeadersIn property. If the SOAP message did not include a <Header> element, the Count() of the HeadersIn property is 0.

Similarly, before your Caché web service or client sends a SOAP message, it must update the HeadersOut property so that it contains any custom elements you want to include in the outbound message. If the HeadersOut Count() is 0, the outbound SOAP message does not include a <Header> element.

generated description: headers out

For custom header elements, you always use the HeadersIn and HeadersOut properties.

The details are different for other (non-custom) header elements:

  • For WS-Addressing, use the AddressingIn and AddressingOut properties rather than the HeadersIn and HeadersOut properties. See the chapter “Adding and Using WS-Addressing Header Elements” later in this book.

  • For WS-Security header elements, use the WS-Policy features, described in Securing Caché Web Services.

    Or directly use the SecurityIn and SecurityOut properties, discussed in the same book. This is generally more work.

    (Note that the WS-Security header elements are also contained in the HeadersIn and HeadersOut properties, b´ut it is not recommended to access them or to set them via those properties.)

  • Caché SOAP session support uses the HeadersIn and HeadersOut properties. See the chapter “SOAP Session Management,” later in this book.

Supported Header Elements

Caché web services and clients automatically support WS-Addressing and WS-Security headers, but do not automatically support other headers.

To specify the supported header elements in a Caché web service or client, you add an XData block to the class and specify the class parameter USECLASSNAMESPACES. The XData block lists the supported elements. The class parameter causes the WSDL to include the applicable types. See “Specifying the Supported Header Elements.”

Header Elements and the WSDL

The WSDL for a web service advertises the header elements supported by that web service and permitted by web clients that communicate with that web service.

For a Caché web service, the generated WSDL might not include information about the SOAP header elements:

  • If you add SOAP headers manually by setting the HeadersOut property, be sure to declare them in an XData block as described in “Specifying Supported Header Elements,” later in this chapter. Also specify the class parameter USECLASSNAMESPACES as 1 in the web service class.

    If you follow these steps, the WSDL contains all the applicable information. Otherwise, it does not, and you must save the WSDL to a file and edit it manually as needed.

  • If you add WS-Security headers by setting the SecurityOut property (as described in Securing Caché Web Services), the WSDL does not include all needed information. (This is because the WSDL is generated at compile time and the headers are added later, at runtime.) In this case, save the WSDL to a file and edit it manually as needed.

    For many reasons, it is simpler and easier to add WS-Security elements by using WS-Policy, as described in the same book. With WS-Policy, the generated WSDL includes all needed information.

  • In other cases, the generated WSDL includes all needed information.

Note that the W3C specifications do not require a web service to provide a generated WSDL.

Required Header Elements

If a given header element specifies mustUnderstand=1, the element is considered mandatory, and the recipient must support it. The recipient cannot process the message unless it recognizes all mandatory header element.

Following the SOAP standard, Caché rejects SOAP messages that contain required but unsupported header elements. Specifically, if Caché web service or client receives a message that contains a header element that includes mustUnderstand=1, and if that service or client does not support that header element, the service or client issues a SOAP fault and then ignores the message.

Defining Custom Header Elements

If you use the SOAP Wizard to create a Caché web service or web client based on a given WSDL, the system generates classes to represent any header elements as needed.

If you create a web service or client manually, you must manually define classes to represent any custom header elements. To do so:

  1. For each custom header element, create a subclass of %SOAP.Header.

  2. Specify the NAMESPACE parameter to indicate the namespace of the header element.

  3. Specify the XMLNAME parameter to indicate the name of the header element.

  4. In the subclass, define properties to contain the header information you need. By default, your properties are projected to elements within your <Header> element.

  5. Optionally specify the XMLFORMAT parameter, which controls the format of this header element. By default, the header elements are always in literal format (rather than SOAP-encoded).

For example:

Class Scenario1.MyHeaderElement Extends %SOAP.Header
{

Parameter NAMESPACE = "http://www.myheaders.org";

Parameter XMLNAME = "MyHeader";

Property Subelement1 As %String;

Property Subelement2 As %String;

}
Copy code to clipboard

This header element appears as follows within a SOAP message:

<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope [parts omitted]>
  <SOAP-ENV:Header>
    <MyHeader xmlns="http://www.myheaders.org"
                     xmlns:hdr="http://www.myheaders.org">
      <Subelement1>abc</Subelement1>
      <Subelement2>def</Subelement2>
    </MyHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
   [omitted]
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Copy code to clipboard

For details on customizing the XML projection of any given object class, see the book Projecting Objects to XML.

For information on the SOAP Wizard, see “Using the SOAP Wizard.”

Adding a Custom Header Element to a SOAP Message

To add custom header elements to a SOAP message (from either the web service or the web client), do the following before sending the SOAP message.

  1. Create an instance of your header object.

  2. Set the properties of that object as appropriate, optionally including the actor and mustUnderstand properties.

  3. Add the new header to the outbound header array, the HeadersOut property. This property is an array with the usual array interface (for example, the SetAt(), Count(), and GetAt() methods).

Note:

If you perform these steps in a utility method, note that the method must be an instance method and must be a member of an instantiable class (not an abstract class, for example).

Then within your web service or client class, you could have a utility method that adds a header element:

Method AddMyHeaderElement(mustUnderstand=0)
{
    Set h=##class(MyHeaderElement).%New()
    Set h.Subelement1 = "abc"
    Set h.Subelement2 = "def"
    If mustUnderstand {Set h.mustUnderstand=1}
    Do ..HeadersOut.SetAt(h,"MyHeaderElement")
}
Copy code to clipboard

Finally, you could call this utility method from each web method where you wanted to use it. For example:

/// Divide arg1 by arg2 and return the result
Method Divide(arg1 As %Numeric, arg2 As %Numeric) As %Numeric [ WebMethod ]
{
    //main method code here
    //...

    do ..AddMyHeaderElement()

    Quit ans
}
Copy code to clipboard

When you invoke this web method, the header is added to the SOAP response.

Specifying Supported Header Elements

Caché web services and clients automatically support WS-Addressing and WS-Security header elements, but do not automatically support other header elements.

To specify the header elements supported by a Caché web service or web client, do the following:

  • Define classes to represent these header elements as described in “Defining Custom Header Elements.”

  • Associate the header element classes with header elements for the web service or web client.

    You can do this in either of two ways:

    • Add an XData block to the web service or client class. In this XData block, specify an association between specific header elements and the corresponding header element classes.

      If the service or client class also sets the class parameter USECLASSNAMESPACES to 1 (the recommended value), then this header information is used in the generated WSDL.

    • In your web service or web client class, specify the SOAPHEADERS parameter. In this parameter, specify an association between specific header elements and the corresponding header element classes.

      Note:

      This technique is less flexible, does not affect the generated WSDL, and is now deprecated.

    The following sections give the details.

Specifying the Supported Header Elements in an XData Block

If you use the SOAP Wizard to create a Caché web service or web client based on a given WSDL, the system generates an XData block in that class to represent any header elements supported in its SOAP messages. (For information on the SOAP Wizard, see “Using the SOAP Wizard.”)

If you create a web service or client manually, you must manually specify this XData block.

The following is a simple example:

XData NewXData1
{
<parameters xmlns="http://www.intersystems.com/configuration">
   <request>
      <header name="ServiceHeader" class="NewHeaders.MyCustomHeader"/> 
   </request>
   <response>
      <header name="ExpectedClientHeader" class="NewHeaders.MyCustomHeader"/> 
   </response>
</parameters>
}
Copy code to clipboard

Details

The requirements for this XData block are as follows:

  • The XData block can have any name. The name (NewXData1 in this case) is not used.

    The SOAP Wizard uses the name parameters when it creates this block.

  • The top level element must be <parameters>

  • The <parameters> element and all its child elements (and their children) must be in the namespace "http://www.intersystems.com/configuration"

  • The <parameters> element can have the following children:

    • <request> — Determines the header elements associated with all request messages, for any header elements that should be the same in all request messages.

      This element should have a child element <header> for each applicable header element.

    • <response> — Determines the header elements associated with all response messages, for any header elements that should be the same in all response messages.

      This element should have a child element <header> for each applicable header element.

    • <methodname> — Determines the header elements associated with the web method whose name is methodname.

      This element can have the following children:

      • <header> — Determines the header elements associated with request and response messages for this web method, for any header elements that should be the same in both cases.

      • <request> — Determines the header elements associated with request messages for this web method.

        This element should have a child element <header> for each applicable header element.

      • <response> — Determines the header elements associated with response messages for this web method.

        This element should have a child element <header> for each applicable header element.

  • In this XData block, each <header> element associates a header element with the Caché class that should be used to represent it. This element includes the following attributes:

    Attribute Purpose
    name Name of the header element.
    class Caché class that represents this header element.
    alias (Optional) Key for this header element in the HeadersIn array of the web service or web client. The default is the value given for the name attribute.

    The position of a <header> element within the XData block indicates the messages to which it applies.

Inheritance of Custom Headers

If you create a subclass of this web service, that subclass inherits the header information that is not specific to a method — the header information contained in the <request> or <response> elements that are direct child elements of <parameters>. This is true even if SOAPMETHODINHERITANCE is 0.

Examples

Another example is as follows:

XData service
{
<parameters xmlns="http://www.intersystems.com/configuration">
  <response>
    <header name="Header2" class="User.Header4" alias="Header4"/>
    <header name="Header3" class="User.Header3"/>
  </response>
  <method name="echoBase64">
    <request>
      <header name="Header2" class="User.Header4" alias="Header4"/>
      <Action>http://soapinterop.org/Round2Base.Service.echoBase64Request</Action>
    </request>
    <response>
      <header name="Header2" class="User.Header2" alias="Header2"/>
      <header name="IposTransportHeader" class="ipos.IposTransportHeader"/>
      <Action>http://soapinterop.org/Round2Base.Service.echoBase64Result</Action>
    </response>
  </method>
  <method name="echoString">
    <request>
      <Action>http://soapinterop.org/Round2Base.Service.echoStringRequest</Action>
    </request>
    <response>
      <Action>http://soapinterop.org/Round2Base.Service.echoStringAnswer</Action>
    </response>
  </method>
</parameters>
}
Copy code to clipboard

Specifying the Supported Header Elements in the SOAPHEADERS Parameter

The older way to specify supported header elements is to include the SOAPHEADERS parameter in the web service or web client class.

This parameter must equal a comma-separated list of header specifications. Each header specification has the following form:

headerName:headerPackage.headerClass
Copy code to clipboard

Where headerName is the element name of the supported header and headerPackage.headerClass is the complete package and class name of a class that represents that header. For example:

Parameter SOAPHEADERS = "MyHeaderElement:Scenario1Client.MyHeaderElement" 
Copy code to clipboard

This list identifies all headers supported in the SOAP requests to this web service or client and indicates the class to which each one is mapped.

If you use this older technique, note the following points:

  • For a web service, this technique does not affect the generated WSDL.

  • It is not possible to specify different header elements for specific web methods.

  • The SOAP Wizard no longer generates the SOAPHEADERS parameter in your generated web service and client classes.

  • This technique is deprecated.

Inheritance of Custom Headers

If you create a subclass of this web service, that subclass inherits the SOAPHEADERS parameter. This is true even if SOAPMETHODINHERITANCE is 0.

Using Header Elements

To use specific SOAP header elements after receiving a request message, use the HeadersIn property of the service or client.

For each supported header element, the service or client creates an instance of the appropriate header class and adds the header to the inbound header array, which is the HeadersIn property. This property is an array with the usual array interface (for example, SetAt(), Count(), and GetAt() methods). The web service or web client can then act on these headers as appropriate.

Note:

The header element namespace is not used for matching the header element in the list. However, the header element namespace in the SOAP message must be the same as specified by the NAMESPACE parameter in your header element subclass; otherwise, an error occurs when the message is imported.