Well, two things. First of all the javadocs for @Subscriber would seem to indicate that putting both Publisher and Subscriber on the same method wouldn't work as Subscriber says that the annotated method "must return void".
Despite that, the solution you proposed was exactly what I tried at first, and it works fine with 1 method. It even works fine if you have more methods so long as each method has their own input channel. The problem is, the type based routing seems to happen at the object level near as I can tell so as soon as you have two methods subscribed to the same channel with different payload types you get an exception and the whole thing blows up.
Specifically if you have something like
Code:
@Subscriber(channel="input")
@Publisher(channel="output1")
public POJO doSomething(MyObject1 arg) {
return new POJO();
}
@Subscriber(channel="input")
@Publisher(channel="output2")
public AnotherPOJO doSomethingElse(MySecondObject arg) {
return new AnotherPOJO();
}
You'll get an exception as soon as you put a new message into the "input" channel. Specifically, lets say you put a MyObject1 payload into the "input" channel, the exception you get will look something like this
Code:
24 Jul 2008 09:03:54,397 [message-bus-1] WARN - MessagePublishingErrorHandler.handle(57) | failure occurred in messaging task with message: [ID=504a9062-b1ca-4b46-832d-b8c932e14a32][Header=[CorrelationID=null][Properties={}][Attributes={}][Timestamp=Thu Jul 24 09:03:53 EDT 2008][Expiration=null][Priority=NORMAL][Sequence #1 (of 1)]][Payload='MyObject1@1a93f38']
org.springframework.integration.message.MessageHandlingException: Failed to invoke handler method 'doSomethingElse' with arguments: {MyObject1@1a93f38}
at org.springframework.integration.handler.AbstractMessageHandlerAdapter.handle(AbstractMessageHandlerAdapter.java:120)
at org.springframework.integration.endpoint.HandlerEndpoint$HandlerInvokingTarget.send(HandlerEndpoint.java:136)
at org.springframework.integration.endpoint.TargetEndpoint.handleMessage(TargetEndpoint.java:103)
at org.springframework.integration.endpoint.TargetEndpoint.poll(TargetEndpoint.java:111)
at org.springframework.integration.endpoint.EndpointPoller.visitEndpoint(EndpointPoller.java:25)
at org.springframework.integration.endpoint.AbstractEndpoint.doSend(AbstractEndpoint.java:252)
at org.springframework.integration.endpoint.AbstractEndpoint.send(AbstractEndpoint.java:225)
at org.springframework.integration.endpoint.AbstractEndpoint.send(AbstractEndpoint.java:213)
at org.springframework.integration.dispatcher.AbstractDispatcher.sendMessageToTarget(AbstractDispatcher.java:74)
at org.springframework.integration.dispatcher.BroadcastingDispatcher.send(BroadcastingDispatcher.java:44)
at org.springframework.integration.dispatcher.PollingDispatcher.dispatch(PollingDispatcher.java:116)
at org.springframework.integration.dispatcher.PollingDispatcher.run(PollingDispatcher.java:102)
at org.springframework.integration.scheduling.SimpleTaskScheduler$TaskRunner.run(SimpleTaskScheduler.java:206)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:207)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NoSuchMethodException: $Proxy15.doSomethingElse(org.springframework.integration.message.GenericMessage)
at java.lang.Class.getMethod(Class.java:1605)
at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:180)
at org.springframework.integration.util.NameResolvingMethodInvoker.invokeMethod(NameResolvingMethodInvoker.java:53)
at org.springframework.integration.util.AbstractMethodInvokingAdapter.invokeMethod(AbstractMethodInvokingAdapter.java:130)
at org.springframework.integration.handler.AbstractMessageHandlerAdapter.handle(AbstractMessageHandlerAdapter.java:107)
... 20 more
Near as I can tell it looks like using @Subscriber with payload type based routing puts a selector at the object level and not the method level, and then routes any messages on that channel to all the methods on the object subscribed to it, regardless of what the object type of the argument is. When it can't find a handler of the proper type on one of the methods it falls back to checking for a overloaded method that takes a type of GenericMessage, and when it can't find one it blows up.
Edit: FYI, this was done on M5