MohammadGhoreishi
MohammadGhoreishi

Reputation: 103

How to get message headers in an interceptor in Spring-Integration

I'm using Spring-Integration to proxy a SOAP Webservice. I get the request using some inbound gateway and after some transformations, the message passes a ws:outbound-gateway. I extended ClientInterceptor and define a custom one with the name WSLoggingInterceptor which logs XML requests and responses and added it to my ws:outbound-gateway.

I want to add an identifier to logs in order to relate logs of sending requests and receiving responses in the same message flow. I defined some UUID named messageId in the integration headers at the beginning of the messaging flow. My question is how can I have the messageId or other integration headers of an integration message in such interceptors? Is there any way?

Thanks.

Below is my interceptor class.

package com.asansoft.interceptors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.context.MessageContext;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Mohammad Ghoreishi.
 * [email protected]
 */

@Component(value = "wsLoggingInterceptor")
public class WSLoggingInterceptor implements ClientInterceptor {

    private final Logger requestLogger = LoggerFactory.getLogger("WSRequest");
    private final Logger responseLogger = LoggerFactory.getLogger("WSResponse");
    private final Logger errorLogger = LoggerFactory.getLogger("WSError");
    private List<String> exclusionRequestNSList = new ArrayList<>();
    private List<String> exclusionResponseNSList = new ArrayList<>();

    @Override
    public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            messageContext.getRequest().writeTo(byteArrayOutputStream);
            requestLogger.info("Web Service Request : " + removeRequestCredentials(removeSecurityHeaders(new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8))));
        } catch (IOException e) {
            errorLogger.error(e.getMessage(), e);
        }
        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            messageContext.getResponse().writeTo(byteArrayOutputStream);
            responseLogger.info("Web Service Response : " + removeResponseCredentials(removeSecurityHeaders(new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8))));
        } catch (IOException e) {
            errorLogger.error(e.getMessage(), e);
        }
        return true;
    }

    @Override
    public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
        try {
            long rs = (new Date()).getTime() - responseTime;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            messageContext.getResponse().writeTo(byteArrayOutputStream);
            errorLogger.error("Web Service Response : " + removeResponseCredentials(removeSecurityHeaders(new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8))));
            errorLogger.error("Response Time : " + rs + "ms");
        } catch (IOException e) {
            errorLogger.error(e.getMessage(), e);
        }
        return true;
    }

    @Override
    public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException {
        // Blah blah blah
    }


    private String removeSecurityHeaders(String xmlString) {
        // Blah blah blah
    }

    private String removeRequestCredentials(String xmlString) {
        // Blah blah blah
    }

    private String removeResponseCredentials(String xmlString) {
        // Blah blah blah
    }

    public List<String> getExclusionRequestNSList() {
        return exclusionRequestNSList;
    }

    public List<String> getExclusionResponseNSList() {
        return exclusionResponseNSList;
    }

    public void setExclusionRequestNSList(List<String> exclusionRequestNSList) {
        this.exclusionRequestNSList = exclusionRequestNSList;
    }

    public void setExclusionResponseNSList(List<String> exclusionResponseNSList) {
        this.exclusionResponseNSList = exclusionResponseNSList;
    }
}

Upvotes: 1

Views: 1729

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121177

First of all take a look, please, into a message history and global wire-tap into a logging channel adapter. This way you would be able to trace all path the message travels through your flow, including headers and payload.

See docs for more info:

https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/system-management.html#message-history

https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/core.html#channel-wiretap

Another way (and only the way) to have the requested info in your WS-specific interceptor is only via a ThreadLocal variable. You store that info in some shared ThreadLocal before calling ws:outbound-gateway and get that info from this variable in your interceptor. Probably you are aware what is MDC in loggers or SecurityContextHolder in Spring Security.

You probably could map your custom header into a SOAP request, but that's apparently not what would be good from business perspective to carry that info over the network to the Web Service...

Upvotes: 2

Related Questions