Any word on a strategy for this?
Printable View
Any word on a strategy for this?
We probably have to update documentation explaining this rare case but here is the scoop.
When gateway method has no parameters, it simply means that you will be receiving messages instead of sending or sending and receiving.
Look at it this way; Messaging Gateway by definition is an entry point to the Messaging system. Interaction with the Messaging system could exist at 3 levels and SI gateway simply supports all 3.
1. Send only:
public void foo(Object whatever);
2. Send and Receive:
public Object foo(Object whatever);
3. Receive only:
public Object foo();
So all you need to do is to change configuration a bit
Note that I only have a reply channel. Request channel is meaningless in this case since there is no request. The reply channel is also a pollable channel.Code:<integration:gateway id="artifactProvider"
service-interface="test.ArtifactProvider">
<integration:method name="getArtifact" reply-channel="request.noparam"/>
. . .
In your code send a message to this channel before executing getArtifact() method
Hope that explainsCode:MessageChannel channel = appContext.getBean("request.noparam", MessageChannel.class);
channel.send(new GenericMessage<String>("hello"));
System.out.println("Received: " + provider.getArtifact());
I have a question. If I use the "Receive only", how can I guarantee that I receive the correct message?
For example, if I have a method called "public String getSession();" and it returns a session string thats bound to the current connecting client, how can I make sure that I dont receive a message intended for someone elses client, for example if 20 people make a function call to getSession at the same time?
I am not sure I understand the comment about current client etc.... All you are doing is receiving the next Message from the Queue. It seems to me you are implying some state awareness which contradicts one of the core concept of Messaging architecture - stateless architecture. The only component that contains any state is Message itself (not endpoints)
To explain my predicament and what I was initially trying to do is the following.
Have a Bean that creates a session token based on some knowledge of the connecting client. This bean is the SessionManager.
On the LoginManager I make a function call createNewSession() through an interface ISessionManager (which the gateway is mimic'ing). I am expecting a reply with my session token, but no arguments are required to be sent
as the client stuff is handled somewhat invisibly.
I don't see why I am not allowed to do this, because by breaking the function call out and seperating it into a message transaction, I can then perform aspect oriented programming procedures on the message itself.
I still don't understand how your use case maps to Messaging and Spring Integration. As i said before you are receiving the next Message from the queue, nothing more.
I tried the recommendations and still have problems. Without commenting out this line:
I get the error:Code:
<!-- integration:service-activator input-channel="request.noparam" output-channel="reply.noparam" ref="artifactManager" method="getArtifact"/-->
Once this line is commented out, I can run without error, but it doesn't work the way it is supposed to. This recommended solution basically puts a message on a queue and then the gateway reads that value off the queue and totally bypasses the service activator on the other end.Code:SEVERE: org.springframework.integration.MessageDeliveryException: Dispatcher has no subscribers.
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:104)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:61)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:176)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:160)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:125)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:119)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:101)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.endpoint.PollingConsumer.doPoll(PollingConsumer.java:70)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:144)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:207)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:202)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
I apologize for continuing to bother you about this, but it still seems like what I am attempting to do is not that unusual. It seems like I have two possible choices:
- Change my API so that I always have a parameter. This seems fundamentally wrong.
- Use polling which doesn't seem like it solves the problem at all.
I understand the implementation determines request, request/response, and response scenarios based on the method signature, but I believe that it would be extremely helpful if a configuration item would be added to let this scenario (ie. no param method) be used in a request/response interaction.
That is a whole separate issue. You have service-activator that defines output-channel which is a DirectChannel which has no subscribers. But keep in mind that has no connection to the no-param Gateway method issue.
Now I'm really confused. Your previous instructions said to modify the gateway definition to remove the request channel and only have a reply channel. By doing this, it caused the error I included in my last post. But, a service activator requires an input and output channel. If I don't have anything sending my service activator a message, how can it respond?
All I'm trying to do is trigger a remote service to send me a response. The way I'm understanding this is if my remote service happened to be a webservice, there would be no way to use spring integration to integrate with that method if it doesn't have parameters to send it.
If you remote service is a web service than you would issue something like a SOAP request or REST request and we support both via HTTP and WS modules.
Your original issue was about Gateway interface that has a non-void and no-parameter Method and as I explained this would expose a PPOJO way to pull a message from the QueueChannel. Just to understand my analogy a non-POJO way would be to do this:
where with Gateway all you'd need to do is this:Code:QueeuChannel channel = . . .
Message message = channel.receive();
String payload = (String)message.getPayload()
The Service Activator has nothing to do with this gateway unless its output-channel is the QueueChannel from which you are polling Messages with the Gateway.Code:public interface MyGateway{
public String foo();
}
MyGateway gateway = . . .
String payload = gateway.foo();
All I ma trying to explain is the use case for no-param non-void gateway method and what it means. The assumptions you made in your previous configurations are incorrect and I am trying to explain what is wrong. I hope it helps