Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse XOP/MTOM SOAP response using java?

Tags:

java

soap

cxf

mtom

xop

I just want to know, is there any simple way for parsing MTOM/XOP SOAP response. The problem is that I use plain HTTP to send soap message and javax.xml for parsing response. But some services responds me with mulipart/related and it requires much more complex logic to parse it (performance matters). So I wonder may I somehow take advantage of apache cxf, apache axiom or any other library for parsing MTOM/XOP SOAP response?

like image 826
Oleg Kandaurov Avatar asked Aug 09 '13 15:08

Oleg Kandaurov


3 Answers

These unit tests show you how to use CXF to extract attachments out of an MTOM message. I'll inline one of the tests in case this link doesn't exist in the future:

private MessageImpl msg;

@Before
public void setUp() throws Exception {
    msg = new MessageImpl();
    Exchange exchange = new ExchangeImpl();
    msg.setExchange(exchange);
}

@Test
public void testDeserializerMtom() throws Exception {
    InputStream is = getClass().getResourceAsStream("mimedata");
    String ct = "multipart/related; type=\"application/xop+xml\"; "
                + "start=\"<[email protected]>\"; "
                + "start-info=\"text/xml; charset=utf-8\"; "
                + "boundary=\"----=_Part_4_701508.1145579811786\"";

    msg.put(Message.CONTENT_TYPE, ct);
    msg.setContent(InputStream.class, is);

    AttachmentDeserializer deserializer = new AttachmentDeserializer(msg);
    deserializer.initializeAttachments();

    InputStream attBody = msg.getContent(InputStream.class);
    assertTrue(attBody != is);
    assertTrue(attBody instanceof DelegatingInputStream);

    Collection<Attachment> atts = msg.getAttachments();
    assertNotNull(atts);

    Iterator<Attachment> itr = atts.iterator();
    assertTrue(itr.hasNext());

    Attachment a = itr.next();
    assertNotNull(a);

    InputStream attIs = a.getDataHandler().getInputStream();

    // check the cached output stream
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    IOUtils.copy(attBody, out);
    assertTrue(out.toString().startsWith("<env:Envelope"));

    // try streaming a character off the wire
    assertTrue(attIs.read() == '/');
    assertTrue(attIs.read() == '9');
}

In your case, the ct will come from the content type header of the response. The "mimedata" will be the content of the response.

like image 170
Daniel Kaplan Avatar answered Nov 18 '22 21:11

Daniel Kaplan


No need to use CXF, the standard javax.mail.internet.MimeMultipart class do the job and it's very easy to use (also to create MTOM request).

Here a very simple sample to decode parts of a MTOM response:

MimeMultipart mp = new MimeMultipart(new ByteArrayDataSource(data, contentType));
int count = mp.getCount();
for (int i = 0; i < count; i++) {
    BodyPart bp = mp.getBodyPart(i);
    bp.saveFile(filepath + "_" + i);
}
like image 39
Nicolas Albert Avatar answered Nov 18 '22 21:11

Nicolas Albert


I had same issue and solved as @Nicolas Albert

public byte[] mimeParser(InputStream isMtm) {
    ByteArrayOutputStream baos = null;
    try {
        MimeMultipart mp = new MimeMultipart(new ByteArrayDataSource(isMtm,
                ct));
        int count = mp.getCount();
        baos = new ByteArrayOutputStream();
        for (int i = 0; i < count; i++) {
            BodyPart bodyPart = mp.getBodyPart(i);
            if (!Part.ATTACHMENT
                    .equalsIgnoreCase(bodyPart.getDisposition())
                    && !StringUtils.isNotBlank(bodyPart.getFileName())) {
                continue; // dealing with attachments only
            }
            bodyPart.writeTo(baos);
        }

        byte[] attachment = baos.toByteArray();
        FileUtils.writeByteArrayToFile(new File("E:/wss/attachment.zip"), attachment);
        return attachment;
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        if (baos != null) {
            try {
                baos.close();
            } catch (Exception ex) {

            }
        }
    }
    return null;
}
like image 25
Winston Avatar answered Nov 18 '22 21:11

Winston