keth
keth

Reputation: 825

Spring Integration outbound gate way with dynamic URLs, HTTP methods and different response types

I have a little bit understanding about Spring Integration and so far i have used JMS and File outbound adapters and now i want to introduce the HTTP out bound adapter for Spring REST support. So far so good an i was able to call external REST api with outany issue as below.

Spring Integration Config

<int-http:outbound-gateway id="outbound.gateway"
    request-channel="get.request.channel" url="https://jsonplaceholder.typicode.com/posts/1"
    http-method="GET" expected-response-type="com.cst.entity.Post"
    charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel">
</int-http:outbound-gateway>

Outbound gateway invokation

public void restTest() throws Exception{

    Message<?> message = MessageBuilder.withPayload().build();
    getRequestChannel.send(message);
    Message<?> receivedMsg = receivedChannel.receive();
    Post post = (Post) receivedMsg.getPayload();

    System.out.println("############## ServerMsg ##############");
    System.out.println(post.toString());
    System.out.println("############## Done! ##############");

}

However i want to develop a framework where developers can invoke any REST url with any method and expect different types of response types. I found a way of dynamically setting the URL as below by introducing

<int-http:outbound-gateway id="outbound.gateway"
    request-channel="get.request.channel" url="{fhirurl}"
    http-method="GET" expected-response-type="com.bst.pages.crm.web.Post"
    charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel">
</int-http:outbound-gateway>

with

public void restTest() throws Exception{

    FHIRInput input = new FHIRInput();
    input.setUrl(url);

    Message<?> message = MessageBuilder.withPayload(input).build();
    getRequestChannel.send(message);
    Message<?> receivedMsg = receivedChannel.receive();
    Post post = (Post) receivedMsg.getPayload();

    System.out.println("############## ServerMsg ##############");
    System.out.println(post.toString());
    System.out.println("############## Done! ##############");

}

Then i tried to implement dynamic HTTP methods with dynamic response types using the above method and it didn't work and it looks like we can handle only the URL using <int-http:uri-variable/>.

What would be the ideal solution for this. appreciate your help

Thanks, Keth

EDIT

After following below comments i was able to implement a framework where developers can call use dynamic URL s based on the payload content. below is my configuration for HTTP outbound adapter.

<int-http:outbound-gateway id="outbound.gateway"
    request-channel="get.request.channel" url="{fhirurl}"
    http-method-expression="payload.getHttpMethod()" expected-response-type-expression="payload.getResponseType()"
    charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel">

    <int-http:uri-variable name="fhirurl" expression="payload.getUrl()"/>

</int-http:outbound-gateway>

However im still looking for a way to pass a dynamic request body as a POST parameter. Since we use payload to carry the URL, http method and expected response type i can not pass the request body.

Upvotes: 0

Views: 2173

Answers (1)

Gary Russell
Gary Russell

Reputation: 174554

It's not clear what you mean by

Then i tried to implement dynamic HTTP methods with dynamic response types using the above method and it didn't work and it looks like we can handle only the URL using <int-http:uri-variable/>.

To handle multiple response types, get them as String (JSON) and then use transformer(s) to convert to the types.

EDIT1

The response type and method can be an expressions:

<xsd:attribute name="expected-response-type-expression" type="xsd:string">
    <xsd:annotation>
        <xsd:documentation>
            SpEL expression to determine the type for the expected response to which the response body should be converted
            The returned value of the expression could be an instance of java.lang.Class or
            java.lang.String representing a fully qualified class name.
            This attribute cannot be provided if expected-response-type has a value
        </xsd:documentation>
    </xsd:annotation>
</xsd:attribute>

<xsd:attribute name="http-method-expression" type="xsd:string">
    <xsd:annotation>
        <xsd:documentation>
            The SpEL expression to determine HTTP method, use when executing requests with this adapter,
            dynamically. This attribute cannot be provided if http-method has a value.
        </xsd:documentation>
    </xsd:annotation>
</xsd:attribute>

Solution

I was able to come with a solution for a simple framework where we can allow developers to call different rest URLs with different HTTP methods and Response types.

This is the configuration for Spring Integration

<int:channel id='reply.channel'>
    <int:queue capacity='10' />
</int:channel>
<int:channel id='request.channel'/>

<int:channel id='outbound.Channel'/>

<int:gateway id="outboundGateway"
    service-interface="com.bst.pm.PostGateway"
    default-request-channel="outbound.Channel">
</int:gateway>

<int:object-to-json-transformer input-channel="outbound.Channel" output-channel="request.channel"/>



<int-http:outbound-gateway id="outbound.gateway"
    request-channel="request.channel" url-expression="headers.bstUrl"
    http-method-expression="headers.bstHttpMethod" expected-response-type-expression="headers.bstExpectedResponseType"
    charset="UTF-8" reply-timeout="5000" reply-channel="reply.channel"
    mapped-request-headers="bst*, HTTP_REQUEST_HEADERS">

</int-http:outbound-gateway>

and here is my Java code for invoking the above integration system.

@Autowired @Qualifier("reply.channel") PollableChannel receivedChannel;
@Autowired @Qualifier("request.channel") MessageChannel getRequestChannel;
@Autowired @Qualifier("outbound.Channel") MessageChannel httpOutboundGateway;

    Post post = new Post();
    post.setTitle("Spring INtegration Test");
    post.setBody("This is a sample request body to test Spring Integration HTTP Outbound gateway");
    post.setUserId(Long.valueOf(1));

    Message<?> message = MessageBuilder.withPayload(post)
                        .setHeader("bstUrl", "https://jsonplaceholder.typicode.com/posts")
                        .setHeader("bstHttpMethod", "POST")
                        .setHeader("bstExpectedResponseType", "com.bst.pages.crm.web.Post")
                         .build();

    httpOutboundGateway.send(message);
    Message<?> receivedMsg = receivedChannel.receive();

    Post post = (Post) receivedMsg.getPayload();
    System.out.println("############## ServerMsg ##############");
    System.out.println(o);
    System.out.println("############## Done! ##############");

Upvotes: 1

Related Questions