4
votes

I'm calling a Spring Data Rest URL using Spring Integration with an <int-http:outbound-gateway>.

My invocation is a simple HTTP GET towards a known resource URL (in my case, "examples").

This is the configuration of the <int-http:outbound-gateway>:

<int-http:outbound-gateway id="internalGW" request-channel="dataRestChannel"
    encode-uri="true" url-expression="payload" 
    http-method="GET" extract-request-payload="true"
    header-mapper="headerMapper"> 
</int-http:outbound-gateway>

In the logs I can see this message:

The 'extractPayload' attribute has no relevance for the current request since the HTTP Method is 'GET', and no request body will be sent for that method.

I suppose that is refered to the http-method="GET" extract-request-payload="true" configuration, but I don't know if this warning is relevant for the question.

This is the invocation of that outbound channel with a message that contains the REST url to be invoked:

public Object invokeUrl(String url){
    MessagingChannel messagingChannel = (MessagingChannel)ApplicationContextResolver.getApplicationContext().getBean("requestChannelBean");
    MessageChannel dataRestChannel = messagingChannel.getDataRestChannel();
    MessagingTemplate messagingTemplate = new MessagingTemplate();
    Message<?> requestMessage = MessageBuilder.withPayload(url).build();
    Message<?> response = messagingTemplate.sendAndReceive(dataRestChannel, requestMessage);
    return response.getPayload();
}

The invocation is fine, I have an HTTP status code 200; this is the response.getPayload():

<200 OK,
{
    Server=[Apache-Coyote/1.1],
    Cache-Control=[no-cache,no-store,max-age=0,must-revalidate],
    Pragma=[no-cache],
    Expires=[0],
    X-XSS-Protection=[1; mode=block],
    X-Frame-Options=[DENY,DENY],
    X-Content-Type-Options=[nosniff,nosniff],
    Transfer-Encoding=[chunked],
    Date=[Fri,22 Jul 2016 13:03:22 GMT],
    Content-Type=[application/hal+json],
    Content-Length=[0]
}>

However, I don't understand why the "payload body" is empty, as you can see in the Content-Length header.

response    GenericMessage<T>  (id=219) 
    headers MessageHeaders  (id=221)    
    payload ResponseEntity<T>  (id=222) 
        body    null    
        headers HttpHeaders  (id=224)   
        statusCode  HttpStatus  (id=159)    

If I go directly to that URL with a GET on the browser, this is the response that I receive:

{
    "_embedded": {
        "examples": []
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/restapp/api/examples"
        },
        "profile": {
            "href": "http://localhost:8080/restapp/api/profile/examples"
        }
    }
}

I would expected this as the response payload, not an empty payload.

It seems that the ResponseEntity.body that I receive is empty.

Is there any way to get the same JSON result of the HTTP get with the outbound-gateway?

Thanks in advance.

UPDATE

As from Gary suggestion, I have monitored the traffic.

Here there are the details of the requests:

Spring Integration Request:

GET http://localhost:8080/restapp/api/examples HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4

Browser Request:

GET http://localhost:8080/restapp/api/examples HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=C966FB7DB6B172D530D7C1F4DC57C6B8

The requests seems to be the same, except for one header (the Cookie JSESSIONID, there is absent in Integration context).

UPDATE 2

Maybe I have found the reason of the empty payload on the response.

The "extractData" method of org.springframework.web.client.RestTemplate has the object instance this.delegate setted to a null value.

So, in return there is a ResponseEntity object without the body.

@Override
public ResponseEntity<T> extractData(ClientHttpResponse response) throws IOException {
    if (this.delegate != null) {  // this.delegate is null
        T body = this.delegate.extractData(response);
        return new ResponseEntity<T>(body, response.getHeaders(), response.getStatusCode());
    }
    else {
        return new ResponseEntity<T>(response.getHeaders(), response.getStatusCode()); // <- it's executed this one
    }
}

It would be interesting to discover why this.delegate is setted to null.

1
There's probably something different in the request. I suggest you use a TCP monitor (there's one built into eclipse, or use wireshark etc) to compare the two requests/responses. If you can't figure it out from that, edit the question with the network traces.Gary Russell
Thanks for the suggestion, Gary. I have edited the question with the details of the requests.Alessandro C
Sounds like your server app might need a session (login?) - you need to debug on the server side.Gary Russell
I have added a second update, maybe I have discovered the reason of the issue, but I don't know how to solve it!Alessandro C
See my answer below - we could have gotten here quicker if you'd shown the responses as well as the requests in your previous edit.Gary Russell

1 Answers

6
votes

You need to add expected-response-type="java.lang.String" to the gateway.