我正在尝试获取从网络服务调用返回的 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/