0

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.

piet.t
  • 11,718
  • 21
  • 43
  • 52
keth
  • 793
  • 2
  • 11
  • 36

1 Answers1

1

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! ##############");
keth
  • 793
  • 2
  • 11
  • 36
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • In here i want to provide a generic http:outbound-gateway where developers can pass and invoke any POST or GET request with any URL with different types of request payload. As per my initial reading we need to provide the http-method and expected-response-type with the http:outbound-gateway configuration. Therefore i want to find a way to dynamically configure http-method and expected-response-type. I was able to pass the url dynamically using the as per my above example. – keth Jun 06 '18 at 04:28
  • 1
    My mistake; you can use expressions - see the edit to my answer. – Gary Russell Jun 06 '18 at 14:15
  • I was able to find a way to dynamically pass the URL, HTTP method and expected response type. Please have a look my edit. I am still looking for a way to pass the Dynamic post request body – keth Jun 11 '18 at 15:02
  • 1
    You should pass the URL, etc, as headers instead of properties on the payload. `"headers['urlHeader']` etc. – Gary Russell Jun 11 '18 at 15:05
  • i was able to find a solution and i have mentioned it under EDIT 2. Do you see any issues or concerns regarding the solutions. Appreciate the help – keth Jun 12 '18 at 12:09