web-dev-qa-db-ja.com

エラー発生時のJAX-WSによるXML要求/応答のトレース

エラーが発生した場合、未加工のSOAPポストリクエストをログに記録したいのですが、JAX-WSを使用しています。どんな助けでもありがたいです。

例外が応答で発生した場合にのみ、JAX-WSリファレンス実装(JDK 1.5以降に含まれるもの)で公開されたWebサービスの生の要求/応答XMLにアクセスする簡単な方法(別名:プロキシを使用しない)はありますか?生のログを記録したいSOAP reuestなので、後の段階で任意のWebサービスクライアントを使用してテストできます

24
user665837

使用する

com.Sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true

そして

com.Sun.xml.internal.ws.transport.http.HttpAdapter.dump=true

代わりに(パッケージ名の「内部」に注意)、これは私にとってはトリックでした。

乾杯、トルステン

33
Torsten

私がこれに言及すると思っただけです:

internalが含まれるプロパティ名をいつ使用し、いつ使用しないかという質問

Metro Guide を読むと、次のように指示されます。

クライアント上:

com.Sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true

サーバー上:

com.Sun.xml.ws.transport.http.HttpAdapter.dump=true

ただし、JDKにJAX-WS RIライブラリが標準で含まれている場合(Java 6の場合))、Sunはプロパティ名を「internal」に変更する必要があったようです。したがって、JDKにバンドルされているJAX-WS RIを使用している場合は、必ずプロパティ名にinternalを追加する必要があります。それ以外の場合は、つまり、次のように使用する必要があります。

クライアント上:

com.Sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true

サーバー上:

com.Sun.xml.internal.ws.transport.http.HttpAdapter.dump=true

一方、スタンドアロンバージョンのJAX-WS RI(またはMetro全体)を使用している場合、プロパティ名なしを使用する必要があると思いますinternal

誰かがこれについて内面の知識を持っていて、これが真実かどうか言うことができれば嬉しいです。

27
peterh

トルステンの答えに加えて

com.Sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump = true

WebServiceClientオブジェクト(Serviceを拡張するオブジェクト)をインスタンス化する前に、必ずこれを設定してください

4
thirdy

最初に試したいのは、次のシステムプロパティの一方または両方を使用することです。

クライアント:

com.Sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true

サーバ:

com.Sun.xml.ws.transport.http.HttpAdapter.dump=true
3
kschneid

Jboss 6.1を使用していて、SOAP WebサービスへのJAX-WS生成クラス要求のログを印刷する場合は、ファイル/home/Oracle/jboss-eap-6.1/bin/standalone.shノート:jbossをインストールした場所に行ってください

あなたはこのようなものを見つけるでしょう

Java_OPTS="$Java_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"

以下のように変更してください

Java_OPTS="$Java_OPTS -Dcom.Sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"

また、デバッグを有効にしてください

DEBUG_MODE=true
2
vinodh nair

システムプロパティを使用しても問題ありません(ここにtestタスクのGradle DSLがあります):

systemProperty "com.Sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.Sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.Sun.xml.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.Sun.xml.internal.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.Sun.xml.ws.transport.http.HttpAdapter.dumpTreshold", "99999"
systemProperty "com.Sun.xml.internal.ws.transport.http.HttpAdapter.dumpTreshold", "99999"

ただし、これらの設定はグローバルであり、PRODで有効にするために大量になる可能性があります... XMLロギングの量を減らしたい場合、ビジネスロジックにバインドされたロギングフレームワークにフィルターを追加するのは楽しいことではありません。

WSハンドラーでのreq/rspボディのキャプチャの詳細は私の回答にあります SOAPハンドラーからWebサービスクライアントにデータを返すにはどうすればよいですか?

ここに重要な部分があります:

public class MsgLogger implements SOAPHandler<SOAPMessageContext> {

    public static String REQEST_BODY = "com.evil.request";
    public static String RESPONSE_BODY = "com.evil.response";

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        SOAPMessage msg = context.getMessage();
        Boolean beforeRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(32_000);
            context.getMessage().writeTo(baos);
            String key = beforeRequest ? REQEST_BODY : RESPONSE_BODY;
            context.put(key, baos.toString("UTF-8"));
            context.setScope(key, MessageContext.Scope.APPLICATION);
        } catch (SOAPException | IOException e) { }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return handleMessage(context);
    }

    @Override
    public void close(MessageContext context) { }
}

ハンドラーを登録し、保存されたプロパティを使用するには:

BindingProvider provider = (BindingProvider) port;
List<Handler> handlerChain = bindingProvider.getBinding().getHandlerChain();
handlerChain.add(new MsgLogger());
bindingProvider.getBinding().setHandlerChain(handlerChain);

Req req = ...;
Rsp rsp = port.serviceCall(req); // call WS Port

// Access saved message bodies:
Map<String, Object> responseContext = provider.getResponseContext();
String reqBody = (String) responseContext.get(MsgLogger.REQEST_BODY);
String rspBody = (String) responseContext.get(MsgLogger.RESPONSE_BODY);

この解決策(これはスケルトンであり、適切なエラー処理/エッジのケースはあなた次第です)を使用して、応答があったときにログに記録することにします。

2
gavenkoa

これは私のために働きました:

-Dcom.Sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
1
Wojtek

必要なのはハンドラーだと思います。以下を参照してください。 http://jax-ws.Java.net/articles/handlers_introduction.html
ハンドラーを使用すると、Webサービス呼び出しをインターセプトして、すべてのSOAPメッセージにアクセスできます。

1
lpinto.eu