views:

62

answers:

1

I've been working on creating a SAAJ based client. Everything seemed to be working fine, until I implemented the logic to send attachments as part of a web-service request.

The web-service operation is simple - it expects a string element for file-location, and a base64binary element for the file content.

I've tested the ws operation using SoapUI, and everything seems to be in order. However, when i send the file attachment from my SAAJ-based client, the web-service operation would only receive the file-location element's value. I wrote a handler at the ws-server to intercept the WS operation request, in order to see whether the attachment even reaches the web-service. As expected, the attachment was reaching fine, and i could access its contents using the SAAJ api within the handler.

That just leads me to wonder - is there any compatibility issue when sending attachments using SAAJ and receiving them through JAXB bindings? is there something i'm missing out?

thanks for any help!

+1  A: 

You need to ensure that an AttachmentUnmarshaller is registered on your Unmarshaller to receive attachments in JAXB.

import javax.activation.DataHandler;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.attachment.AttachmentUnmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jaxbContext = JAXBContext.newInstance(Demo.class);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        unmarshaller.setAttachmentUnmarshaller(new MyAttachmentUnmarshaller());
    }

    private static class MyAttachmentUnmarshaller extends AttachmentUnmarshaller {

        @Override
        public DataHandler getAttachmentAsDataHandler(String cid) {
            // TODO - Lookup MIME content by content-id, cid, and return as a DataHandler.
            ...
        }

        @Override
        public byte[] getAttachmentAsByteArray(String cid) {
            // TODO - Retrieve the attachment identified by content-id, cid, as a byte[]
            ...
        }

    }

}
Blaise Doughan
how does one ensure that? also, if an AttachmentUnmarshaller is not registered, then how come the attachments sent through SoapUI got resolved correctly?
anirvan
Are you using a generated client or a hand written client with your service?
Blaise Doughan
The client is a hand-written one, based on SAAJ. Since the client will need to interface w/ many web-services, we can't simply generate bindings specific to any particular WSDL.
anirvan
Are you sure that when the message is sent through SoapUI that the attachments aren't being inlined?
Blaise Doughan
yeah - i've enabled MTOM, and also checked the RAW XML that it sends. the attachment is separated from the SOAP body and linked using the "cid:xxxxxxx" identifier. also, appreciate the approach you've described above. however, that cannot work in my case, since i cannot impose/insist the web-service developers to make any implementation changes.
anirvan
Do you have access to the Unmarshaller to set an AttachmantUnmarshaller that you have created to relate the cid to an actual attachment? This is the only means by which JAXB can resolve attachments. Note: I'm part of the JAXB expert group that designed this JAXB behaviour in conjunction with the JAX-WS expert group.
Blaise Doughan
well that's a comforting thought :] as for access to the unmarshaller, the answer is 'no'. i can only control all aspects related to the client that i'm developing. since i create the soap requests using SAAJ, i simply rely on its API to associate elements to their corresponding attachments using cid. i am NOT using any JAXB related classes in my client. i'll probably rummage through soapUi's source to see what those guys are upto.
anirvan
My mistake, for some reason thought you had JAXB on the client. The same thing happens the server only JAX-WS will automatically pass the JAXB layer an AttachmentUnmarshaller. For some reason outside of JAXB the JAX-WS layer is not receiving your attachment.
Blaise Doughan
blaise - i did some thorough analysis of the behaviour of my client vis-a-vis SoapUI. so with MTOM enabled in SoapUI, it correctly separates the attachment content from the soap body. i verified this using Fiddler too. however, in the web-service handler, when i get the SOAP request printed, i see that the attachment content is placed inline as well as in the separate 'part'. when using my SAAJ client, the request printed by the handler shows that the content is in the separate 'part' without any inline data.
anirvan
WRT JAXB, if the content is inlined JAXB will unmarshal it. If the content is available through a CID JAXB will defer to the AttachmentUnmarshaller for the content. From the results of your investigation your problem is occuring with JAX-WS and not JAXB.
Blaise Doughan
so i guess it's a problem with the JAXWS implementation, which happens to be Sun-RI in this particular case. Blaise, i can't possibly thank you enough for being so patient and persistent in helping me resolve this. you're a *. One last thing - what would be your suggestion to handle this kind of a scenario? send the content inline anyway through the SAAJ client? is there any way to detect if the service end-point has the correct unmarshaller and then attach accordingly?
anirvan
Blaise Doughan