Working with SOAP attachments using Mule’s CXF module

It is pretty common that you may need to add/extract attachments when working with SOAP based Web services (WS). In this short blog post we explain how to do it using Mule’s CXF module.

Receive and extract attachments

When you are receiving a SOAP message, the first thing you must know is that Mule does not copy SOAP attachments to your Mule message. If you want to do so, you will need to add a special CXF interceptor to do it (CopyAttachmentInInterceptor). The next code snippet shows how to add that interceptor:

All the attachments are copied to the cxf_attachments INVOCATION property of the message. Notice that the value of that property is a COLLECTION of attachments. To work with attachments you can use the expression transformer, for example the following code snippet extract the contents of the first attachment of the list and sets it as the current payload of the message:

Add attachments and send

On the other hand, if you want to send attachments to a WS you will need to create the cxf_attachments property and then use the CopyAttachmentOutInterceptor interceptor to copy those attachments to the SOAP message. The following code snippet adds an attachment and calls the WS:

The AddAttachmentMessageProcessor class is responsible of creating the attachments collection and set it in the cxf_attachments property. The class itself is pretty simple, just adds the attachments as a property of the message:

Hope you like the post!
Cheers


26 Responses to “Working with SOAP attachments using Mule’s CXF module”

  • mathaj Says:

    Hi,

    Can you publish the wsdl i wanted to see the response. I have a similar requirement of sending an attachment which could be pdf,rtf,xls or html format. Any help will be greatly appreciated

  • Esteban Robles Luna Says:

    Hi Mathaj,
    I didn’t have a WSDL as it was part of some work I did for an ACORD server.
    If you need to send an attachment, then the “Add attachments and send” scenario should be enough
    Cheers

  • mathaj Says:

    Can you please pass me the mule configuration file where you have configured the processors AddAttachmentMessageProcessor it will help to understand a lot

  • Esteban Robles Luna Says:

    Sure,
    Check the following flow: https://gist.github.com/1089481

  • mathaj Says:

    Thanks Esteban that helped
    One more query i wanted the attachment to be added during the web service response. But now i see it been called when i submit the web service request.

  • Patryk Says:

    Hi, I found your article very interesing. I have a question about it. I am using cxf:jaxws-client component sending request to outbound-endpoint. In response I should have attachment. I have slightly changed the first approach from you article (but unfortunately it doesn’t work) :

  • Esteban Robles Luna Says:

    Hi Patryk,
    Could you give me more details? I will try to help you. Probably in the response you may have to use a CopyAttachmentOutInterceptor
    Cheers

  • jm Says:

    Hello Esteban,
    I’m consuming a remote WS using cxf:jaxws-client and getting a SOAP MTOM response. I tried to get the attachment using the in and out interceptor without success…
    Do you have any idea how I can deal with it?

    • Esteban Robles Luna Says:

      Hi Jm,
      The cxf:jaxws-client automatically process the response according to the WS annotations of your service. Have you enabled the mtomEnabled attribute in cxf:jaxws-client?
      Check mtom-client-conf.xml
      HTH

      • jm Says:

        Hi Esteban,
        Thanks for your quick answer. Actually I’ve disabled the mtom feature because I have a “org.apache.commons.httpclient.ProtocolException: Unbuffered entity enclosing request can not be repeated” exception when using it…

        • Esteban Robles Luna Says:

          Hi,
          The exception is a bit rare; a couple of things I would do in your case:
          - Download the sources of Mule. If you use maven just run mvn eclipse:eclipse -DdownloadSources.
          - Put a couple of break points at the http client level
          - Send an email to the Mule list.

          After checking a bit in the web it seems to be a problem in the way the WS responded to you. Check http client problem

          HTH
          Esteban

      • jm Says:

        Hi Esteban,
        Finally found out what was wrong… It was a firewall issue at server side.
        However, my attachment is still not extracted in the response and using in logging interceptor, i’m not able to see anything… Any idea?
        Jm

        • Esteban Robles Luna Says:

          Hi JM,
          Mule’s CXF module is just a wrapper on the top of CXF so you will be able to check and manipulate your SOAP message creating a custom interceptor.

          If I were you I will follow this process:
          - Create a new CXF interceptor (you can use the CopyInAttachments as a template)
          - Put a breakpoint when the interceptor is invoked
          - Use the Eclipse display to get the attachments from the SOAP message, if the attachments are there that’s great, if they are not there you will have to check the application that is invoking yours and in the worst case see the raw message.
          - If the attachments are there then, it is possible that the copyin interceptor is copying the attachments but you are not able to get them from the mule message properties. You can quickly fix it by creating your own custom interceptor and copy the attachments manually.

          HTH
          Esteban

  • David Dossot Says:

    One thing that puzzles me is why aren’t outbound MuleMessage attachments used directly instead of an invocation property named CxfConstants.ATTACHMENTS? Weren’t native MuleMessage attachments good enough?

    • Esteban Robles Luna Says:

      Hi David,
      When I tried it (version 3.1.2) if you don’t set the attachments to CxfConstants.ATTACHMENTS, the CopyAttachmentOutInterceptor won’t send the soap message with the attachments. Mule was not picking the full list of attachments of the message unless you set this property.
      Maybe Dan D can answer about the design
      Cheers

  • Edward Says:

    Good article Esteban, we have been trying to work this out for a while. We will give a shot and see what our out come is?

    Edward Odufuwa

    • Esteban Robles Luna Says:

      Hi Edward,
      Let me know if I can help you if my approach doesn’t work in your case
      Hope everything is OK in the UK
      Cheers
      Esteban

  • Behnaz Says:

    Hi Esteban,

    In MULE 3.3.0, I created “AddAttachmentMessageProcessor” class but I have problem with this line
    ” Collection attachments = new ArrayList(); ” for solution when I click on the red bullet next to this line MULE suggest to me create class Attachment.

    What is the Attachment class?

  • Behnaz Says:

    These are all the “import classes” in “AddAttachmentMessageProcessor” class:

    import java.io.IOException;

    import javax.activation.DataSource;

    import org.apache.axiom.attachments.ConfigurableDataHandler;
    import org.apache.cxf.attachment.AttachmentImpl;
    import org.mule.api.MuleEvent;
    import org.mule.api.MuleException;
    import org.mule.api.processor.MessageProcessor;
    import org.mule.module.cxf.CxfConstants;
    import org.mule.util.IOUtils;

    import com.sun.istack.ByteArrayDataSource;

    But what is “the CXF attachment class”?

  • Behnaz Says:

    This is my “AddAttachmentMessageProcessor” class:

    ———————————————-

    import java.io.IOException;

    import javax.activation.DataSource;

    import org.apache.axiom.attachments.ConfigurableDataHandler;
    import org.apache.cxf.attachment.AttachmentImpl;
    import org.mule.api.MuleEvent;
    import org.mule.api.MuleException;
    import org.mule.api.processor.MessageProcessor;
    import org.mule.module.cxf.CxfConstants;
    import org.mule.util.IOUtils;

    import com.sun.istack.ByteArrayDataSource;

    /*
    * $Id$
    * ————————————————————————————–
    * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
    *
    * The software in this package is published under the terms of the CPAL v1.0
    * license, a copy of which has been included with this distribution in the
    * LICENSE.txt file.
    */

    public class AddAttachmentMessageProcessor implements MessageProcessor
    {
    @Override
    public MuleEvent process(MuleEvent event) throws MuleException
    {
    Collection attachments = new ArrayList();

    AttachmentImpl attachment = new AttachmentImpl(“1″);
    String attachmentXML = “”;

    try
    {
    attachmentXML = IOUtils.getResourceAsString(“attachment.xml”, this.getClass());
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }

    DataSource source = new ByteArrayDataSource(attachmentXML.getBytes(), “text/xml”);
    attachment.setDataHandler(new ConfigurableDataHandler(source));

    attachments.add(attachment);

    event.getMessage().setInvocationProperty(CxfConstants.ATTACHMENTS, attachments);
    return event;
    }

    }

  • Jeff Thorn Says:

    Thank you! I have been trying to figure out how to do this for days. I could not find this information in any documentation anywhere. How did you figure out that you had to use the CopyAttachment Interceptor? This is not documented anywhere. You’d think that normal MuleMessage attachments would get mapped automatically.

    • Esteban Robles Luna Says:

      Hi Jeff,
      I used to work @ Mulesoft and I ran into the same issues.
      The best approach is to get all the sources and dig into the code until you see it clearly. So get all the code and cross your fingers :)
      Cheers
      Esteban

  • Hirak Sarkhel Says:

    Your solution worked wonders.You blog helped us save a lot of time and helped us to get pass the road block we were faced with sending and receiving attachments in mule.

    Thanks again for the post.

Leave a Reply