0
votes

I have one inbound gateway which receives messages over Rest. All messages recieved enter to Internal Gateway . Below is the inbound gateway xml file.

 <bean name="testConfig" class="test.TestApiConfiguration"/>
    <context:annotation-config/>

    <int-http:inbound-gateway request-channel="requestChannel" supported-methods="POST" path="/data" reply-channel="replyChannel"
                              request-payload-type="com.test.model.CallFlow" header-mapper="cc20InBoundHeaders" error-channel="errorChannel" reply-timeout="9000">
        <int-http:request-mapping produces="application/json" consumes="application/json"/>
    </int-http:inbound-gateway>

    <bean id="cc20InBoundHeaders" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
        <property name="inboundHeaderNames" value="*"/>
    </bean>

    <bean id="cc20OutBoundHeaders" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
        <property name="outboundHeaderNames" value="Content-Type, HTTP_REQUEST_HEADERS"/>
        <property name="userDefinedHeaderPrefix" value="" />
    </bean>

So, inbound gateway messages arrive as Json correctly and then an Internal Gateway accepts them and messages are passed into channels are per the configuration.

@MessagingGateway(name="callFlowGateway", requestChannel = "callFlowRequestChannel")
public interface ICallFlow {

    /**
     * Process CallFlow Request
     * @param message SI Message covering APiCall payload and relevant headers for service
     */
    @Gateway
    void processCallFlowRequest(Message<CallFlow> message);

}

Till here, it works as expected. Messages flow to Filter and then router. in Router, if type of one json property is "drink" service, then drink channel is invoked and relevant outbound gateways are called to request an external API endpoints over REST.

But before calling each of the rest endpoints of that external API, you need to have a valid session id token to access other endpoints. It returns a session id in its payload to call other endpoints Beside that, it takes application/x-www-form-urlencoded as content Type in header. I created a transformer to create request for authentication service.

@MessageEndpoint               
public class AuthenticateTransformer {

    @Transformer(inputChannel = "splitterChannel", outputChannel = "authenticateRequestChannel")
    public Message<?> transform(CallFlow callFlow) {

        Map<String, Object> messagePayload = new HashMap<String, Object>();
        messagePayload.put("user", "test");
        messagePayload.put("password", "test");
        return MessageBuilder.withPayload(messagePayload).setHeader("Content-Type", "application/x-www-form-urlencoded").build();
        }
}

So, ideally , a call comes to inbound gateway- Json is converted to an internal object. Based on one property value in JSON, i call different external rest endpoints using http outbound gateway.

Since the call for authentication to get session id is not in Json that is received, i have to create an order in the flow.

  1. I need to invoke an http outbound gateway for authentication to get that session id. How can i invoke this outbound from inbound gateway because that should be executed before every call to other endpoint.

  2. After i get that session id , then i want other endpoints over Rest, at this phase, i want ICallFlow gateway to be called , so that based on value in json, and that session id from step 1, i can call other rest endpoints and get response back.

So, i am stuck in passing that session id token from First call to the second call ? plus i want ICallFlow only be invoked after first authentication request is complete , and pass that session into other subsequent requests. I read that header enricher can do that, where i can put payload into headers, but somehow its not working. Also, i am not sure how to create above flow in the right order.

Any help would be highly appreciated.

1

1 Answers

0
votes

You that's too much information in a single thread and it somehow confusing and misleading.

What I can suggest you is something like ContentEnricher: https://docs.spring.io/spring-integration/docs/5.0.1.RELEASE/reference/html/messaging-transformation-chapter.html#payload-enricher

So, you will call that auth service via request-channel sub-flow, get a session id back and will be able to populate it into headers or that ICallFlow payload if that is possible.

you should be careful using MessageBuilder in the @Transformer use-case. That one doesn't merge request headers afterwards and you won't be able to bring a response to the <int-http:inbound-gateway> in the beginning, just because the replyChannel header will be lost.

The way to carry request headers is like accept a Message in the transform() method and call copyHeaders() on the MessageBuilder.