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