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