简体   繁体   中英

Can't get PDF from SOAP with MTOM using jax-ws

I'm trying to get hold of a PDF returned from a web service call. With SoapUI and other logging I can see that the PDF is attached in the reply. But my attempts to get hold of the PDF fails. The DataHandler for the PDF contains no data.

// Call prepared and executed. result is returned object filled from sub-system.
System.out.println("Some value = " + result.getSomeValue());

DataHandler dh = result.getAttachedPDF();
OutputStream fos=new FileOutputStream("/tmp/out.pdf");
dh.writeTo(fos);
fos.close();

So the file /tmp/out.pdf is empty. Writing the PDF using a buffer yields same result:

InputStream inputstream = dh.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while( (bytesRead = inputstream.read(buffer)) != -1) {
    System.out.println("Read " + bytesRead);
    fos.write(buffer);
}
fos.close();

I've tried to explicit enable MTOM in my client three different ways:

// First enabling
port = service.getPort(new MTOMFeature(true));

// Second enabling
Map<String, Object> ctxt = bp.getRequestContext();
ctxt.put("com.sun.xml.internal.ws.transport.http.client.streaming.chunk.size", 8192);

// Third enabling.
SOAPBinding binding = (SOAPBinding) bp.getBinding();
if( binding.isMTOMEnabled()) {
    System.out.println("MTOM enabled");
} else {
    binding.setMTOMEnabled(true);        
    System.out.println("MTOM NOT enabled");
}

I get "MTOM enabled" whether I use way 1 or 2 or not.

I've run the call inside a debugger (netbeans) and examined the 'result' object. All fields for the DataHandler is empty or having the value 0.

I tried to import the wsdl-file into a project in Eclipse. I abandoned that road when Eclipse reported multiple errors inside the generated source. Instead I let SoapUI generate classes (wsimport and wsdl2java) and used that along with my code. I achieved same result, empty PDF.

Using a SOAPHandler to intercept the messages as suggested here: http://java.globinch.com/enterprise-java/web-services/jax-ws/logging-tracing-web-service-xml-request-response-jax-ws/

The intercepted message I've saved and stored to file and is able to save each part.

Not sure where to go from here. I do feel that there are some bits that I've missed.

This is the actual code public static void main(String[] args) throws Exception { SVVCommonHeaderType header = new SVVCommonHeaderType(); header.setSystemId(SYSTEM_ID); header.setBrukerId("users name"); header.setHendelsesId(UUID.randomUUID().toString());

    GetKontrollseddel gs = new GetKontrollseddel();
    gs.setKontrollseddelNr(new BigInteger("3000036367"));

    Kontrollseddel2 service = new Kontrollseddel2();
    Kontrollseddel2PortType port = service.getKontrollseddel2Port(new MTOMFeature(true));
    BindingProvider bp = (BindingProvider) port;

    Map<String, Object> ctxt = bp.getRequestContext();
    ctxt.put("com.sun.xml.internal.ws.transport.http.client.streaming.chunk.size", 8192);
    ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, ENDPOINT_ADDRESS);
    ctxt.put(BindingProvider.USERNAME_PROPERTY, username);
    ctxt.put(BindingProvider.PASSWORD_PROPERTY, password);

    SOAPBinding binding = (SOAPBinding) bp.getBinding();
    if( binding.isMTOMEnabled()) {
        System.out.println("MTOM enabled");
    } else {
        binding.setMTOMEnabled(true);        
        System.out.println("MTOM NOT enabled");
    }

    GetKontrollseddelResponse resp = port.getKontrollseddel(gs, header);
    DataHandler dh = resp.getKontrollseddel2().getKontrollseddelPDF();
    OutputStream fos=new FileOutputStream("/tmp/out.pdf");
    dh.writeTo(fos);

    // Alternative way to write, same result
    /*
    InputStream inputstream = dh.getInputStream();

    byte[] buffer = new byte[1024];
    int bytesRead;
    while( (bytesRead = inputstream.read(buffer)) != -1) {
        System.out.println("Read " + bytesRead);
        fos.write(buffer);
    }
    */

    fos.close();
}

Edit: As a workaround I've added code in the logging class that extracts the PDF. The handleMessage() looks like

@Override
public boolean handleMessage(SOAPMessageContext arg0) {
    SOAPMessage message= arg0.getMessage();
    boolean isOutboundMessage=  (Boolean)arg0.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);

    if(!isOutboundMessage){
        Iterator iter = message.getAttachments();
        while( iter.hasNext()) {
            AttachmentPart part = (AttachmentPart) iter.next();
            try {
                attachmentInputstream = (InputStream) part.getContent();
            } catch(Exception ex) {
                System.out.println("Exception in handling attachment");
                ex.printStackTrace(System.out);
                attachmentInputstream = null;
            }
        }
    }

    return true;
}

If this workaround is to be used, I've got to add some additional handling code. I'll decide later.

It turned out that the reason for the problem was that there were some firewall at senders side the did some rewriting of the SOAP attachment. This confused jax-ws while SoapUI processed the message anyway.

The answer I got from the producer of the message was that they had a proxy that turned the header from XOP to text while MTOM need to be XOP.

With this in place, my code worked flawless.

I was facing the same issue while calling my JAX-WS webservice. My response was supposed to send back the pdf file as attachment along with binary data. Thanks to below blog for helping me to fix the issue.

https://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-attachment-enable-mtom-jax-ws-web-services/

My problem was, i missed to add @MTOM annotation on my jax-ws service.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM