2016-07-19 3 views
1

J'ai un client REST qui crée une entité XML via Entity.entity(myObject, MediaType.APPLICATION_XML_TYPE). Après cela, j'appelle webTarget.request().buildPost(...Comment obtenir du XML pur à partir de javax.ws.rs Entité côté client

Comment puis-je obtenir le corps de la demande XML que mon client va envoyer au serveur? (J'en ai besoin pour des raisons de débogage.) Tout ce que je reçois ici est un objet Entity.

Bien sûr, je pourrais sérialiser moi-même avec un Marshaller mais est-ce vraiment le même XML le client enverrait?

Répondre

3

Vous pourriez avoir un ClientRequestFilter comme suit, qui est une version simplifiée de LoggingFilter Jersey:

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

Et inscrivez-vous à votre Client:

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

Merci pour cette réponse détaillée! – Sebastian

+1

+1 pour l'excellente réponse, cela m'a beaucoup aidé. J'ai juste une petite question: comment adapteriez-vous cela pour enregistrer la réponse au lieu de la demande? Lorsque je le change pour implémenter ClientResponseFilter et changer le contexte de filtre en objet de contexte de réponse, je me retrouve avec un InputStream au lieu d'un OutputStream, et je n'arrive pas à comprendre comment aller de l'avant avec ce point. – Tim

+1

Merci pour le code détaillé, fonctionne parfaitement pour moi. Ajout de quelques extras pour notre configuration de journalisation. – kdoteu