2016-07-19 24 views
1

Entity.entity(myObject, MediaType.APPLICATION_XML_TYPE)XMLエンティティを作成するRESTクライアントがあります。その後、私はwebTarget.request().buildPost(...javax.ws.rsからプレーンXMLを取得する方法クライアント側のエンティティ

私のクライアントがサーバーに送信するリクエストボディXMLを取得するにはどうしたらいいですか? (私はデバッグのためにそれを必要としています。)ここで得られるのはEntityオブジェクトです。

もちろん、Marshallerでそれをシリアル化できますが、これは実際にはクライアントが送信するXMLと同じですか?

答えて

3

あなたがジャージーのLoggingFilterの簡易版である、以下のようClientRequestFilterを持つことができます:

import java.io.ByteArrayOutputStream; 
import java.io.FilterOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.nio.charset.Charset; 
import java.nio.charset.StandardCharsets; 
import java.util.logging.Logger; 

import javax.annotation.Priority; 
import javax.ws.rs.ConstrainedTo; 
import javax.ws.rs.RuntimeType; 
import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.client.ClientRequestContext; 
import javax.ws.rs.client.ClientRequestFilter; 
import javax.ws.rs.container.PreMatching; 
import javax.ws.rs.ext.WriterInterceptor; 
import javax.ws.rs.ext.WriterInterceptorContext; 

@Priority(Integer.MIN_VALUE) 
@ConstrainedTo(RuntimeType.CLIENT) 
public class LoggingFilter implements ClientRequestFilter, WriterInterceptor { 

    private static final Logger LOGGER = 
            Logger.getLogger(LoggingFilter.class.getName()); 

    private static final String ENTITY_STREAM_PROPERTY = 
            LoggingFilter.class.getName() + ".entityLogger"; 

    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; 

    private static final int MAX_ENTITY_SIZE = 1024 * 8; 

    private void log(StringBuilder sb) { 
     LOGGER.info(sb.toString()); 
    } 

    @Override 
    public void filter(ClientRequestContext context) throws IOException { 

     if (context.hasEntity()) { 
      OutputStream stream = new LoggingStream(context.getEntityStream()); 
      context.setEntityStream(stream); 
      context.setProperty(ENTITY_STREAM_PROPERTY, stream); 
     } 
    } 

    @Override 
    public void aroundWriteTo(WriterInterceptorContext context) 
       throws IOException, WebApplicationException { 

     LoggingStream stream = (LoggingStream) 
            context.getProperty(ENTITY_STREAM_PROPERTY); 
     context.proceed(); 
     if (stream != null) { 
      log(stream.getStringBuilder(DEFAULT_CHARSET)); 
     } 
    } 

    private class LoggingStream extends FilterOutputStream { 

     private final StringBuilder b = new StringBuilder(); 
     private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

     LoggingStream(final OutputStream inner) { 
      super(inner); 
     } 

     StringBuilder getStringBuilder(final Charset charset) { 
      // write entity to the builder 
      final byte[] entity = baos.toByteArray(); 

      b.append(new String(entity, 0, 
           Math.min(entity.length, MAX_ENTITY_SIZE), charset)); 
      if (entity.length > MAX_ENTITY_SIZE) { 
       b.append("...more..."); 
      } 
      b.append('\n'); 

      return b; 
     } 

     @Override 
     public void write(final int i) throws IOException { 
      if (baos.size() <= MAX_ENTITY_SIZE) { 
       baos.write(i); 
      } 
      out.write(i); 
     } 
    } 
} 

そして、あなたのClientにそれを登録します。

Client client = ClientBuilder.newClient().register(LoggingFilter.class); 
+1

は、この詳細な回答をありがとう! – Sebastian

+1

+1は優れた答えで、これは私を助けました。私はちょっとした疑問があります。リクエストの代わりにレスポンスを記録するにはどうすればいいですか? ClientResponseFilterを実装するためにそれを変更し、フィルタコンテキストをレスポンスコンテキストオブジェクトに変更すると、OutputStreamの代わりにInputStreamが使用されてしまい、その時点でどのように前進するのかわかりません。 – Tim

+1

詳しいコードをお寄せいただき、ありがとうございます。私たちのロギング設定のいくつかの追加が追加されました。 – kdoteu

関連する問題