PDA

View Full Version : Converting Remote calls to use Jms:channel



greenwayb
Jan 13th, 2010, 01:15 AM
I am converting existing code which used to use Jini for remote method calls.

The basic idea is that the end Service has a number of methods on it, and i want to call them remotely. I wanted to use jms as the transport.

I have created an intial outline but run into a problem when using <jms:channel

</root>][Headers={history=[[name=getStockOfTheWeek;type=gateway;timestamp=1263 365328929], [name=ServiceActivator for [com.jdv.b2b.research.aspect.AspectResearchImpl$$En hancerByCGLIB$$8beb13fe.getStockOfTheWeek]];type=endpoint;timestamp=1263365329030]], $timestamp=1263365328926, $id=26153905-2c05-4c03-8f6b-18a904eb1ea9}]
WARN : org.springframework.jms.listener.DefaultMessageLis tenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.integration.core.MessagingExce ption: failed to handle incoming JMS Message
at org.springframework.integration.jms.JmsDestination BackedMessageChannel.onMessage(JmsDestinationBacke dMessageChannel.java:158)
at org.springframework.jms.listener.AbstractMessageLi stenerContainer.doInvokeListener(AbstractMessageLi stenerContainer.java:559)
at org.springframework.jms.listener.AbstractMessageLi stenerContainer.invokeListener(AbstractMessageList enerContainer.java:498)
at org.springframework.jms.listener.AbstractMessageLi stenerContainer.doExecuteListener(AbstractMessageL istenerContainer.java:467)
at org.springframework.jms.listener.AbstractPollingMe ssageListenerContainer.doReceiveAndExecute(Abstrac tPollingMessageListenerContainer.java:323)
at org.springframework.jms.listener.AbstractPollingMe ssageListenerContainer.receiveAndExecute(AbstractP ollingMessageListenerContainer.java:261)
at org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.invokeL istener(DefaultMessageListenerContainer.java:977)
at org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.execute OngoingLoop(DefaultMessageListenerContainer.java:9 69)
at org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.run(Def aultMessageListenerContainer.java:871)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.integration.message.MessageHan dlingException: error occurred in message handler [org.springframework.integration.handler.BridgeHand ler@ac97cc]
at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:70)
at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :103)
at org.springframework.integration.dispatcher.Unicast ingDispatcher.dispatch(UnicastingDispatcher.java:9 0)
at org.springframework.integration.jms.JmsDestination BackedMessageChannel.onMessage(JmsDestinationBacke dMessageChannel.java:155)
... 9 more
Caused by: java.lang.IllegalStateException: Bridge handler requires an output channel
at org.springframework.util.Assert.state(Assert.java: 384)
at org.springframework.integration.handler.BridgeHand ler.verifyOutputChannel(BridgeHandler.java:47)
at org.springframework.integration.handler.BridgeHand ler.handleRequestMessage(BridgeHandler.java:41)
at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:100)
at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:64)
... 12 more

The scenario i have will work if i use <channel > but swapping to <jms:channel > i will get the error above.


The Basic setup i have is a Gateway, annotated with @Component, and then the methods annotated with @Gateway and each method to have a request and reply channel, ie:

@Gateway(requestChannel="stockOfTheWeek" , replyChannel = "stockOfTheWeekReply")
AspectResearchResponse getStockOfTheWeek(AspectResearchStockOfTheWeekData Request request);


There is an Implementation class which implements this gateway ie:

@MessageEndpoint
@Configuration
public class AspectResearchImpl implements AspectResearchGateway, SmartLifecycle {

Implementation methods are then:

@ServiceActivator(inputChannel = "modelPortfolioView", outputChannel = "modelPortfolioViewReply")
public AspectResearchResponse getModelPortfolioView(AspectResearchModelPortfolio ViewRequest request) {
URL url = null;


Relevant items of spring config are then:

<integration:annotation-config/>
<context:component-scan base-package="com.jdv.b2b.research.aspect" />

<!--<channel id="modelPortfolioView" />-->
<!--<channel id="modelPortfolioViewReply" />-->

<jms:channel id="modelPortfolioView" queue="requestQueue" />
<jms:channel id="modelPortfolioViewReply" queue="responseQueue" />

<gateway id="aspectGateway" service-interface="com.jdv.b2b.research.aspect.AspectResearchGateway" />

As you can see above i have a commented out section with the channel ids, if these are uncommented and the jms:channels commented all works fine.

Changing only to jms:channels causes the Bridge handler requires output channel error.

This was tested on M2 and CI-752.

Am i doing something obviously wrong or is this an issue?

greenwayb
Jan 13th, 2010, 03:35 AM
<gateway id="aspectGateway" service-interface="com.jdv.b2b.research.aspect.AspectResearchGateway" />

Looks like if i attempt the same thing, but use the jms:outbound gateways i can get what i desired. I was just hoping that jms:channel could be used by way of making one (smaller) definition.

ie use:
<channel id="stockOfTheWeek" />
<channel id="modelPortfolioView" />

Then:

<jms:outbound-gateway request-destination="requestQueue" reply-destination="responseQueue" receive-timeout="6000"
request-channel="stockOfTheWeek"/>

<jms:outbound-gateway request-destination="requestQueue" reply-destination="responseQueue" receive-timeout="6000"
request-channel="modelPortfolioView"/>


<jms:inbound-gateway request-destination="requestQueue" request-channel="jmsOutputChannel"/>

greenwayb
Jan 13th, 2010, 07:09 PM
Actually i can only use jms-outbound gateway wired through to the service-activator if the message request objects are different (obvious really)

What i was trying to do though was to use the service activator annotated with the relevant channels initiated on the gateway such that the methods were mapping 1:1. Again this works with a standard channel, but not with a jms:channel.

I am aware that i could rewrite the code to change the model and create specific request type objects rather than 1:1 calls, but i wanted to limit the impact on existing code and try to find the easiest way to implement my solution.

Is anyone using jms:channel successfully ?