Search code examples
javaspringspring-integrationresttemplatespring-resttemplate

Can HTTPS response status code made available in other classes in Spring integration


I have a requirement to make response.statusCode() received from ClientHttpResponse in Interceptor, should be available in testSubmitPaymentResponseVO object that I created so that error handling can be done accordingly . However I dont know where and how to pass response to my POJO testSubmitPaymentResponseVO.

<int:channel id="MytestReqRequestChannel"/>

<int:header-enricher input-channel="MytestReqRequestChannel" output-channel="MytestReqEnrichedRequestChannel">
    <int:header name="x-api-key" value="#{configurationService.configuration.getProperty('myKey')}"/>
    <int:header name="Content-Type" value="application/json;charset=UTF-8" />
</int:header-enricher>


<int:object-to-json-transformer input-channel="MytestReqEnrichedRequestChannel"
                                output-channel="MytestReqJSONRequestChannel"/>

<int-http:outbound-gateway
        url="#{configurationService.configuration.getProperty('myURL')}"
        http-method="POST"
        header-mapper="testPaymentHeaderMapper"
        rest-template="testSubmitPaymentRestTemplate"
        request-channel="MytestReqJSONRequestChannel"
        reply-channel="MytestReqJSONResponseChannel"
        charset="UTF-8"
        expected-response-type="java.lang.String">
</int-http:outbound-gateway>

<int:json-to-object-transformer input-channel="MytestReqJSONResponseChannel"
                                output-channel="MytestReqResponseChannel"
                                type="com.test.testb2bintegrations.models.payment.request.testSubmitPaymentResponseVO"/>

<int:channel id="MytestReqResponseChannel"/>

Interceptor code:

public class TestRequestLoggingInterceptor implements ClientHttpRequestInterceptor
{

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
{
    ClientHttpResponse response;
    try
    {
        request.getHeaders().setAcceptCharset(Collections.singletonList(Charsets.UTF_8));
        long startTimeinMillis = new Date().getTime();
        response = execution.execute(request, body);
        logResponse(response);
    }
    catch (Exception e)
    {
        LOGGER.error("Error when trying to fetch the information : " + e.getMessage());
        throw new IOException("Connection was unsuccessful!", e);
    }
    return response;
}

private void logResponse(ClientHttpResponse response) throws IOException
{
       String lineSeparator = System.lineSeparator();
        String responseBody = StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"));

        StringBuilder responseLog = new StringBuilder();
        responseLog.append("=======================Response Begin==========================").append(lineSeparator);
        responseLog.append("Status code  : {" + response.getStatusCode() + "}").append(lineSeparator);
        responseLog.append("Status text  : {" + response.getStatusText() + "}").append(lineSeparator);
        responseLog.append("Headers      : {" + response.getHeaders() + "}").append(lineSeparator);
        responseLog.append("Response body: {" + responseBody + "}").append(lineSeparator);
        responseLog.append("======================Response End==============================").append(lineSeparator);
}

Solution

  • I gave you some instructions in the comments for my answer for this your question: java.lang.IllegalArgumentException: 'json' argument must be an instance of: [class java.lang.String, class [B

    We probably could consider this as a duplication, but that won't hurt me if I repeat myself over here as well.

    The HTTP response status code is stored in the respective header when <int-http:outbound-gateway> processes the ClientHttpResponse:

        else {
            replyBuilder = messageBuilderFactory.withPayload(httpResponse);
        }
        replyBuilder.setHeader(org.springframework.integration.http.HttpHeaders.STATUS_CODE,
                httpResponse.getStatusCode());
        return replyBuilder.copyHeaders(headers);
    

    And this header is simply available downstream for your consideration.

    If you really eager to have that status code presented in your testSubmitPaymentResponseVO, then you probably need to have a setter on it.

    One of the way is to implement some transformer method to accept your testSubmitPaymentResponseVO and that header and set it into your POJO and return it from that header:

    testSubmitPaymentResponseVO setStatusCode(testSubmitPaymentResponseVO pojo, @Header(name = HttpHeaders.STATUS_CODE) HttpStatus statusCode) {
       pojo.setStatusCode(statusCode);
       return pojo;
    }
    

    Another way is to use an <enricher> component:

    <int:enricher id="userEnricher"
                  input-channel="setStatusCodeChannel"
                  output-channel="MytestReqResponseChannel">
        <int:property name="StatusCode" expression="headers[http_statusCode]"/>
    </int:enricher>
    

    And your <int:json-to-object-transformer> should output to this new setStatusCodeChannel.

    See docs: https://docs.spring.io/spring-integration/docs/current/reference/html/message-transformation.html#payload-enricher