Creating Web Services and Web Clients
Adding and Using Custom Header Elements
|
|
This chapter describes how to add and use custom SOAP header elements.
This chapter discusses the following:
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>
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.
When an InterSystems IRIS 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, InterSystems IRIS 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:
To use these header elements, your InterSystems IRIS 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 InterSystems IRIS 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.
The details are different for other (non-custom) header elements:
-
-
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.)
-
InterSystems IRIS 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 an InterSystems IRIS 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.”
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 an InterSystems IRIS web service, the generated WSDL might not include information about the SOAP header elements:
-
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 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.
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, InterSystems IRIS rejects SOAP messages that contain required but unsupported header elements. Specifically, if InterSystems IRIS 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.
If you use the
SOAP Wizard to create an InterSystems IRIS 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:
-
-
Specify the
NAMESPACE parameter to indicate the namespace of the header element.
-
Specify the
XMLNAME parameter to indicate the name of the header element.
-
In the subclass, define properties to contain the header information you need. By default, your properties are projected to elements within your
<Header> element.
-
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).
Class Scenario1.MyHeaderElement Extends %SOAP.Header
{
Parameter NAMESPACE = "http://www.myheaders.org";
Parameter XMLNAME = "MyHeader";
Property Subelement1 As %String;
Property Subelement2 As %String;
}
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>
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.
-
Create an instance of your header object.
-
Set the properties of that object as appropriate, optionally including the
actor and
mustUnderstand properties.
-
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")
}
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
}
When you invoke this web method, the header is added to the SOAP response.
InterSystems IRIS 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 an InterSystems IRIS web service or web client, do the following:
-
-
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.
If you use the
SOAP Wizard to create an InterSystems IRIS 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>
}
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.
-
-
-
-
<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.
-
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 InterSystems IRIS class that should be used to represent it. This element includes the following attributes:
The position of a
<header> element within the XData block indicates the messages to which it applies.
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.
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>
}
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
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"
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.
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.
Content Date/Time: 2019-02-20 00:55:51