0

I am making a third party request in Hybris1811 framework using Spring Rest Template . But after getting response I am Getting below error:

Could not properly initialize user sessionorg.springframework.web.util.NestedServletException: 
Request processing failed; 
nested exception is java.lang.IllegalArgumentException: 'json' argument must be an instance of: [class java.lang.String, class [B, class java.io.File, class java.net.URL, class java.io.InputStream, class java.io.Reader] , but gotten: class org.springframework.http.ResponseEntity.

when I try to implement the below code:

<int:gateway id="testRequestGateway" service-interface="com.test.testb2bintegrations.payment.gateway.testRequestGateway" default-request-channel="MytestReqRequestChannel" default-reply-channel="MytestReqResponseChannel"/>

<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);
}
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
Geek
  • 15
  • 7

1 Answers1

2

The error comes from the <int:json-to-object-transformer> when it tries to convert a reply from the <int-http:outbound-gateway> into your testSubmitPaymentResponseVO object.

But it turns out that reply is not a plain string as you would expect using expected-response-type="java.lang.String", but the whole ResponseEntity.

We have there a logic like this:

    if (httpResponse.hasBody()) {
        Object responseBody = httpResponse.getBody();
        replyBuilder = (responseBody instanceof Message<?>)
                ? messageBuilderFactory.fromMessage((Message<?>) responseBody)
                : messageBuilderFactory.withPayload(responseBody); // NOSONAR - hasBody()

    }
    else {
        replyBuilder = messageBuilderFactory.withPayload(httpResponse);
    }

So, looks like that url="#{configurationService.configuration.getProperty('myURL')}" REST service returns nothing back to you as an HTTP response.

Nothing what we can help with: we don't control that service so you should consult with them what is wrong in the request you send to them.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks for your response, however, strange thing is when I don't log ClientHttpResponse response.getBody() in overriden intercept() method from ClientHttpRequestInterceptor. It works absolutely fine. I get response . I am not sure why. – Geek Jul 04 '20 at 17:05
  • Show your interceptor code, please. Probably you need to use an `HttpComponentsClientHttpRequestFactory` for that `` if you can't get rid of your interceptor... – Artem Bilan Jul 04 '20 at 17:09
  • Please check edited question , I have updated it with the interceptor code. – Geek Jul 04 '20 at 17:21
  • Right. The body is read once and it empty for subsequent calls. As I said: consider to use an `HttpComponentsClientHttpRequestFactory` instead of default one `SimpleClientHttpRequestFactory`: see the `request-factory` attribute of that `` – Artem Bilan Jul 04 '20 at 17:26
  • My requirement is to log response body that's why I have provided rest-template , but after updating with request-factory , it throws error like. Configuration problem: When providing a 'rest-template' reference, the 'request-factory' attribute is not allowed. – Geek Jul 04 '20 at 17:42
  • That's OK. So, your custom `testSubmitPaymentRestTemplate` has to be supplied with that request factory instead. See its `setRequestFactory(ClientHttpRequestFactory requestFactory)` – Artem Bilan Jul 04 '20 at 17:44
  • How to supply ? In Hybris framework, I defined rest template bean as follows: – Geek Jul 04 '20 at 17:49
  • Huh? So just use another `` and have an `HttpComponentsClientHttpRequestFactory` as a `` declared. – Artem Bilan Jul 04 '20 at 17:51
  • Now I get this error : Could not properly initialize user sessionorg.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on POST request for "myURL": Attempted read from closed stream.; nested exception is java.io.IOException: Attempted read from closed stream. – Geek Jul 04 '20 at 18:22
  • OK. Let's step back then and try to wrap a response in your interceptor into the `BufferingClientHttpResponseWrapper` before calling your `logResponse()` and return from your `intercept()` method exactly that wrapper already. – Artem Bilan Jul 04 '20 at 18:35
  • I resolved it by providing , testBufferingClientHttpRequestFactory bean to Rest Template. It is working now. Thanks for your response – Geek Jul 05 '20 at 09:35
  • One more question, Is it possible that the status code received in HTTPS response can be available in testSubmitPaymentResponseVO? – Geek Jul 14 '20 at 16:51
  • You can do that using an `` and copy a value from the `HttpHeaders.STATUS_CODE` into your `testSubmitPaymentResponseVO` using its respective setter. See more in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/message-transformation.html#payload-enricher – Artem Bilan Jul 14 '20 at 17:00
  • I am completely new to Spring , I see I am already using a header enricher in XML , My requirement is to make respons estatus code available in my POJO testSubmitPaymentResponseVO. Can you elaborate more on this. That would really be a great help for me – Geek Jul 14 '20 at 17:07
  • Your `testSubmitPaymentResponseVO` is a payload of a message after that ``. It has to have some setter for the status you mention. The `` has an option ` – Artem Bilan Jul 14 '20 at 17:34