PDA

View Full Version : AutoStartup property of SimpleMessageListenerContainer


keenan
09-04-2008, 03:09 PM
If I attempt to start our command line service without first having started AMQ, the process aborts with a stack trace on the console:


Unhandled Exception: System.Configuration.ConfigurationErrorsException: Error creating context 'spring.root':
No connection could be made because the target machine actively refused it 127.0.0.1:61616
---> Spring.Util.FatalReflectionException: Cannot instantiate Type [Spring.Context.Support.XmlApplicationContext] using ctor [Void .ctor(System.String, Boolean, System.String[])] : 'Exception has been thrown by the target of an invocation.'
---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> Spring.Objects.Factory.ObjectCreationException: Error thrown by a dependency of object 'XXX' defined in 'file [XXX.xml]' : Initialization of object failed : No connection could be made because the target machine actively refused it 127.0.0.1:61616 while resolving 'StartObjects[0]' to 'XXX' defined in 'file [XXX.xml]'
---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:61616
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
at Apache.NMS.ActiveMQ.Transport.Tcp.TcpTransportFact ory.Connect(String host, Int32 port) in TcpTransportFactory.cs:line 114
at Apache.NMS.ActiveMQ.Transport.Tcp.TcpTransportFact ory.CreateTransport(Urilocation) in TcpTransportFactory.cs:line 72
at Apache.NMS.ActiveMQ.ConnectionFactory.CreateConnec tion(String userName, String password) in ConnectionFactory.cs:line 94
at Apache.NMS.ActiveMQ.ConnectionFactory.CreateConnec tion() in ConnectionFactory.cs:line 80
at Spring.Messaging.Nms.Connections.SingleConnectionF actory.DoCreateConnection() in SingleConnectionFactory.cs:line 349
at Spring.Messaging.Nms.Connections.SingleConnectionF actory.InitConnection() in SingleConnectionFactory.cs:line 273
at Spring.Messaging.Nms.Connections.SingleConnectionF actory.CreateConnection() in SingleConnectionFactory.cs:line 237
at Spring.Messaging.Nms.Support.NmsAccessor.CreateCon nection() in NmsAccessor.cs:line 145
at Spring.Messaging.Nms.Listener.AbstractListenerCont ainer.CreateSharedConnection() in AbstractListenerContainer.cs:line 451
at Spring.Messaging.Nms.Listener.AbstractListenerCont ainer.EstablishSharedConnection() in AbstractListenerContainer.cs:line 413
at Spring.Messaging.Nms.Listener.SimpleMessageListene rContainer.DoInitialize() in SimpleMessageListenerContainer.cs:line 161
at Spring.Messaging.Nms.Listener.AbstractListenerCont ainer.Initialize() in AbstractListenerContainer.cs:line 273
at Spring.Messaging.Nms.Listener.AbstractListenerCont ainer.AfterPropertiesSet() in AbstractListenerContainer.cs:line 222
at Spring.Objects.Factory.Support.AbstractAutowireCap ableObjectFactory.InvokeInitMethods(Object target, String name, IConfigurableObjectDefinition definition) in AbstractAutowireCapableObjectFactory.cs:line 1257


My question: Is this the desired/expected behavior for a SimpleMessageListenerContainer when the AutoStartup property is set to false?

Here is the use case: We have multiple instances of this service and in cases where queueing features are not needed, I was hoping to be able to deploy the same Config.xml in all locations and use the AutoStartup property (set from a placeholder) to enable/disable queueing.

Does that make sense?

Mark Pollack
09-04-2008, 08:07 PM
Hi,

The AutoStart functionality is related to calling Connection.Start and not creating the connection. By default the connection to the broker is always made but if Start is not called, then messages will not be delivered. Sounds like you want conditional object definitions, which is something that I know will be addressed in Spring Java 3.0, perhaps along the lines of

<object id="myObject" type="MyType, MyAssembly" condition="SpEL expression"/>


but at the moment this isn't supported. The way around this is some conventions regarding the naming of the configuration file or to have logic that bootstraps the server so that it is aware which config files to load based on the environment.

One crude workaround is to create an IObjectFactoryPostProcessor (http://www.springframework.net/doc-latest/reference/html/objects.html#objects-factory-customizing-factory-postprocessors) that will delete objects based on the evaluation of some condition, something like

<object type="DeletingObjectDefinitionIObjectFactoryPostProcesso r, MyAssembly">
<property name="ObjectNameToDelete" value="myObject"/>
<property name="Condition" value="${booleanVariable"/>
</object>

keenan
09-05-2008, 04:28 AM
Mark,

Thanks for the clarification. Either of the proposed solutions will work although I'm leaning towards conditional inclusion of configuration files.


I have a follow up question. If AutoStartup is false and the following sequence takes place:

1) add 10 messages to queue
2) start listener
3) add 10 more messages to queue

What is the expected behavior? My observation is that the first 10 messages show up in the logs as Rejecting received message because of the listener container having been stopped in the meantime, which makes sense. After the listener is started and the additional messages are sent, the second set are received by the listener.

The original set of messages remain in the queue and are never delivered.

If I switch AutoStartup to true and restart, the original messages are received by the listener.

So, what I see is that a listener with AutoStartup=false will not receive existing messages on a queue, only new messages.

Mark Pollack
09-05-2008, 06:53 PM
Hi,

Actually the behavior your report doesn't make sense because the first set of 10 messages should not be dispatched as Spring hasn't called Start on the connection yet. I set a breakpoint at all locations where we call Connection.Start and it wasn't called.

Digging into it a bit more, it seems this is a bug in ActiveMQ .NET bindiing. In the ActiveMQConnection constructor it starts the transport and the initial state is set to 'started'. The Java version doesn't seem to do that from what I can tell. Can you file a bug report with the ActiveMQ project regarding this? The JMS spec states this type of behavior which isn't being followed.

I know this isn't the case with TIBCO as it was a critical piece of functionality for me to sync up client state.

Cheers,
Mark

keenan
09-05-2008, 08:16 PM
Mark,

Thanks for tracking this down. I have created a JIRA issue (https://issues.apache.org/activemq/browse/AMQNET-111) withe the ActiveMQ.NET team.

In the future I will try to determine if it is an NMS problem before posting here so as not to waste cycles looking in the wrong spot.

Mark Pollack
09-05-2008, 10:00 PM
Hi,
NP, that is par for the course, and I could still be wrong on the matter...
Mark

keenan
09-07-2008, 02:01 AM
The JIRA issue I opened is marked Fixed/Closed. I downloaded the latest NMS source and compiled a new assembly.

The behavior has changed, but is still not what I expected.

The first set of messages are received and processed even before the Start() method is invoked on the listener container.

The stack trace reveals that NMS is dispatching the messages, so I'll follow up on why the dispatch occurs on a connection that is not yet started.

=== EDIT ===

Oops... I had AutoStartup set to true, so the above statements are not accurate.

The behavior appears to be the same as before. I'll continue testing...

=== EDIT 2 ===

I have re-opened the issue with the NMS team based on what I saw during my debugging sessions.

keenan
09-09-2008, 07:12 PM
This is now fixed in Apache.NMS.ActiveMQ library (you need Revision 693525 or later from the 1.0.0 tag)

I verified that a listener container with AutoStartup set to false will not receive messages until the Start() method is called.