Search code examples
javasoapmime

How to change Mime Headers of SOAP message using Java


I have to change Mime header for SOAP request, especially the 'content type' header, my code is already working for most of headers, but for some reason I get back the old value for the content type header:

Here is the simplified code with comments:

public static synchronized SOAPMessage sendSoapRequest(String endpointUrl, SOAPMessage request) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
SOAPMessage response = null;


HashMap<String,String> headers =  ConfigManager.GetInstance().GetHeaders(); 

int number_of_retries = ConfigManager.GetInstance().GetNumberOfAttempts();
if (number_of_retries==0)
  {
    number_of_retries = 10;
  }

for (int i = 0; i <=number_of_retries ; i++) {
 try {

    
    // Send HTTP SOAP request and get response
    SOAPConnection soapConnection
            = SOAPConnectionFactory.newInstance().createConnection();
    ***// here I have mime headers with "Content-Type: text/xml; charset=utf-8"***
    if (headers != null)
        {
        Iterator it = headers.entrySet().iterator();
        while (it.hasNext()) {
            HashMap.Entry pair = (HashMap.Entry)it.next();
           
            // request.getMimeHeaders().addHeader(pair.getKey().toString(),  pair.getValue().toString());
            request.getMimeHeaders().setHeader(pair.getKey().toString(), pair.getValue().toString()); ***// I set here: "Content-Type => application/soap+xml"***
          
            }
        request.saveChanges();   ***// I got back mime headers with "Content-Type: text/xml;*** charset=utf-8"
        }
   

    response = soapConnection.call(request, endpointUrl); ***// If I don't use request.saveChanges(), I also get back mime headers with "Content-Type: text/xml; charset=utf-8"***
    // Close connection
    soapConnection.close();
   
    return response;
  } 
 }
 return null;
}

I don't understand why Content-Type is set back to 'text/xml; charset=utf-8' and how to fix it.


Solution

  • From the code you have and the comment, it seems to me that you are using SAAJ to make a SOAP call to a SOAP 1.2 endpoint and your attempt to set the correct content type is conflicting with whatever SAAJ is doing behind the scenes.

    SAAJ allows you to work with an object tree while handling the SOAP details for you. By default it knows to work with SOAP 1.1. The main thing to note here is that for SOAP 1.1. the content type is text/xml and the SOAP XML namespace is http://schemas.xmlsoap.org/soap/envelope/.

    You want to send application/soap+xml which is the content type for SOAP 1.2. The SOAP XML namespace will in this case be http://www.w3.org/2003/05/soap-envelope.

    So even if you manage to set the desired content type, your XML message created by SAAJ will still be wrong because it will have the namespace of SOAP 1.1. because that's the default.

    If you want to call a SOAP 1.2. endpoint you need to tell SAAJ that. Your SAAJ object tree is probably built by using a MessageFactory which has a default instantiation of SOAP 1.1. with:

    MessageFactory mf = MessageFactory.newInstance();
    

    If you need SOAP 1.2. you need to tell SAAJ that with this instead:

    MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    

    If you do that you will still have the issue with the content type, but this time it will be SAAJ setting application/soap+xml (which is what you want) and also set the proper XML SOAP namespaces within the message.