rabbitmq-jruby-client 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Jerry Luk <jerryluk@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,55 @@
1
+ RabbitMQ JRuby Client
2
+ =====================
3
+ rabbitmq-jruby-client allows you to use RabbitMQ Client from JRuby using the official Java RabbitMQ client from Rabbit Technologies
4
+ See more at http://www.rabbitmq.com
5
+
6
+ Getting Started
7
+ ===============
8
+ 1. Make sure you can install RubyGem from GitHub (you only have to do this once): jruby -S gem sources -a http://gems.github.com
9
+ 2. Install and start RabbitMQ (see below)
10
+ 3. Install JRuby RabbitMQ Client: jruby -S gem install jerryluk-rabbitmq-jruby-client
11
+
12
+ Example Usage
13
+ =============
14
+ gem 'jerryluk-rabbitmq-jruby-client'
15
+ require 'rabbitmq_client'
16
+
17
+ # Initializes the new client and connect to the server
18
+ client = RabbitMQClient.new
19
+
20
+ # Initializes a new queue
21
+ queue = client.queue('queue_name')
22
+
23
+ # Initializes a new exchange
24
+ exchange = client.exchange('exchange_name')
25
+
26
+ # Connects queue with the exchange
27
+ queue.bind(exchange)
28
+
29
+ # Publish a message to the queue
30
+ queue.publish('message body')
31
+
32
+ # Retrieve a message from the queue
33
+ message = queue.retrieve
34
+
35
+ # Subscribe to a queue with callback. The callback will be run in a new thread for each new message.
36
+ queue.subscribe do |message|
37
+ # do something with message
38
+ end
39
+
40
+ # Subscribe to a queue in a loop. No new thread will be created.
41
+ queue.loop_subscribe do |message|
42
+ # do something with message
43
+ end
44
+
45
+
46
+ Installing RabbitMQ on OS X
47
+ ===========================
48
+ 1. Install MacPorts
49
+ 2. sudo port install erlang
50
+ 3. wget http://www.rabbitmq.com/releases/rabbitmq-server/v1.5.3/rabbitmq-server-generic-unix-1.5.3.tar.gz
51
+ 4. tar zxvf rabbitmq-server-1.5.3.tar.gz
52
+ 5. sudo mv rabbitmq_server-1.5.3 /opt/local/lib/erlang/lib
53
+
54
+ To run RabbitMQ
55
+ 6. sudo /opt/local/lib/erlang/lib/rabbitmq_server-1.5.3/sbin/rabbitmq-server
Binary file
Binary file
data/lib/junit.jar ADDED
Binary file
Binary file
@@ -0,0 +1,189 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/junit.jar'
3
+ require File.dirname(__FILE__) + '/commons-cli-1.1.jar'
4
+ require File.dirname(__FILE__) + '/commons-io-1.2.jar'
5
+ require File.dirname(__FILE__) + '/rabbitmq-client.jar'
6
+
7
+ class RabbitMQClient
8
+ include ObjectSpace
9
+ include_class('com.rabbitmq.client.Connection')
10
+ include_class('com.rabbitmq.client.ConnectionParameters')
11
+ include_class('com.rabbitmq.client.ConnectionFactory')
12
+ include_class('com.rabbitmq.client.Channel')
13
+ include_class('com.rabbitmq.client.Consumer')
14
+ include_class('com.rabbitmq.client.DefaultConsumer')
15
+ include_class('com.rabbitmq.client.QueueingConsumer')
16
+ include_class('com.rabbitmq.client.MessageProperties')
17
+ include_class('java.lang.InterruptedException')
18
+ include_class('java.lang.String') { |package, name| "J#{name}" }
19
+
20
+ class RabbitMQClientError < StandardError;end
21
+
22
+ class QueueConsumer < DefaultConsumer
23
+ def initialize(channel, block)
24
+ @channel = channel
25
+ @block = block
26
+ super(channel)
27
+ end
28
+
29
+ def handleDelivery(consumer_tag, envelope, properties, body)
30
+ delivery_tag = envelope.get_delivery_tag
31
+ message_body = Marshal.load(String.from_java_bytes(body))
32
+ # TODO: Do we need to do something with properties?
33
+ @block.call message_body
34
+ @channel.basic_ack(delivery_tag, false)
35
+ end
36
+ end
37
+
38
+ class Queue
39
+ def initialize(name, channel, durable=false)
40
+ @name = name
41
+ @durable = durable
42
+ @channel = channel
43
+ @channel.queue_declare(name, durable)
44
+ self
45
+ end
46
+
47
+ def bind(exchange, routing_key='')
48
+ @routing_key = routing_key
49
+ @exchange = exchange
50
+ raise RabbitMQClientError, "queue and exchange has different durable property" unless @durable == exchange.durable
51
+ @channel.queue_bind(@name, @exchange.name, @routing_key)
52
+ self
53
+ end
54
+
55
+ # Set props for different type of message. Currently they are:
56
+ # RabbitMQClient::MessageProperties::MINIMAL_BASIC
57
+ # RabbitMQClient::MessageProperties::MINIMAL_PERSISTENT_BASIC
58
+ # RabbitMQClient::MessageProperties::BASIC
59
+ # RabbitMQClient::MessageProperties::PERSISTENT_BASIC
60
+ # RabbitMQClient::MessageProperties::TEXT_PLAIN
61
+ # RabbitMQClient::MessageProperties::PERSISTENT_TEXT_PLAIN
62
+ def publish(message_body, props=nil)
63
+ auto_bind
64
+ message_body_byte = Marshal.dump(message_body).to_java_bytes
65
+ @channel.basic_publish(@exchange.name, @routing_key, props, message_body_byte)
66
+ message_body
67
+ end
68
+
69
+ def persistent_publish(message_body, props=MessageProperties::PERSISTENT_TEXT_PLAIN)
70
+ raise RabbitMQClientError, "can only publish persistent message to durable queue" unless @durable
71
+ publish(message_body, props)
72
+ end
73
+
74
+ def retrieve
75
+ auto_bind
76
+ message_body = nil
77
+ no_ack = false
78
+ response = @channel.basic_get(@name, no_ack)
79
+ if response
80
+ props = response.get_props
81
+ message_body = Marshal.load(String.from_java_bytes(response.get_body))
82
+ delivery_tag = response.get_envelope.get_delivery_tag
83
+ @channel.basic_ack(delivery_tag, false)
84
+ end
85
+ message_body
86
+ end
87
+
88
+ def subscribe(&block)
89
+ no_ack = false
90
+ @channel.basic_consume(@name, no_ack, QueueConsumer.new(@channel, block))
91
+ end
92
+
93
+ def loop_subscribe(&block)
94
+ no_ack = false
95
+ consumer = QueueingConsumer.new(@channel)
96
+ @channel.basic_consume(@name, no_ack, consumer)
97
+ loop do
98
+ begin
99
+ delivery = consumer.next_delivery
100
+ message_body = Marshal.load(String.from_java_bytes(delivery.get_body))
101
+ block.call message_body
102
+ @channel.basic_ack(delivery.get_envelope.get_delivery_tag, false)
103
+ rescue InterruptedException => ie
104
+ next
105
+ end
106
+ end
107
+ end
108
+
109
+ protected
110
+ def auto_bind
111
+ unless @exchange
112
+ exchange = Exchange.new("#{@name}_exchange", 'fanout', @channel, @durable)
113
+ self.bind(exchange)
114
+ end
115
+ end
116
+ end
117
+
118
+ class Exchange
119
+ attr_reader :name
120
+ attr_reader :durable
121
+
122
+ def initialize(name, type, channel, durable=false)
123
+ @name = name
124
+ @type = type
125
+ @durable = durable
126
+ @channel = channel
127
+ @channel.exchange_declare(@name, type.to_s, durable)
128
+ self
129
+ end
130
+ end
131
+
132
+ # Class Methods
133
+ class << self
134
+ end
135
+
136
+ attr_reader :channel
137
+ attr_reader :connection
138
+
139
+ # Instance Methods
140
+ def initialize(options={})
141
+ # server address
142
+ @host = options[:host] || '127.0.0.1'
143
+ @port = options[:port] || 5672
144
+
145
+ # login details
146
+ @username = options[:username] || 'guest'
147
+ @password = options[:password] || 'guest'
148
+ @vhost = options[:vhost] || '/'
149
+
150
+ # queues and exchanges
151
+ @queues = {}
152
+ @exchanges = {}
153
+
154
+ connect unless options[:no_auto_connect]
155
+ # Disconnect before the object is destroyed
156
+ define_finalizer(self, lambda {|id| self.disconnect if self.connected? })
157
+ self
158
+ end
159
+
160
+ def connect
161
+ params = ConnectionParameters.new
162
+ params.set_username(@username)
163
+ params.set_password(@password)
164
+ params.set_virtual_host(@vhost)
165
+ params.set_requested_heartbeat(0)
166
+ conn_factory = ConnectionFactory.new(params)
167
+ @connection = conn_factory.new_connection(@host, @port)
168
+ @channel = @connection.create_channel
169
+ end
170
+
171
+ def disconnect
172
+ @channel.close
173
+ @connection.close
174
+ @connection = nil
175
+ end
176
+
177
+ def connected?
178
+ @connection != nil
179
+ end
180
+
181
+ def queue(name, durable=false)
182
+ @queues[name] ||= Queue.new(name, @channel, durable)
183
+ end
184
+
185
+ def exchange(name, type='fanout', durable=false)
186
+ @exchanges[name] ||= Exchange.new(name, type, @channel, durable)
187
+ end
188
+ end
189
+
@@ -0,0 +1,125 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require File.dirname(__FILE__) + '/../lib/rabbitmq_client'
4
+
5
+ describe RabbitMQClient do
6
+ before(:each) do
7
+ @client = RabbitMQClient.new
8
+ end
9
+
10
+ after(:each) do
11
+ @client.disconnect
12
+ end
13
+
14
+ it "should able to create a connection" do
15
+ @client.connection.should_not be_nil
16
+ end
17
+
18
+ it "should able to create a channel" do
19
+ @client.channel.should_not be_nil
20
+ end
21
+
22
+ it "should be able to create a new exchange" do
23
+ exchange = @client.exchange('test_exchange', 'direct')
24
+ exchange.should_not be_nil
25
+ end
26
+
27
+ describe Queue, "Basic non-persistent queue" do
28
+ before(:each) do
29
+ @queue = @client.queue('test_queue')
30
+ @exchange = @client.exchange('test_exchange', 'direct')
31
+ end
32
+
33
+ it "should able to create a queue" do
34
+ @queue.should_not be_nil
35
+ end
36
+
37
+ it "should able to bind to an exchange" do
38
+ @queue.bind(@exchange).should_not be_nil
39
+ end
40
+
41
+ it "should able to publish and retrieve a message" do
42
+ @queue.bind(@exchange)
43
+ @queue.publish('Hello World')
44
+ @queue.retrieve.should == 'Hello World'
45
+ @queue.publish('人大')
46
+ @queue.retrieve.should == '人大'
47
+ end
48
+
49
+ it "should able to subscribe with a callback function" do
50
+ a = 0
51
+ @queue.bind(@exchange)
52
+ @queue.subscribe do |v|
53
+ a += v.to_i
54
+ end
55
+ @queue.publish("1")
56
+ @queue.publish("2")
57
+ sleep 1
58
+ a.should == 3
59
+ end
60
+
61
+ it "should able to subscribe to a queue using loop_subscribe" do
62
+ a = 0
63
+ @queue.bind(@exchange)
64
+ Thread.new do
65
+ begin
66
+ timeout(1) do
67
+ @queue.loop_subscribe do |v|
68
+ a += v.to_i
69
+ end
70
+ end
71
+ rescue Timeout::Error => e
72
+ end
73
+ end
74
+ @queue.publish("1")
75
+ @queue.publish("2")
76
+ sleep 2
77
+ a.should == 3
78
+ end
79
+
80
+ it "should raise an exception if binding a persistent queue with non-persistent exchange and vice versa" do
81
+ persistent_queue = @client.queue('test_queue1', true)
82
+ persistent_exchange = @client.exchange('test_exchange1', 'fanout', true)
83
+ lambda { persistent_queue.bind(@exchange) }.should raise_error(RabbitMQClient::RabbitMQClientError)
84
+ lambda { @queue.bind(persistent_exchange) }.should raise_error(RabbitMQClient::RabbitMQClientError)
85
+ end
86
+
87
+ it "should raise an exception if publish a persistent message on non-duration queue" do
88
+ @queue.bind(@exchange)
89
+ lambda { @queue.persistent_publish('Hello') }.should raise_error(RabbitMQClient::RabbitMQClientError)
90
+ end
91
+ end
92
+
93
+ describe Queue, "Basic persistent queue" do
94
+ before(:each) do
95
+ @queue = @client.queue('test_durable_queue', true)
96
+ @exchange = @client.exchange('test_durable_exchange', 'fanout', true)
97
+ end
98
+
99
+ it "should able to create a queue" do
100
+ @queue.should_not be_nil
101
+ end
102
+
103
+ it "should able to bind to an exchange" do
104
+ @queue.bind(@exchange).should_not be_nil
105
+ end
106
+
107
+ it "should able to publish and retrieve a message" do
108
+ @queue.bind(@exchange)
109
+ @queue.persistent_publish('Hello World')
110
+ @queue.retrieve.should == 'Hello World'
111
+ end
112
+
113
+ it "should able to subscribe with a callback function" do
114
+ a = 0
115
+ @queue.bind(@exchange)
116
+ @queue.subscribe do |v|
117
+ a += v.to_i
118
+ end
119
+ @queue.persistent_publish("1")
120
+ @queue.persistent_publish("2")
121
+ sleep 1
122
+ a.should == 3
123
+ end
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbitmq-jruby-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ platform: ruby
6
+ authors:
7
+ - Jerry Luk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-09 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A RabbitMQ client for JRuby
17
+ email: jerryluk@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - MIT-LICENSE
27
+ - lib/commons-cli-1.1.jar
28
+ - lib/commons-io-1.2.jar
29
+ - lib/rabbitmq-client.jar
30
+ - lib/junit.jar
31
+ - lib/rabbitmq_client.rb
32
+ - spec/rabbitmq_client_spec.rb
33
+ has_rdoc: true
34
+ homepage: http://www.linkedin.com/in/jerryluk
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: A RabbitMQ client for JRuby
61
+ test_files:
62
+ - spec/rabbitmq_client_spec.rb