アウトバウンドCXF要求の未加工XMLメッセージを変更する方法

cxf interceptor java web-services
アウトバウンドCXF要求の未加工XMLメッセージを変更する方法

発信SOAP要求を変更したいと思います。 エンベロープの本体から2つのxmlノードを削除したいと思います。 インターセプターをセットアップし、メッセージの生成されたストリング値をエンドポイントに設定することができました。

ただし、次のコードは、送信メッセージが期待どおりに編集されていないため、機能していないようです。 これを行う方法に関するコードやアイデアはありますか?

public class MyOutInterceptor extends AbstractSoapInterceptor {

public MyOutInterceptor() {
        super(Phase.SEND);
}

public void handleMessage(SoapMessage message) throws Fault {
        // Get message content for dirty editing...
        StringWriter writer = new StringWriter();
        CachedOutputStream cos  = (CachedOutputStream)message.getContent(OutputStream.class);
        InputStream inputStream = cos.getInputStream();
        IOUtils.copy(inputStream, writer, "UTF-8");
        String content = writer.toString();

        // remove the substrings from envelope...
        content = content.replace("0", "");
        content = content.replace("false", "");
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(content.getBytes(Charset.forName("UTF-8")));
        message.setContent(OutputStream.class, outputStream);
}

  16  10


ベストアンサー

最初のコメントに基づいて、石鹸の封筒全体を簡単に変更できる抽象クラスを作成しました。

誰かがすぐに使用できるコード部分が必要な場合に備えて。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.log4j.Logger;

/**
 * http://www.mastertheboss.com/jboss-web-services/apache-cxf-interceptors
 * http://stackoverflow.com/questions/6915428/how-to-modify-the-raw-xml-message-of-an-outbound-cxf-request
 *
 */
public abstract class MessageChangeInterceptor extends AbstractPhaseInterceptor {

    public MessageChangeInterceptor() {
        super(Phase.PRE_STREAM);
        addBefore(SoapPreProtocolOutInterceptor.class.getName());
    }

    protected abstract Logger getLogger();

    protected abstract String changeOutboundMessage(String currentEnvelope);

    protected abstract String changeInboundMessage(String currentEnvelope);

    public void handleMessage(Message message) {
        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();
                IOUtils.closeQuietly(cs);
                CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);

                String currentEnvelopeMessage = IOUtils.toString(csnew.getInputStream(), "UTF-8");
                csnew.flush();
                IOUtils.closeQuietly(csnew);

                if (getLogger().isDebugEnabled()) {
                    getLogger().debug("Outbound message: " + currentEnvelopeMessage);
                }

                String res = changeOutboundMessage(currentEnvelopeMessage);
                if (res != null) {
                    if (getLogger().isDebugEnabled()) {
                        getLogger().debug("Outbound message has been changed: " + res);
                    }
                }
                res = res != null ? res : currentEnvelopeMessage;

                InputStream replaceInStream = IOUtils.toInputStream(res, "UTF-8");

                IOUtils.copy(replaceInStream, os);
                replaceInStream.close();
                IOUtils.closeQuietly(replaceInStream);

                os.flush();
                message.setContent(OutputStream.class, os);
                IOUtils.closeQuietly(os);

            } catch (IOException ioe) {
                getLogger().warn("Unable to perform change.", ioe);
                throw new RuntimeException(ioe);
            }
        } else {
            try {
                InputStream is = message.getContent(InputStream.class);
                String currentEnvelopeMessage = IOUtils.toString(is, "UTF-8");
                IOUtils.closeQuietly(is);

                if (getLogger().isDebugEnabled()) {
                    getLogger().debug("Inbound message: " + currentEnvelopeMessage);
                }

                String res = changeInboundMessage(currentEnvelopeMessage);
                if (res != null) {
                    if (getLogger().isDebugEnabled()) {
                        getLogger().debug("Inbound message has been changed: " + res);
                    }
                }
                res = res != null ? res : currentEnvelopeMessage;

                is = IOUtils.toInputStream(res, "UTF-8");
                message.setContent(InputStream.class, is);
                IOUtils.closeQuietly(is);
            } catch (IOException ioe) {
                getLogger().warn("Unable to perform change.", ioe);

                throw new RuntimeException(ioe);
            }
        }
    }

    public void handleFault(Message message) {
    }

    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 {
        }
    }
}

35


今日もこの問題がありました。 たくさんの涙と歯ぎしりの後、http://svn.apache.org/viewvc/cxf/trunk/distribution/src/main/release/samples/configuration_interceptor/ [configuration_interceptor]デモでStreamInterceptorクラスを変更することができましたCXFソースに付属しています:

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

    String soapMessage = IOUtils.toString(csnew.getInputStream());
    ...

`soapMessage`変数には完全なSOAPメッセージが含まれます。 SOAPメッセージを操作し、それを出力ストリームにフラッシュし、 `message.setContent(OutputStream.class …​`呼び出しを行ってメッセージに変更を加えることができるはずです。 私はCXFを初めて使用するので、これには保証が付いていません!

注:CachedStreamは、StreamInterceptorクラスのプライベートクラスです。 SOAPインターセプターがSOAPメッセージを作成できるように、インターセプターをPRE_STREAMフェーズで実行するように構成することを忘れないでください。

17


以下は、サーバー側の例外をバブルアップすることができます。 以前のソリューションでIOUtils.closeQuietly(os)の代わりにos.close()を使用すると、例外をバブルアップすることもできます。

public class OutInterceptor extends AbstractPhaseInterceptor {
    public OutInterceptor() {
        super(Phase.PRE_STREAM);
        addBefore(StaxOutInterceptor.class.getName());
    }
    public void handleMessage(Message message) {
        OutputStream os = message.getContent(OutputStream.class);
        CachedOutputStream cos = new CachedOutputStream();
        message.setContent(OutputStream.class, cos);
        message.getInterceptorChain.aad(new PDWSOutMessageChangingInterceptor(os));
    }
}

public class OutMessageChangingInterceptor extends AbstractPhaseInterceptor {
    private OutputStream os;

    public OutMessageChangingInterceptor(OutputStream os){
        super(Phase.PRE_STREAM_ENDING);
        addAfter(StaxOutEndingInterceptor.class.getName());
        this.os = os;
    }

    public void handleMessage(Message message) {
        try {
            CachedOutputStream csnew = (CachedOutputStream) message .getContent(OutputStream.class);
            String currentEnvelopeMessage = IOUtils.toString( csnew.getInputStream(), (String) message.get(Message.ENCODING));
            csnew.flush();
            IOUtils.closeQuietly(csnew);
            String res = changeOutboundMessage(currentEnvelopeMessage);
            res = res != null ? res : currentEnvelopeMessage;
            InputStream replaceInStream = IOUtils.tolnputStream(res, (String) message.get(Message.ENCODING));
            IOUtils.copy(replaceInStream, os);
            replaceInStream.close();
            IOUtils.closeQuietly(replaceInStream);
            message.setContent(OutputStream.class, os);
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }
}

1


タイトルとURLをコピーしました