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