Question

I'm trying to do very simple thing : a Client invokes a SOAP service via its WSDL to load a PDF document.

I'm using Apache CXF 2.7.5 and MTOM

The problem is that it seems that the document isn't completely sent to the client (file size doesn't equal the original) and so, ADOBE isn't able to open it as it's corrupted.

Both my unit test and SOAPUI invokation failed.

If the title of the question has to be improved you're welcome

Thanks in advance.

Service interface

@WebService
@DataBinding(value = JAXBDataBinding.class)
public interface DocumentService {
    @WebMethod(operationName = "getContent")
    DocumentContentVO getContent(@WebParam(name = "documentId") String documentId);
}

Service Implementation

@WebService(endpointInterface = "com.*.*.ws.sei.DocumentService", portName = "DocumentPort")
public class CXFDocumentService extends AbstractCommonService implements DocumentService {
@Override
public DocumentContentVO getContent(String documentId) {
    DocumentContentVO contentVO = new DocumentContentVO();
    contentVO.setDocumentId(documentId);
    DataSource ds = new PDFDataSource(nodeService,documentId);
    contentVO.setContent(new DataHandler(ds));
    return contentVO;
   }
}

PDFDataSource

@Component
public class PDFDataSource implements DataSource {

public static final String APPLICATION_PDF = "application/pdf";
private final String documentId;
private PCPNodeService nodeService;

public PDFDataSource(PCPNodeService nodeService, String documentId) {
    this.documentId = documentId;
    this.nodeService = nodeService;
}

@Override
public InputStream getInputStream() throws IOException {
    FileInputStream fis = new FileInputStream("c:/document.pdf");
    RemoteInputStream remoteInputStream = nodeService.getNodeInputStream(documentId);
    return fis;
}

@Override
public OutputStream getOutputStream() throws IOException {
    return null;
}

@Override
public String getContentType() {
    return APPLICATION_PDF;
}

@Override
public String getName() {
    return "INDICATE-DOCUMENT-NAME.pdf";
}
}

Value Object

@XmlRootElement(name = "DocumentContentVO")
@XmlAccessorType(XmlAccessType.FIELD)
@BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING)
public class DocumentContentVO {

private String documentId;

@XmlMimeType("application/octet-stream")
private DataHandler content;


public DataHandler getContent() {
    return content;
}

public void setContent(DataHandler content) {
    this.content = content;
}

public String getDocumentId() {
    return documentId;
}

public void setDocumentId(String documentId) {
    this.documentId = documentId;
}

}

Unit test (to make Client invoke)

public class DocumentWSClientTest {

@Test
public void soap_operation_getContent_should_return_pdf_document() throws Exception {

    final String documentId = "931c43c0-66a1-4ca3-bd86-5195a8f9e3de";
    final String wsdl = "http://localhost/pcp-soap/soap/v1/Documents?wsdl";
    final String operation = "getContent";
    final QName opName = new QName("http://sei.ws.*.*.com/", "getContent");

    //
    JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
    Client client = factory.createClient(wsdl);
    Object[] result = client.invoke(opName, documentId);
    DocumentContentVO documentContentVO = (DocumentContentVO) result[0];
    InputStream inputStream = documentContentVO.getContent().getInputStream();
    File file = new File("c:/job/test.pdf");
    if (file.exists() ) {
        file.delete();
    }
    file.createNewFile();
    FileOutputStream outputStream = new FileOutputStream(file);
    byte[] buffer = new byte[1024];
    while (inputStream.read(buffer) > -1) {
        outputStream.write(buffer);
    }
}
}

Exception Stack

org.apache.cxf.interceptor.Fault: Could not write attachments.
at org.apache.cxf.interceptor.AttachmentOutInterceptor$AttachmentOutEndingInterceptor.handleMessage(AttachmentOutInterceptor.java:105)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:203)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:137)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:158)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:243)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:163)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:219)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:457)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:662)
    **Caused by: java.io.IOException: Closed**
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:140)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:107)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:60)
at org.apache.cxf.attachment.AttachmentSerializer.writeAttachments(AttachmentSerializer.java:272)
at org.apache.cxf.interceptor.AttachmentOutInterceptor$AttachmentOutEndingInterceptor.handleMessage(AttachmentOutInterceptor.java:103)
... 38 more

SOAPUI httpLog link to pastebin SOAP UI http Log

Was it helpful?

Solution

Resolved because something wrong went within my Apache http configuration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top