Search code examples
javasoapcxfinterceptor

Apache cxf interceptor how get full response body


I have wsdl service. All request and response saving in minio bucket. But when content too big, in minio saved only part of this content.

My Interceptor

@Slf4j
@Component
public class LogResponseInterceptor extends AbstractPhaseInterceptor<Message> {

    private final MinioService minioService;
    private final AdministrationWebClient administrationWebClient;

    public LogResponseInterceptor(MinioService minioService, AdministrationWebClient administrationWebClient) {
        super(Phase.PRE_PROTOCOL_ENDING);
        this.minioService = minioService;
        this.administrationWebClient = administrationWebClient;
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        try (CachedOutputStream outputStream = ((CachedOutputStream) message.getContent(OutputStream.class));
             InputStream inputStream = outputStream.getInputStream()) {

            UUID uuid = UUID.randomUUID();
            minioService.uploadFile(
                    inputStream, Constantas.MinioConst.MINIO_SPV_OUT_PATH, uuid.toString(), "application/xml"
            );

            SpvRecord spvRecord = SpvRequestContext.getSpvRequest();

            spvRecord.setRequestState(RequestState.COMPLETED);
            spvRecord.setResponseXmlUrl(Constantas.MinioConst.MINIO_SPV_OUT_PATH + uuid);
            spvRecord.setFinishDate(ZonedDateTime.now());
            log.info("End spv action with {}", spvRecord);

            spvRecord.setRequestNumber(administrationWebClient.getSpvLastRequestNumber() + 1);
            administrationWebClient.createSpvRecord(spvRecord);

        } catch (IOException e) {
            log.error("### Error while get response xml");
            throw new RuntimeException(e);
        } finally {
            SpvRequestContext.clear();
        }
    }
}

CachedOutputStream contains only part of response body. How i can get full response body?


Solution

  • You can try lowering the level of the phase.The attachment interceptor is at the receive level (version 3.3.7).

    Phase chain

    To get the request you can try this, copy the original content to be able to flush it.

    // now get the request xml
    InputStream is = message.getContent ( InputStream.class );
    CachedOutputStream os = new CachedOutputStream ( );
    IOUtils.copy ( is, os );
    os.flush ( );
    message.setContent (  InputStream.class, os.getInputStream ( ) );
    is.close ( );
            
    System.out.println ("The request is: " + IOUtils.toString ( os.getInputStream ( ) ));
    os.close ( );
    

    To get the response, you need made custom implementation del original

    https://github.com/apache/cxf/blob/main/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java

    and modify the method onClose(CachedOutputStream cos) with this

            public void onClose(CachedOutputStream cos) {
            final LogEvent event = eventMapper.map(message);
            if (shouldLogContent(event)) {
                copyPayload(cos, event);
            } else {
                event.setPayload(CONTENT_SUPPRESSED);
            }
    
            StringBuilder sb = new StringBuilder("\nOutbound Message\n---------------------------\n");
            sb.append("ID: " + event.getExchangeId() + " \n");
            sb.append("Address: " + event.getAddress() + " \n");
            sb.append("Encoding: " + event.getEncoding() + " \n");
            sb.append("Content-Type: " + event.getContentType() + " \n");
            sb.append("Headers: " + event.getHeaders() + " \n");
            
            if(event.isTruncated()) {
                sb.append("Payload (truncated) : " + event.getPayload() + " \n");
            } else {
                sb.append("Payload: " + event.getPayload() + " \n");
            }
            
            sb.append("---------------------------");
            this.logger.trace(sb.toString());
            
            try {
                // empty out the cache
                cos.lockOutputStream();
                cos.resetOut(null, false);
            } catch (Exception ex) {
                // ignore
            }
            message.setContent(OutputStream.class, origStream);
        }
    

    IMPORTANT: the limit truncate the response, set limit to max for read the entire response