2016-07-19 7 views
1

에 javax.ws.rs 법인에서 일반 XML을 얻을 수 있습니다. 그 다음에는 webTarget.request().buildPost(...어떻게 <code>Entity.entity(myObject, MediaType.APPLICATION_XML_TYPE)</code> 통해 <code>XML</code> 엔티티를 생성하는 <code>REST</code> 클라이언트가 클라이언트 측

클라이언트가 서버에 보낼 요청 본문 XML을 어떻게 얻을 수 있습니까? (나는 이유를 디버깅을 위해 필요합니다.) 내가 여기까지 모든는 Entity 개체입니다.

물론 내가 Marshaller으로 직접 serialize 할 수 있지만 실제로는 클라이언트가 보낼 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을 구현하고 응답 문맥 객체에 필터 컨텍스트를 변경하는 변경하면, 나는의 InputStream 대신 OutputStream에와 끝까지, 그리고 그 시점에서 앞으로 이동하는 방법을 알아낼 수 없습니다. – Tim

+1

자세한 코드를 보내 주셔서 감사합니다. 저에게 적합합니다. 우리의 로깅 구성을위한 몇 가지 추가 사항이 추가되었습니다. – kdoteu