Nathan Russell Nathan Russell - 3 months ago 177
HTTP Question

Spring Integration - how to send POST parameters with http outbound-gateway

I'm trying to put together a really simple HTTP POST example using Spring Integration and a http outbound-gateway.

I need to be able to send a HTTP POST message with some POST parameters, as I would with

curl
:

$ curl -d 'fName=Fred&sName=Bloggs' http://localhost


I can get it working (without the POST parameters) if I send a simple
String
as the argument to the interface method, but I need to send a pojo, where each property of the pojo becomes a POST parameter.

I have the following SI config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

<int:gateway id="requestGateway"
service-interface="RequestGateway"
default-request-channel="requestChannel"/>

<int:channel id="requestChannel"/>

<int-http:outbound-gateway request-channel="requestChannel"
url="http://localhost"
http-method="POST"
expected-response-type="java.lang.String"/>

</beans>


My
RequestGateway
interface looks like this:

public interface RequestGateway {
String echo(Pojo request);
}


My
Pojo
class looks like this:

public class Pojo {
private String fName;
private String sName;

public Pojo(String fName, String sName) {
this.fName = fName;
this.sName = sName;
}

.... getters and setters
}


And my class to kick it all off looks like this:

public class HttpClientDemo {

public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/si-email-context.xml");
RequestGateway requestGateway = context.getBean("requestGateway", RequestGateway.class);

Pojo pojo = new Pojo("Fred", "Bloggs");
String reply = requestGateway.echo(pojo);
System.out.println("Replied with: " + reply);
}
}


When I run the above, I get:

org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [Pojo] and content type [application/x-java-serialized-object]


I've googled a lot for this, but cannot find any examples of sending HTTP POST parameters with an outbound-gateway (I can find lots about setting HTTP Headers, but that's not what I'm trying to do here)

The only thing I did find was spring-integration: how to pass post request parameters to http-outbound but it's a slightly different use case as the OP was trying to send a JSON representation of his pojo which I am not, and the answer talks about setting headers, not POST parameters.

Any help with this would be very much appreciated;

Thanks

Nathan

Answer

Thanks to the pointers from @jra077 regarding Content-Type, this is how I solved it.

My SI config now looks like this - the important bit was adding the Content-Type header:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:int="http://www.springframework.org/schema/integration"
   xmlns:int-http="http://www.springframework.org/schema/integration/http"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

    <int:gateway id="requestGateway"
             service-interface="RequestGateway"
             default-request-channel="requestChannel">
        <int:method name="sendConfirmationEmail">
            <int:header name="Content-Type" value="application/x-www-form-urlencoded"/>
        </int:method>
    </int:gateway>

    <int:channel id="requestChannel"/>

    <int-http:outbound-gateway request-channel="requestChannel"
                           url="http://localhost"
                           http-method="POST"
                           expected-response-type="java.lang.String"/>

</beans>

Then I changed my interface to take a Map as it's argument rather than the pojo:

public interface RequestGateway {
    String echo(Map<String, String> request);
}

The pojo itself remains as before; and the class that invokes the service is changed so that it creates a Map and passes it:

public class HttpClientDemo {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("/si-email-context.xml");
        RequestGateway requestGateway = context.getBean("requestGateway", RequestGateway.class);

        Pojo pojo = new Pojo("Fred", "Bloggs");

        Map<String, String> requestMap = new HashMap<String, String>();
        requestMap.put("fName", pojo.getFName());
        requestMap.put("sName", pojo.getSName());

        String reply = requestGateway.echo(requestMap);
        System.out.println("Replied with: " + reply);
    }
}

I'm sure there are several more elegant ways of transforming the pojo into a Map, but for the time being this answers my question.

To send POST parameters with a http outbound-gateway you need to set the Content-Type to application/x-www-form-urlencoded and you need to pass a Map of key/values pairs.