6

I am trying to make a messaging application using, RabbitMQ for iOS. and i am using this wrapper classes for objective c, with RabbitMQ-C client libraries.

https://github.com/profmaad/librabbitmq-objc

Exchange, Queue & Queue Binding all are ok but my code is not publishing message to RabbitMQ server. Please help me , what is the problem?

this is my code:

    NSError *error= nil;

    AMQPConnection *connection = [[AMQPConnection alloc] init];

    [connection connectToHost:@"SERVER_NAME" onPort:PORT error:&error];

    if (error != nil){
        NSLog(@"Error connection: %@", error);
        return;
    }

    [connection loginAsUser:@"USER_NAME" withPasswort:@"PASSWORD" onVHost:@"/" error:&error];

    if (error != nil){
        NSLog(@"Error logined: %@", error);
        return;
    }

    AMQPChannel *channel = [connection openChannel];


   AMQPExchange *exchange = [[AMQPExchange alloc] initFanoutExchangeWithName:@"EXCHANGE_NAME" onChannel:channel isPassive:NO isDurable:NO getsAutoDeleted:NO error:&error];

    if (error != nil){
        NSLog(@"Error declareExchange: %@", error);
        return;
    }



    //AMQPQueue *queue = [[AMQPQueue alloc] initWithName:@"NAME" onChannel:channel isPassive:NO isExclusive:NO isDurable:YES getsAutoDeleted:YES error:&error];
     AMQPQueue *queue = [[AMQPQueue alloc] initWithName:@"NAME" onChannel:[connection openChannel]];
    if (error != nil){
        NSLog(@"Error declare Queue: %@", error);
        return;
    }



    NSError *error ;
    [queue bindToExchange:exchange withKey:@"KEY" error:&error];

    amqp_basic_properties_t props;
    props._flags= AMQP_BASIC_CLASS;
    props.type = amqp_cstring_bytes([@"typeOfMessage" UTF8String]);
    props.priority = 1;
    [exchange publishMessage:@"Test message" usingRoutingKey:@"ROUTING_KEY" propertiesMessage:props mandatory:NO immediate:NO error:&error];
    if (error != nil){
        NSLog(@"Error declareExchange: %@", error);
        return;
    }
Jlia
  • 59
  • 1
  • 8
  • Did you declared exchange as expected? Did you declared queue as expected? Did bind queue to exchange as expected? Do you publish message to appropriate exchange? Can your message be routed to expected queue? Do you have some consumers that stole your message? Are there any exceptions thrown from application? Are there any suspicious output in RabbitMQ log? - These questions often save my time and neurons to find the reason why some magic happens. – pinepain Jul 17 '14 at 06:43
  • Thanks zaq178miami, i am using EXCHANGE NAME = "fanout" , BINDING KEY = "hello", ROUTING KEY = "hello" and QUEUE = "11111" i have also tried this project: https://github.com/leisurehuang/RabbitMQ-IOS-lib Same problem. It is making everything on RabbitMQ server but not publishing any message to the queue. And i have no consumer thread running, no exception on xcode. i am confused it is a server problem or there is something i am missing? – Jlia Jul 17 '14 at 07:00
  • Those question are for you to help debug the reason. Anyway, try to publish to default exchange (with empty name) with routing key equals to queue name, it's a quick and dirty way to put message to exact queue you want. – pinepain Jul 17 '14 at 07:10
  • zaq178miami , i am now using the same way what you have suggested. And getting some exceptions in Xcode. Please suggest me what i should do now? i am new in RabbitMQ. Exceptions: AMQPException: Failed to bind queue to exchange: ACCESS_REFUSED - operation not permitted on the default exchange AMQPException: Failed to publish message: ACCESS_REFUSED - operation not permitted on the default exchange Error declareExchange: Error Domain=AMQPExchange Code=-10 "Failed to publish message:" UserInfo=0x8f41250 {NSLocalizedDescription=Failed to publish message:} – Jlia Jul 17 '14 at 07:43
  • To publish to the default exchange you don't need to perform the binding. Deleting the `queue bindToExchange` line should help – old_sound Jul 17 '14 at 15:18
  • 1
    I have solved it. Actually there was a problem with `amqp_basic_properties_t props;` Then i tried with `amqp_basic_properties_t props; props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG; props.content_type = amqp_cstring_bytes("text/plain"); props.delivery_mode = 2; props.priority = 1;` **it is working now.** @zaq178miami and @old_sound Thanks for helping me. – Jlia Jul 21 '14 at 06:33

1 Answers1

5

I searched allot as I am too implementing this type of app, at many places I found library that have many types of errors while implementing with iPhone application. I know you have solved your problem but this answer is for those who are still suffering. I combined libs of rabbitmq-c and obejective-c wrapper , erase issues and store it at my own place. You can have rabbitmq-lib for Objective-C development given link.

https://dl.dropboxusercontent.com/u/75870052/AMQPLib.zip

Include this library, import files as given below:-

#import "AMQPExchange.h"
#import "AMQPConsumer.h"
#import "AMQPConnection.h"
#import "AMQPConsumerThread.h"
#import "AMQPChannel.h"
#import "AMQPQueue.h"
#import "AMQPMessage.h"

Define your credentials, I have used default.

#define host @"localhost"
#define routingQueue @"CreateQueue"
#define port 5672
#define user @"guest"
#define pass @"guest"

For publishing message on server use following method.

- (IBAction)send:(id)sender {

    NSError *error= nil;
    NSError *error2 = nil;
    NSError *error3 = nil;
    NSError *error4 = nil;

    AMQPConnection *connection = [[AMQPConnection alloc] init];
    [connection connectToHost:host onPort:port error:&error];

    if (error != nil){
        NSLog(@"Error connection: %@", error);
        return;
    }

    [connection loginAsUser:user withPasswort:pass onVHost:@"/" error:&error];

    if (error != nil){
        NSLog(@"Error logined: %@", error);
        return;
    }


    AMQPChannel *channel = [connection openChannelError:&error2];

    AMQPExchange *exchange = [[AMQPExchange alloc] initDirectExchangeWithName:@"AMQP" onChannel:channel isPassive:NO isDurable:NO getsAutoDeleted:NO error:&error];


    if (error != nil){
        NSLog(@"Error declareExchange: %@", error);
        return;
    }


    AMQPQueue *queue = [[AMQPQueue alloc] initWithName:routingQueue onChannel:channel error:&error3];
    if (error != nil){
        NSLog(@"Error declare Queue: %@", error);
        return;
    }


    BOOL success = [queue bindToExchange:exchange withKey:routingQueue error:&error4];

    if (success) {
        amqp_basic_properties_t props;
        props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
        props.content_type = amqp_cstring_bytes("text/plain");
        props.delivery_mode = 2;
        props.priority = 1;

        //Here put your message to publish...

        [exchange publishMessage:@"YOUR MESSAGE" usingRoutingKey:routingQueue propertiesMessage:props mandatory:NO immediate:NO error:&error];

        if (error != nil){
            NSLog(@"Error declareExchange: %@", error);
            return;
        }
    }
}

For receiving message, you need delegate.

-(IBAction)receiveMessage:(id)sender
{
    NSError *error= nil;
    NSError *error2 = nil;
    NSError *error3 = nil;
    NSError *error4 = nil;

    AMQPConnection *connection = [[AMQPConnection alloc] init];
    [connection connectToHost:host onPort:port error:&error];
    [connection loginAsUser:user withPasswort:pass onVHost:@"/" error:&error];

    AMQPChannel *channel = [connection openChannelError:&error2];
    AMQPQueue *queue = [[AMQPQueue alloc] initWithName:routingQueue onChannel:channel isPassive:NO isExclusive:NO isDurable:NO getsAutoDeleted:NO error:&error3];

    AMQPConsumer *consumer = [[AMQPConsumer alloc] initForQueue:queue onChannel:&channel useAcknowledgements:YES isExclusive:NO receiveLocalMessages:NO error:&error4 deepLoop:1];

    AMQPConsumerThread *consumerThread = [[AMQPConsumerThread alloc] initWithConsumer:consumer delegate:self nameThread:@"myThread" persistentListen:NO];

    consumerThread.delegate=self;

    [consumerThread start];
}


-(void)amqpConsumerThreadReceivedNewMessage:(AMQPMessage *)theMessage
{
    NSLog(@"message = %@", theMessage.body);
}
Prince Kumar Sharma
  • 12,591
  • 4
  • 59
  • 90
  • is this port number specific ?? – nr5 Dec 30 '14 at 11:12
  • how to add this library in Swift ?? I am tried adding it using the Bridging-Header.h file. it giving a lot of error. ex '/Users/Adonta/moojic_workspace/moojicapp2/moojicapp2/amqp.h:243:49: error: unknown type name 'size_t' extern void *amqp_pool_alloc(amqp_pool_t *pool, size_t amount);' – jeevs Jul 02 '15 at 12:06
  • I am also struck in the above question. I have all library file,, still I am receiving,,, file not found @jeevs – McDonal_11 Jul 06 '16 at 04:28
  • @McDonal_11 No i was not able to find a solution. I switched to a different library. – jeevs Jul 07 '16 at 15:34
  • http://stackoverflow.com/questions/38259528/ios-unable-to-establish-rabbitmq-connection-from-swift @jeevs . Kindly guide me on this. – McDonal_11 Jul 08 '16 at 05:39
  • @Nil kindly guide me on the above comment – McDonal_11 Jul 08 '16 at 05:40
  • the dropbox link is not working. can you Please share the link again – Nilesh Jha Feb 11 '20 at 08:25