I turned my pingpong example into a set of unit tests, and created
patches (attached to LINGO-29) for trunk and 1.1. The tests are
identical, only difference is the activemq config for 1.1 so that it
works with AMQ 3.x.
There are 3 tests:
PingPongTest - This is the real use case, async invoke, sync callback
invoke on a topic
SyncPingPongTest - Tests if a sync/queue invoke with a sync callback
invoke works
AsyncPingResponderSyncPingPongTest - Tests if a sync/queue invoke
with an async callback invoke works
All of these tests pass with Lingo 1.1, only
AsyncPingResponderSyncPingPongTest passes with trunk.
I'd really appreciate it if someone could look into this and find a
solution. I am not yet familiar enough with the Lingo codebase to
determine what the proper fix is.
--jason
On Nov 2, 2006, at 3:57 PM, Jason Dillon wrote:
Hi folks, I am trying to figure out some of the more advanced Lingo
usage... trying to get a simple working example of EventListener
remoting, but so far I have had no luck.
I'm trying to get a super-simple ping/pong from a client to a set
of nodes listening on a topic, where the invocation is one-way, and
the server's ping responder will invoke a method on an ping
listener to send its pong.
This is what I've got:
<snip>
public interface PingListener
extends EventListener
{
void pong();
}
public interface PingResponder
{
void ping(PingListener listener);
}
public class PingResponderImpl
implements PingResponder
{
public void ping(final PingListener listener) {
log.info("Responding to PING")
listener.pong();
}
}
</snip>
My client is also simple, though in this example I've trimmed out
the bits which load the spring ctx and autowire the components:
<snip>
public class PingClient
{
public void ping() {
PingCollector collector = new PingCollector();
responder.ping(collector);
// wait for ctrl-c to end
}
public class PingCollector
implements PingListener
{
public void pong() {
log.info("Received PONG");
}
}
}
</snip>
And then the spring ctx:
<snip>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/
beans http://www.springframework.org/schema/beans/spring-
beans-2.0.xsd">
<bean id="jmsFactory"
class="org.apache.activemq.ActiveMQConnectionFactory"
scope="singleton">
<property name="brokerURL" value="vm://localhost?
broker.persistent=false"/>
</bean>
<bean id="pingResponderDestination"
class="org.apache.activemq.command.ActiveMQTopic" scope="singleton">
<constructor-arg index="0" value="gbuild.pingResponder"/>
</bean>
<bean id="pingResponder"
class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface"
value="org.apache.geronimo.gbuild.ping.PingResponder"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="pingResponderDestination"/>
</bean>
<bean id="pingReponderImpl"
class="org.apache.geronimo.gbuild.ping.PingResponderImpl"
scope="singleton"/>
<bean id="pingReponderService"
class="org.logicblaze.lingo.jms.JmsServiceExporter" scope="singleton">
<property name="service" ref="pingReponderImpl"/>
<property name="serviceInterface"
value="org.apache.geronimo.gbuild.ping.PingResponder"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="pingResponderDestination"/>
</bean>
</beans>
</snip>
In this configuration, I see the "Responding to PING" and "Received
PONG" log messages, which is followed by some exceptions after a
delay:
<snip>
15:39:43,075 WARN [JmsClientInterceptor] Remote access error:
invocation: method 'pong', arguments []; target is null
javax.jms.JMSException:
edu.emory.mathcs.backport.java.util.concurrent.TimeoutException
at
org.logicblaze.lingo.jms.impl.MultiplexingRequestor.createJMSException
(MultiplexingRequestor.java:205)
at
org.logicblaze.lingo.jms.impl.MultiplexingRequestor.request
(MultiplexingRequestor.java:133)
at org.logicblaze.lingo.jms.JmsClientInterceptor.invoke
(JmsClientInterceptor.java:138)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:185)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke
(JdkDynamicAopProxy.java:209)
at $Proxy6.pong(Unknown Source)
...
</snip>
And then a warning from the MultiplexingRequestor:
<snip>
15:39:43,113 WARN [MultiplexingRequestor] Response received for
unknown correlationID: 2 request: ActiveMQObjectMessage {commandId
= 9, responseRequired = true, messageId =
ID:Bliss.local-52836-1162510752209-2:6:1:1:2, originalDestination =
null, originalTransactionId = null, producerId =
ID:Bliss.local-52836-1162510752209-2:6:1:1, destination = temp-
queue://ID:Bliss.local-52836-1162510752209-2:13:1, transactionId =
null, expiration = 1162510813098, timestamp = 1162510783104,
arrival = 0, correlationId = 2, replyTo = null, persistent = true,
type = null, priority = 4, groupID = null, groupSequence = 0,
targetConsumerId = null, compressed = false, userID = null, content
= [EMAIL PROTECTED],
marshalledProperties = null, dataStructure = null,
redeliveryCounter = 0, size = 12390, properties = null,
readOnlyProperties = true, readOnlyBody = true, droppable = false}
</snip>
And at this point, the method call to responder.ping() is still
blocking.
If I change the destination to use a queue, then I get the same
timeout trace, but the call to responder.ping() unblocks due to the
JMSException being propagated.
If I enable a metadata strategy to make this async for one way
voids, with something like:
<snip>
<bean id="pingResponder"
class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface"
value="org.apache.geronimo.gbuild.ping.PingResponder"/>
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="pingResponderDestination"/>
<property name="metadataStrategy">
<bean class="org.logicblaze.lingo.SimpleMetadataStrategy">
<constructor-arg value="true"/>
</bean>
</property>
</bean>
</snip>
The I see the "Responding to PING" but right after I get this
exception:
<snip>
15:46:35,401 WARN [RemoteInvocationTraceInterceptor] Processing of
JmsServiceExporter remote call resulted in fatal exception:
org.apache.geronimo.gbuild.ping.PingResponder.ping
java.lang.UnsupportedOperationException: A destination must be
specified.
at org.apache.activemq.ActiveMQMessageProducer.send
(ActiveMQMessageProducer.java:448)
at org.logicblaze.lingo.jms.impl.OneWayRequestor.doSend
(OneWayRequestor.java:196)
at
org.logicblaze.lingo.jms.impl.MultiplexingRequestor.doSend
(MultiplexingRequestor.java:189)
at org.logicblaze.lingo.jms.impl.OneWayRequestor.send
(OneWayRequestor.java:101)
at org.logicblaze.lingo.jms.impl.OneWayRequestor.send
(OneWayRequestor.java:97)
at
org.logicblaze.lingo.jms.impl.MultiplexingRequestor.request
(MultiplexingRequestor.java:122)
at org.logicblaze.lingo.jms.JmsClientInterceptor.invoke
(JmsClientInterceptor.java:138)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:185)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke
(JdkDynamicAopProxy.java:209)
at $Proxy6.pong(Unknown Source)
...
</snip>
I am using Apple's JDK 1.5, Lingo 1.3 and Spring 2.0. Other simple
sync invocations work fine... but I really need to get something
working for more complicated invocations to and from an arbitrary
set of nodes.
Does anyone have any ideas how to get this working? I have been
digging around in the lingo svn, looking at the tests. Looks like
there is a test that uses an EventListener... and it appears to
pass, but I don't know what I am doing differently.
I've also been looking for other input on the lingo nabble
forums... but so far... no luck.
Any help is appreciated.
Thanks,
--jason