2008/07/25
25 Jul, 2008

Understand the Famous "Did not understand MustUnderstand header(s)" Error

  • Eran Chinthaka
  • Software Engineer - WSO2

Within Axis2, repercussions of not understanding some of these mustUnderstand headers is common, especially in those ciscumstances when you try to use add-on modules with Axis2. This article describes the mustUnderstand header field and goes on to explain the cause of such errors. The article also looks at what happens inside Axis2, as such errors are encountered and how some of it can be fixed with minimal effort.

Table of Contents

Introduction

One of the most common errors you encounter with Axis2 in terms of SOAP headers is the "Did not understand MustUnderstand header(s)" error. The most common reason for such an error to pop up is when your server is missing a module required to process your SOAP message. Even though the answer to this question is so simple, it is worthwhile looking into the details of this error to find out what goes on behind the cover that results in this error.

Applies To

Project/lan Axis2

Understanding the Error

SOAP specifications define two parts that goes within a SOAP envelope. They are (a.) the mandatory <body> element and (b.) the optional <header> element. Information encapsulated within a <header> element are mostly destined to the SOAP processing engine than to the real application logic behind the Web service you are invoking. If you do not send your SOAP headers in a certain manner, SOAP processor has the option to either "understand" the given information or ignore them. The meaning of "understanding" here means, that SOAP processor processes the information and optionally carry out certain special tasks depending on that. At times clients may have a requirement to emphasize some of the information encapsulated within SOAP headers. As a result, there exists a requirement for clients to force processing headers by various SOAP engines.

The trick is to set the "mustUnderstand" attribute in the SOAP header to "true" (or to "1"), whenever you want the SOAP processor to understand.

<env:Envelope xmlns:env="https://www.w3.org/2003/05/soap-envelope" > 
	<env:Header>
 		<MyHeader xmlns:t="https://example.org/2001/06/tx" 
                env:mustUnderstand="true">
   		You must understand me. 
 		</MyHeader>
	</env:Header>
	<env:Body>
	............
	</env:Body>
</env:Envelope >

According to SOAP 1.2 specification, when a SOAP processor receives a SOAP message with a header that reads mustUnderstand="true" or mustUnderstand="1" (both are semantically referring to the same), then, the SOAP processor must process that header. If it cannot, it should fault without reading the rest of the message. But there is a tricky exception to the above rule that might not prop up most of the time. Let's first see what that is:

SOAP headers could also have an attribute that identifies the SOAP node that particular SOAP header is destined for. In SOAP 1.1, this was referred to as "actor" and in 1.2, this is renamed as "role". At most times message exchanges only involve client and server only, and we don't have to use this attribute explicitly. When we are carry out message exchanges involving multiple parties, then, SOAP processors may receive SOAP headers, with a different values in the "role" field. This means, that a particular SOAP header is destined to a different SOAP node. In these cases, even though the SOAP header contains "mustUnderstand=true", a SOAP node can ignore it. Unfortunately, this can also happen with the "UltimateReceiver" (UltimateReceiver being the final destination of a given SOAP message). In other words, the final SOAP endpoint might receive a SOAP header, with mustUnderstand attribute set to false, and also the role value set to a different one than UltimateReceiver (this can happen due to faulty SOAP nodes in-between the communication path). SOAP 1.2 specification clearly states that this cannot be regarded as an error within the SOAP endpoint.

What is Happening within Axis2

Having understood all the above, now let's see what Axis2 is doing with this error condition. As you might already know, Axis2 has a handler architecture. All the SOAP messages received are sent through the registered handlers before handing over the SOAP request to the service implementation. One of the responsibilities of these handlers are to process SOAP headers. Having processed the relevant SOAP headers, those handlers clear the mustUnderstand flags of the relevant SOAP headers. At the end of the pipe, if there are more headers left, with mustUnderstand attribute set to true, then following the SOAP specification, Axis2 sends out a fault to the client with the message "Did not understand MustUnderstand header(s)".

Common Causes for the Error

If you receive an errors like this from Axis2, there can be two things causing this error.

  1. Your SOAP request uses another WS-* Specification and the code which handles that particular specifation has added some headers with mustUnderstand set to true. For example, you must have enable WS-Security within client side, and WS-Security client handlers put some mustUnderstand headers in to the SOAP message. But if the server, you send your SOAP message, has not got WS-Security deployed within it, then you will get this error. The obvious reason is that the mustUnderstand header you sent, can not be processed on the server, as it doesn't have the proper handlers (in the above example, WS-Security handlers) to understand those headers.
  2. You might be setting mustUnderstand headers, randomly. You can set mustUnderstand attribute, within your client code to some SOAP headers. But if these are not standard headers, then you can not expect Axis2 server to understand them. This also will send out the above error.

When a SOAP node generates a fault with a Value of Code element (faultcode in SOAP 1.1) set to "env:MustUnderstand", it SHOULD provide NotUnderstood SOAP header blocks in the generated fault message. So When you get this error next time, you can look in the SOAP header blocks to see who the culprit is.

How to Fix the Error

As we mentioned earlier, there are different reasons for the error and let's look at some of the possibilities of it being fixed or debugged.

  1. If you are not setting the mustUnderstand headers yourself: On the client side, it can be that one of the modules you are using on the client side are setting the headers. You could either find out what these modules are or you could look at SOAP fault message that you receive. As mentioned before, these should have information as to what is causing the error. You could then find out the module associated with a relevant header preferably by referencing the namespace associated or by using header name and checking the module handling the specific header.

    For example, it could be that you are engaging WS-Security on your side (for the purpose of enabling WS-Security support for your SOAP messages), but the server-side has no WS-Security module engaged (but in this case, you will get a different error to say WS-Security is not engaged, then the server side might not even be able to decrypt the message) or it could be that there are configuration errors.

  2. If you are setting the mustUnderstand headers: In this case you must have corresponding handlers engaged in the server side to process these headers. Once those handlers are complete processing the SOAP headers, they need call the setProcessed() function for each of the SOAP header block they process. The must understand checker within Axis2 checks this flag for all SOAP headers that comes with the mustUnderstand value turned on.

    public class MyHandler implements Handler {
    
    // other code here
    
    	public InvocationResponse invoke(MessageContext msgContext) throws AxisFault{
          
          // process the message with relevant headers
                
      		// for each header this handler processed
      		headerBlock.setProcessed();
    	}
    }
    

    Setting the processed flag within a custom handler for processed headers.

    If any of the "mustUnderstand" headers are not being processed, Axis2 throws the well-known "Did not understand MustUnderstand header(s)" error.

    If you want to set or unset the mustUnderstand headers manually, you need to get hold of the SOAP envelope (irrespective of whether you are on the client side or the server side). Then navigate to the SOAP header block, you want the mustUnderstand value to be set and call setMustUnderstand(boolean) method.

    The following code fragment illustrated how you could add a new SOAP header with mustUnderstand header set:

    SOAPEnvelope envelope = // get access to SOAP envelope here
    SOAPHeaderBlock soapHeaderBlock =
                    envelop.getHeader().addHeaderBlock(omElementToadd.getLocalName(),omElementToadd.getNamespace());
    soapHeaderBlock.setMustUnderstand(true);
    

Summary

This article explains the use of mustUnderstand headers and what makes the "Did not understand MustUnderstand header(s)" error to occurr with detailed explanations on certain tricky areas. It also explains how Axis2 handles such errors and what you as the user should be doing to fix them.

Author

Author : Eran Chinthaka, Member-Apache Software Foundation. eranXchinthakaYgmail.com, where X=. and Y=@

 

About Author

  • Eran Chinthaka
  • Software Engineer
  • WSO2 Inc.