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>
<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