Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring integration gateway methods with multiple parameters

I have a question regarding Gateways and multiple parameters:

The context: I would like a Gateway to have two methods:

search(Query query, FetchSpec fetchSpec);
search(int queryId, FetchSpec fetchSpec);

The first method should route directly to a service executing the query, while the second should route to another service to have the queryId resolved into a Query, and then on to the first Service to have the Query executed.

The Question: What would be best practice for having TWO (or more) parameters as arguments for a Gateway method? It seems that the entire pattern is targeted at having only one parameter corresponding the one Message. Should I use the message headers for adding extra parameters?

like image 430
Christian von Wendt-Jensen Avatar asked Feb 20 '23 00:02

Christian von Wendt-Jensen


2 Answers

I guess that asking the question was forcing me to think about the problem.

The answer to my question is this:

The Gateway takes exactly ONE parameter as Payload - the rest goes to headerfields with custom names. So in my case I would do like this:

@Gateway (requestChannel = "incomingAdhocQuery")
public ResultSet search(@Payload Query query, @Header("fetchSpec") FetchSpec fetchSpec);

@Gateway (requestChannel = "incomingPersistedQuery")
public ResultSet search(@Payload int queryId, @Header("fetchSpec") FetchSpec fetchSpec);

I DEFINE which parameters are payload and which are headers.Then each method direct its messages to specific channels for service activation.

In the configuration I define my Gateway like this:

<int:gateway service-interface="my.company.search.Search" />

And then I activate the search service with one specific configuration for each gateway method:

<bean id="myManager" class="my.company.search.MyManager"/>
<int:service-activator input-channel="incomingAdhocQuery"  expression="@myManager.fetchByQuery(payload, headers['fetchSpec'])"/>
<int:service-activator input-channel="incomingPersistedQuery" expression="@myManager.fetchById(payload, headers['fetchSpec'])"/>

In this way, I design my Manager like this:

public ResultSet fetchById(int queryId, FetchSpec fetchSpec) {...}

public ResultSet fetchByQuery(Query query, FetchSpec fetchSpec) {...}

I find this solution very elegant because I do not have to have any dependencies to Spring in my Service. Only the Gateway need have this dependency. The wiring is all done in the spring configuration. I think I'm in love with spring-integration :-D

like image 54
Christian von Wendt-Jensen Avatar answered Mar 03 '23 20:03

Christian von Wendt-Jensen


You can use following on the gateway side:

@Payload("T(java.util.Arrays).asList(#args[0],#args[1])")
search(Query query, FetchSpec fetchSpec);

while on service activator if assuming it's same signature:

@ServiceActivator(inputChannel = "request", outputChannel = "reply")
search(@Payload("#this[0]")  Query query, @Payload("#this[1]") FetchSpec fetchSpec)
like image 44
Manoj Arya Avatar answered Mar 03 '23 20:03

Manoj Arya