© Copyright 1990-2011 P3 Consulting unless otherwise indicated. Please contact us with any questions or comments.

 

 AMQP Lib for iOS sample code

This small application demonstrates the functionalities of the AMQPLib for iOS.
Requirement: you need access to an AMQP server like RabbitMQ with the right to queue messages.
You will enter its hostname or IP address and listening port,
the virtual host to use (/ by default), the login to use to send and receive messages in the "Login" tab.
This application send messages and in order to demonstrate the functionalities also listen to the queues used.
Of course in real world sender and receiver should be different processes on different devices…
But for the sake of the demo and to not require installation on several devices, the software acts as both source and destinations of events.
For each pattern of message sending, we have set up 3 different listeners that will
show their result in 3 different text views. But this is done "honestly":
the messages are really transiting by the server
- what you could observe if you have access to its admin console -
and both sending and receiving tasks are implemented the same way a normal application will do:
background threads are sending and receiving events and notifying the User Interface when necessary.
The other tabs (Work Queue, Pub/sub, Routing and Topics) demonstrate each one
a "classic" pattern of event distribution and reception.

The Work Queue is the pattern to be used if you want to distribute tasks equally between several workers.
The code calls:
[senderChannel publishMessage:msg usingRoutingKey:@"demo.workQueue" withProperties:nil] ;
					
several times and the work queue is watched by
/* there is one work queue receiver connection per UITextView */
wqReceiverConnections[i] = [[AMQPConnection alloc] init] ;
[wqReceiverConnections[i] connectToHost:self.fHostname onPort:self.fPort] ;
[wqReceiverConnections[i] loginAsUser:self.fUsername withPassword:self.fPassword onVHost:self.fVHost] ;
					
wqReceiverChannels[i] = [wqReceiverConnections[i] openChannel]  ;

AMQPQueue *queue = [[[AMQPQueue alloc] initWithName:WORK_QUEUE_NAME 
				onChannel:wqReceiverChannels[i] 
				isPassive:NO 
				isExclusive:NO 
				isDurable:NO 
				getsAutoDeleted:YES] autorelease] ;
[queue bindToAMQDirectWithKey:WORK_QUEUE_NAME] ;
					
AMQPConsumer *consumer = [[[AMQPConsumer alloc] initForQueue:queue 
	onChannel:wqReceiverChannels[i] 
	useAcknowledgements:NO 
	isExclusive:NO 
	receiveLocalMessages:YES] autorelease] ;
wqThreads[i] = [[AMQPConsumerThread alloc] initWithConsumer:consumer andDelegate:self] ;

The Publish/Subscribe Queue is the pattern to be used to distribute messages to several subscribers (like a magazine).
The code calls:
[senderPublishSubscribeExchange publishMessage:msg  usingRoutingKey:@"" withProperties:nil] ;
					
several times and the work queue is watched by
/* there is one psReceiverConnections per UITextView */
psReceiverConnections[i] = [[AMQPConnection alloc] init] ;
[psReceiverConnections[i] 
	connectToHost:self.fHostname 
	onPort:self.fPort] ;
[psReceiverConnections[i] 
	loginAsUser:self.fUsername 
	withPassword:self.fPassword 
	onVHost:self.fVHost] ;
					
psReceiverChannels[i] = [psReceiverConnections[i] openChannel]  ;
publishSubscribeExchange[i] = [[AMQPExchange alloc] 
		initFanoutExchangeWithName:@"demo.publishSubscribeExchange" 
		onChannel:psReceiverChannels[i] 
		isPassive:NO 
		isDurable:NO] ;
					
AMQPQueue *queue = [[[AMQPQueue alloc] 
	initExclusiveAnonymousOnChannel:psReceiverChannels[i]] autorelease] ;
[queue bindToExchange:publishSubscribeExchange[i]] ;
					
AMQPConsumer *consumer = [[[AMQPConsumer alloc] initForQueue:queue 
	onChannel:psReceiverChannels[i] 
	useAcknowledgements:NO 
	isExclusive:YES 
	receiveLocalMessages:YES] autorelease] ;
psThreads[i] = [[AMQPConsumerThread alloc] 
	initWithConsumer:consumer andDelegate:self] ;
				

The Routing Queue is the pattern to be used to distribute messages with key filtering by the client.
The code calls:
[senderRoutingExchange publishMessage:msg usingRoutingKey:@"warning" withProperties:nil] ;
[senderRoutingExchange publishMessage:msg usingRoutingKey:@"error" withProperties:nil] ;
					
several times and the work queue is watched by
/* there is one rtReceiverConnections per UITextView */
rtReceiverConnections[i] = [[AMQPConnection alloc] init] ;
[rtReceiverConnections[i] 
	connectToHost:self.fHostname 
	onPort:self.fPort] ;
[rtReceiverConnections[i] 
	loginAsUser:self.fUsername 
	withPassword:self.fPassword 
	onVHost:self.fVHost] ;
					
rtReceiverChannels[i] = [rtReceiverConnections[i] openChannel]  ;
routingExchange[i] = [[AMQPExchange alloc] 
	initDirectExchangeWithName:@"demo.routingExchange" 
	onChannel:rtReceiverChannels[i] 
	isPassive:NO 
	isDurable:NO] ;
					
AMQPQueue *queue = [[[AMQPQueue alloc] 
	initExclusiveAnonymousOnChannel:rtReceiverChannels[i]] autorelease] ;
if ((i == 0) || (i == 2))
	[queue bindToExchange:routingExchange[i] withKey:@"warning"] ;
if ((i == 1) || (i == 2))
	[queue bindToExchange:routingExchange[i] withKey:@"error"] ;
					
AMQPConsumer *consumer = [[[AMQPConsumer alloc] 
	initForQueue:queue 
	onChannel:rtReceiverChannels[i] 
	useAcknowledgements:NO 
	isExclusive:NO 
	receiveLocalMessages:YES] autorelease] ;
rtThreads[i] = [[AMQPConsumerThread alloc] 
	initWithConsumer:consumer andDelegate:self] ;
					
/* this one is just to help debugging by identifying each thread... */
[rtThreads[i] setName:[NSString stringWithFormat:@"%d",i]] ;
[rtThreads[i] start] ;

The Topics Queue is the pattern to be used to distribute messages with pattern filtering by the client.
The code calls:
[senderTopicExchange publishMessage:msg 
	usingRoutingKey:@"kern.warning" withProperties:nil] ;
[senderTopicExchange publishMessage:msg 
	usingRoutingKey:@"kern.error" withProperties:nil] ;
[senderTopicExchange publishMessage:msg 
	usingRoutingKey:@"kern.error.detail" withProperties:nil] ;
[senderTopicExchange publishMessage:msg 
	usingRoutingKey:@"system.warning" withProperties:nil] ;
[senderTopicExchange publishMessage:msg 
	usingRoutingKey:@"system.error" withProperties:nil] ;
				
several times and the work queue is watched by
/* there is one tpReceiverConnections per UITextView */
tpReceiverConnections[i] = [[AMQPConnection alloc] init] ;
[tpReceiverConnections[i] 
	connectToHost:self.fHostname 
	onPort:self.fPort] ;
[tpReceiverConnections[i] 
	loginAsUser:self.fUsername 
	withPassword:self.fPassword 
	onVHost:self.fVHost] ;
					
tpReceiverChannels[i] = [tpReceiverConnections[i] openChannel]  ;
topicExchange[i] = [[AMQPExchange alloc] 
	initTopicExchangeWithName:@"demo.topicExchange" 
	onChannel:tpReceiverChannels[i] 
	isPassive:NO 
	isDurable:NO] ;
					
AMQPQueue *queue = [[[AMQPQueue alloc] 
	initExclusiveAnonymousOnChannel:tpReceiverChannels[i]] autorelease] ;
/* 
	for the demo to actually show something interesting 
	we need a different filter for each listener attached to each 
	UITextView 
*/
if (i == 0)
	[queue bindToExchange:topicExchange[i] withKey:@"kern.*"] ;
if (i == 1)
	[queue bindToExchange:topicExchange[i] withKey:@"*.error"] ;
if (i == 2)
	[queue bindToExchange:topicExchange[i] withKey:@"#"] ;
					
AMQPConsumer *consumer = [[[AMQPConsumer alloc] 
	initForQueue:queue 
	onChannel:tpReceiverChannels[i] 
	useAcknowledgements:YES 
	isExclusive:NO 
	receiveLocalMessages:YES] autorelease] ;
tpThreads[i] = [[AMQPConsumerThread alloc] 
	initWithConsumer:consumer andDelegate:self] ;
					
/* this one is just to help debugging by identifying each thread... */
[tpThreads[i] setName:[NSString stringWithFormat:@"%d",i]] ;
[tpThreads[i] start] ;