【问题标题】:Is it possible to send a pretty printed SOAP request with apache cxf?是否可以使用 apache cxf 发送漂亮打印的 SOAP 请求?
【发布时间】:2021-10-03 06:41:15
【问题描述】:

我使用 apache cxf 库作为我们的 SOAP 客户端将 SOAP 请求传输到特定端点。 不幸的是,如果数据出现在一行中(这几乎是标准),这个端点似乎确实很难正确解析数据。我编写了一个简单的测试客户端,它将 RAW 字符串发送到该端点,并且通过它我能够发现如果 SOAP 消息打印得很漂亮,则可以处理请求。如果我在一行中发送相同的请求,服务器会响应 HTTP/1.1 500 内部服务器错误。

我已经提交了错误报告,但我担心接收公司会要求我发送打印好的数据。

apache cxf 可以吗?

【问题讨论】:

  • 您可以尝试在发送前使用interceptors 来转换响应,但是您确定这只是消息的格式,而有效的请求和无效的请求之间没有其他区别吗?如果肥皂网络服务无法解析格式不正确的正确消息(无论如何只有人类会关心),它将从根本上被破坏。
  • 是的,我确定。老实说,整个事情比描述的要复杂一些。在我将“授权”HTTP-Header 传输到远程系统之前,一切正常。使用该标头,远程系统中断并发送状态代码 500。在我看来(从我收到的错误消息推断)远程端的转换场景试图修改我的原始请求,如果所有请求都在一行中,该请求似乎失败.如果我更改我的请求并添加至少两个换行符(在特定位置),一切都会再次正常工作。对我来说,一个非常明确的指标表明远程系统存在错误

标签: java soap cxf


【解决方案1】:

我找到了another question,它帮助我找到了满足我需求的解决方案。

从那篇文章开始,我能够采用以下代码来满足我的需要

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

public class PrettyPrintingOutInterceptor extends AbstractPhaseInterceptor<Message> {

    public PrettyPrintingOutInterceptor(int indent) {
        super(Phase.PRE_STREAM);
        addBefore(SoapPreProtocolOutInterceptor.class.getName());
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        boolean isOutbound = false;
        isOutbound = message == message.getExchange().getOutMessage()
               || message == message.getExchange().getOutFaultMessage();

        if (isOutbound) {
            OutputStream os = message.getContent(OutputStream.class);
            CachedStream cs = new CachedStream();
            message.setContent(OutputStream.class, cs);
            
            message.getInterceptorChain().doIntercept(message);

            try {
                cs.flush();
                CachedOutputStream csnew = (CachedOutputStream) message
                    .getContent(OutputStream.class);
                
                // get current payload
                String soapMessage = IOUtils.toString(csnew.getInputStream());
                // manipulate payload
                soapMessage = prettyPrint(soapMessage, 3);
                
                // Write new data into the OutputStream from above
                ByteArrayInputStream bin = new ByteArrayInputStream(soapMessage.getBytes());
                CachedOutputStream.copyStream(bin, os, 1024);

                os.flush();
            } catch (IOException | TransformerException e) {
                // error handling
            } finally {
                // Important! Close streams!
                try {
                    cs.close();
                } catch (IOException e) {
                }
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }
    }

    private String prettyPrint(String xml, int indent) throws TransformerException {
        Source xmlInput = new StreamSource(new StringReader(xml));
        StringWriter stringWriter = new StringWriter();
        StreamResult xmlOutput = new StreamResult(stringWriter);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer(); 
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "" + indent);
        transformer.transform(xmlInput, xmlOutput);
        return xmlOutput.getWriter().toString();
    }

    private class CachedStream extends CachedOutputStream {
        public CachedStream() {
            super();
        }
        
        protected void doFlush() throws IOException {
            currentStream.flush();
        }

        protected void doClose() throws IOException {
        }
        
        protected void onWrite() throws IOException {
        }
    }
}

并使用client.getOutInterceptors().add(new PrettyPrintingOutInterceptor());将此类中的对象添加到客户端

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多