java - 无法使用 jax-ws 通过 MTOM 从 SOAP 获取 PDF

标签 java web-services soap jax-ws mtom

我正在尝试获取从网络服务调用返回的 PDF。通过 SoapUI 和其他日志记录,我可以看到回复中附有 PDF。 但我试图获取 PDF 的尝试失败了。 PDF 的数据处理程序不包含数据。

// 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();

因此文件 /tmp/out.pdf 是空的。使用缓冲区写入 PDF 会产生相同的结果:

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();

我尝试通过三种不同的方式在我的客户端中显式启用 MTOM:

// 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");
}

无论我是否使用方式 1 或 2,我都会得到“MTOM 已启用”。

我已经在调试器(netbeans)中运行了调用并检查了“结果”对象。 DataHandler 的所有字段均为空或值为 0。

我尝试将 wsdl 文件导入到 Eclipse 中的项目中。当 Eclipse 在生成的源代码中报告多个错误时,我放弃了这条路。相反,我让 SoapUI 生成类(wsimport 和 wsdl2java)并将其与我的代码一起使用。我得到了相同的结果,空 PDF。

按照此处的建议使用 SOAPHandler 拦截消息: http://java.globinch.com/enterprise-java/web-services/jax-ws/logging-tracing-web-service-xml-request-response-jax-ws/

截获的消息我已保存并存储到文件中,并且能够保存每个部分。

不知道从这里去哪里。我确实觉得有些地方我错过了。

这是实际的代码 公共(public)静态无效主(字符串[] args)抛出异常{ SVVCommonHeaderType header = new SVVCommonHeaderType(); header.setSystemId(SYSTEM_ID); header.setBrukerId("用户名"); 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();
}

编辑: 作为解决方法,我在日志记录类中添加了提取 PDF 的代码。 handleMessage() 看起来像

@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;
}

如果要使用此解决方法,我必须添加一些额外的处理代码。我稍后再决定。

最佳答案

事实证明,问题的原因是发送方的某些防火墙对 SOAP 附件进行了一些重写。当 SoapUI 处理消息时,这会混淆 jax-ws。

我从消息制作者那里得到的答案是,他们有一个代理,可以将 header 从 XOP 转换为文本,而 MTOM 需要是 XOP。

有了这个,我的代码就可以完美运行。

关于java - 无法使用 jax-ws 通过 MTOM 从 SOAP 获取 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35808067/

相关文章:

java - 不使用 2.11 编译的 Java 中 Scala 集合的简单使用

java - Android SOAP wsdl

java - 映射、绑定(bind)和解析之间有什么区别?

web-services - Servlet 与 Web 服务

java - 回滚时的 Spring 事务不会将数据库恢复到以前的状态

java - 你如何计算具有初始高度的弹丸的位移?

c++ - 为什么通过 gSOAP 发送二进制数据太慢了?

node.js - Node.js 中的 SOAP 示例及其执行过程?

php - 非 WSDL 模式下的 SOAP 问题

正确分配内存后 Java 代码出错