jruby-hornetq 0.2.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.md +5 -0
- data/LICENSE.txt +201 -0
- data/README.md +249 -0
- data/Rakefile +23 -0
- data/bin/hornetq_server +70 -0
- data/examples/backup_server.yml +4 -0
- data/examples/batch_client.rb +124 -0
- data/examples/client.rb +49 -0
- data/examples/consumer.rb +35 -0
- data/examples/hornetq.yml +36 -0
- data/examples/live_server.yml +5 -0
- data/examples/multi_client.rb +63 -0
- data/examples/multi_consumer.rb +54 -0
- data/examples/producer.rb +36 -0
- data/examples/run_broker.rb +59 -0
- data/examples/server.rb +42 -0
- data/examples/standalone_server.yml +3 -0
- data/lib/hornetq/client_requestor.rb +30 -0
- data/lib/hornetq/client_server.rb +47 -0
- data/lib/hornetq/hornet_q_client.rb +388 -0
- data/lib/hornetq/lib/hornetq-core-client.jar +0 -0
- data/lib/hornetq/lib/hornetq-core.jar +0 -0
- data/lib/hornetq/lib/netty.jar +0 -0
- data/lib/hornetq/org_hornetq_api_core_client_client_session.rb +16 -0
- data/lib/hornetq/org_hornetq_core_client_impl_client_message_impl.rb +166 -0
- data/lib/hornetq/org_hornetq_core_client_impl_client_producer_impl.rb +5 -0
- data/lib/hornetq/org_hornetq_utils_typed_properties.rb +60 -0
- data/lib/hornetq/session_pool.rb +175 -0
- data/lib/hornetq.rb +9 -0
- metadata +106 -0
data/examples/client.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Requestor:
|
3
|
+
# Submit a request and wait for a reply
|
4
|
+
#
|
5
|
+
|
6
|
+
# Allow examples to be run in-place without requiring a gem install
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'hornetq'
|
12
|
+
|
13
|
+
count = (ARGV[0] || 1).to_i
|
14
|
+
timeout = (ARGV[1] || 30000).to_i
|
15
|
+
|
16
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
17
|
+
|
18
|
+
# Create a HornetQ session
|
19
|
+
HornetQClient::Factory.create_session(config) do |session|
|
20
|
+
#session.create_queue('Example', 'Example', true)
|
21
|
+
requestor = session.create_requestor('jms.queue.ExampleQueue')
|
22
|
+
session.start
|
23
|
+
start_time = Time.now
|
24
|
+
|
25
|
+
puts "Sending messages"
|
26
|
+
count.times do |i|
|
27
|
+
message = session.create_message(HornetQClient::Message::TEXT_TYPE,false)
|
28
|
+
# Set the message body text
|
29
|
+
message << "Request Current Time"
|
30
|
+
# Set the user managed message id
|
31
|
+
message.user_id = Java::org.hornetq.utils::UUIDGenerator.getInstance.generateUUID
|
32
|
+
# Send message to the queue
|
33
|
+
puts "Sending Request"
|
34
|
+
if reply = requestor.request(message, timeout)
|
35
|
+
puts "Received Response: #{reply.inspect}"
|
36
|
+
puts " Message:[#{reply.body.inspect}]"
|
37
|
+
#print "."
|
38
|
+
else
|
39
|
+
puts "Time out, No reply received after #{timeout/1000} seconds"
|
40
|
+
end
|
41
|
+
#p message
|
42
|
+
puts "#{i}" if i%1000 == 0
|
43
|
+
puts "Durable" if message.durable
|
44
|
+
end
|
45
|
+
|
46
|
+
requestor.close
|
47
|
+
duration = Time.now - start_time
|
48
|
+
puts "\nMade #{count} calls in #{duration} seconds at #{count/duration} messages per second"
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Consumer:
|
3
|
+
# Write messages to the queue
|
4
|
+
#
|
5
|
+
|
6
|
+
# Allow examples to be run in-place without requiring a gem install
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'hornetq'
|
12
|
+
|
13
|
+
timeout = (ARGV[0] || 1000).to_i
|
14
|
+
|
15
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
16
|
+
|
17
|
+
# Create a HornetQ session
|
18
|
+
HornetQClient::Factory.create_session(config) do |session|
|
19
|
+
consumer = session.create_consumer('jms.queue.ExampleQueue')
|
20
|
+
session.start
|
21
|
+
|
22
|
+
count = 0
|
23
|
+
start_time = Time.now
|
24
|
+
while message = consumer.receive(timeout)
|
25
|
+
count = count + 1
|
26
|
+
message.acknowledge
|
27
|
+
puts "=================================="
|
28
|
+
text = message.body
|
29
|
+
p text
|
30
|
+
p message
|
31
|
+
puts "Durable" if message.durable
|
32
|
+
end
|
33
|
+
duration = Time.now - start_time - timeout/1000
|
34
|
+
puts "Received #{count} messages in #{duration} seconds at #{count/duration} messages per second"
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
development:
|
3
|
+
:connector:
|
4
|
+
:uri: hornetq://localhost,192.168.0.22
|
5
|
+
:failover_on_initial_connection: true
|
6
|
+
:failover_on_server_shutdown: true
|
7
|
+
# 5 Connection attempts takes about 16 seconds before it switches to the backup server
|
8
|
+
:reconnect_attempts: 5
|
9
|
+
:session:
|
10
|
+
:username: guest
|
11
|
+
:password: guest
|
12
|
+
|
13
|
+
# Example configuration showing all possible options and their default values if available
|
14
|
+
full_example:
|
15
|
+
:connector:
|
16
|
+
# The uri is written as follows for the NettyConnectorFactory.
|
17
|
+
# protocol=netty is the default and therefore not required
|
18
|
+
:uri: hornetq://localhost:5445,backupserver:5445/?protocol=netty
|
19
|
+
# Or, the uri is written as follows for the InVM
|
20
|
+
:uri: hornetq://localhost/?protocol=invm
|
21
|
+
# Or, the uri is written as follows for auto-discovery
|
22
|
+
:uri: hornetq://discoveryserver:5445/?protocol=discovery
|
23
|
+
|
24
|
+
# For a static cluster list as an array of URI's
|
25
|
+
:uri:
|
26
|
+
- netty://server1:5445,server1backup:5445
|
27
|
+
- netty://server2:5445,server2backup:5445
|
28
|
+
# URI format:
|
29
|
+
# [netty|invm|discovery]://host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
|
30
|
+
:options:
|
31
|
+
:failover_on_initial_connection: true
|
32
|
+
:failover_on_server_shutdown: true
|
33
|
+
:reconnect_attempts: -1
|
34
|
+
:session:
|
35
|
+
:username: guest
|
36
|
+
:password: guest
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Requestor:
|
3
|
+
# Multithreaded clients all doing requests
|
4
|
+
# Typical scenario is in a Rails app when we need to do a call to a
|
5
|
+
# remote server and block until a response is received
|
6
|
+
#
|
7
|
+
|
8
|
+
# Allow examples to be run in-place without requiring a gem install
|
9
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'yaml'
|
13
|
+
require 'hornetq'
|
14
|
+
|
15
|
+
$thread_count = (ARGV[0] || 1).to_i
|
16
|
+
$timeout = (ARGV[1] || 30000).to_i
|
17
|
+
|
18
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
19
|
+
|
20
|
+
# Sample thread that does some work and then does a request-response call
|
21
|
+
def worker_thread(id, session_pool)
|
22
|
+
begin
|
23
|
+
# Obtain a session from the pool and return when complete
|
24
|
+
session_pool.requestor('jms.queue.ExampleQueue') do |session, requestor|
|
25
|
+
message = session.create_message(HornetQClient::Message::TEXT_TYPE,false)
|
26
|
+
message << "Request Current Time"
|
27
|
+
|
28
|
+
# Send message to the queue
|
29
|
+
puts "Thread[#{id}]: Sending Request"
|
30
|
+
if reply = requestor.request(message, $timeout)
|
31
|
+
puts "Thread[#{id}]: Received Response: #{reply.inspect}"
|
32
|
+
puts "Thread[#{id}]: Message:[#{reply.body.inspect}]"
|
33
|
+
else
|
34
|
+
puts "Thread[#{id}]: Time out, No reply received after #{$timeout/1000} seconds"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue Exception => exc
|
38
|
+
puts "Thread[#{id}]: Terminating due to Exception:#{exc.inspect}"
|
39
|
+
puts exc.backtrace
|
40
|
+
end
|
41
|
+
puts "Thread[#{id}]: Complete"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a HornetQ Factory
|
45
|
+
HornetQClient::Factory.create_factory(config[:connector]) do |factory|
|
46
|
+
|
47
|
+
# Create a pool of session connections, all with the same session parameters
|
48
|
+
# The pool is thread-safe and can be accessed concurrently by multiple threads
|
49
|
+
session_pool = factory.create_session_pool(config[:session])
|
50
|
+
threads = []
|
51
|
+
|
52
|
+
# Do some work and then lets re-use the session in another thread below
|
53
|
+
worker_thread(9999, session_pool)
|
54
|
+
|
55
|
+
$thread_count.times do |i|
|
56
|
+
# Each thread will get a session from the session pool as needed
|
57
|
+
threads << Thread.new { worker_thread(i, session_pool) }
|
58
|
+
end
|
59
|
+
threads.each {|t| t.join}
|
60
|
+
|
61
|
+
# Important. Remember to close any open sessions in the pool
|
62
|
+
session_pool.close
|
63
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Consumer:
|
3
|
+
# Multi-threaded Consumer
|
4
|
+
#
|
5
|
+
|
6
|
+
# Allow examples to be run in-place without requiring a gem install
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'hornetq'
|
12
|
+
|
13
|
+
# Arguments: 'number of threads' 'timeout'
|
14
|
+
$thread_count = (ARGV[0] || 3).to_i
|
15
|
+
$timeout = (ARGV[1] || 1000).to_i
|
16
|
+
|
17
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
18
|
+
|
19
|
+
def worker(id, session)
|
20
|
+
begin
|
21
|
+
consumer = session.create_consumer('jms.queue.ExampleQueue')
|
22
|
+
session.start
|
23
|
+
|
24
|
+
count = 0
|
25
|
+
start_time = Time.now
|
26
|
+
while message = consumer.receive($timeout)
|
27
|
+
count = count + 1
|
28
|
+
message.acknowledge
|
29
|
+
#puts "=================================="
|
30
|
+
#text = message.body
|
31
|
+
#p text
|
32
|
+
#p message
|
33
|
+
puts "Durable" if message.durable
|
34
|
+
print "#{id}."
|
35
|
+
end
|
36
|
+
duration = Time.now - start_time - $timeout/1000
|
37
|
+
puts "\nReceived #{count} messages in #{duration} seconds at #{count/duration} messages per second"
|
38
|
+
rescue Exception => exc
|
39
|
+
puts "Thread #{id} Terminating"
|
40
|
+
p exc
|
41
|
+
ensure
|
42
|
+
session.close
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create a HornetQ session
|
47
|
+
HornetQClient::Factory.create_factory(config[:connector]) do |factory|
|
48
|
+
threads = []
|
49
|
+
$thread_count.times do |i|
|
50
|
+
session = factory.create_session(config[:session])
|
51
|
+
threads << Thread.new { worker(i, session) }
|
52
|
+
end
|
53
|
+
threads.each {|t| t.join}
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Producer:
|
3
|
+
# Write messages to the queue
|
4
|
+
#
|
5
|
+
|
6
|
+
# Allow examples to be run in-place without requiring a gem install
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'hornetq'
|
12
|
+
|
13
|
+
count = (ARGV[0] || 1).to_i
|
14
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
15
|
+
|
16
|
+
# Create a HornetQ session
|
17
|
+
HornetQClient::Factory.create_session(config) do |session|
|
18
|
+
#session.create_queue('Example', 'Example', true)
|
19
|
+
producer = session.create_producer('jms.queue.ExampleQueue')
|
20
|
+
start_time = Time.now
|
21
|
+
|
22
|
+
puts "Sending messages"
|
23
|
+
(1..count).each do |i|
|
24
|
+
message = session.create_message(HornetQClient::Message::TEXT_TYPE,false)
|
25
|
+
# Set the message body text
|
26
|
+
message << "#{Time.now}: ### Hello, World ###"
|
27
|
+
# Send message to the queue
|
28
|
+
producer.send(message)
|
29
|
+
#puts message
|
30
|
+
puts "#{i}\n" if i%1000 == 0
|
31
|
+
puts "Durable" if message.durable
|
32
|
+
end
|
33
|
+
|
34
|
+
duration = Time.now - start_time
|
35
|
+
puts "Delivered #{count} messages in #{duration} seconds at #{count/duration} messages per second"
|
36
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
|
3
|
+
raise 'Environment variable HORNETQ_HOME not set' unless ENV['HORNETQ_HOME']
|
4
|
+
require "#{ENV['HORNETQ_HOME']}/lib/hornetq-core.jar"
|
5
|
+
require "#{ENV['HORNETQ_HOME']}/lib/netty.jar"
|
6
|
+
|
7
|
+
backup_host = ARGV[0]
|
8
|
+
is_backup = backup_host.nil?
|
9
|
+
|
10
|
+
config = Java::org.hornetq.core.config.impl.ConfigurationImpl.new
|
11
|
+
config.persistence_enabled = false
|
12
|
+
config.security_enabled = false
|
13
|
+
config.paging_directory = '../data/paging'
|
14
|
+
config.bindings_directory = '../data/bindings'
|
15
|
+
config.journal_directory = '../data/journal'
|
16
|
+
config.journal_min_files = 10
|
17
|
+
config.large_messages_directory = '../data/large-messages'
|
18
|
+
|
19
|
+
if Java::org.hornetq.core.journal.impl.AIOSequentialFileFactory.isSupported
|
20
|
+
config.journal_type = Java::org.hornetq.core.server.JournalType::ASYNCIO
|
21
|
+
else
|
22
|
+
puts("AIO wasn't located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal");
|
23
|
+
config.journal_type = Java::org.hornetq.core.server.JournalType::NIO
|
24
|
+
end
|
25
|
+
|
26
|
+
netty_acceptor_class_name = Java::org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory.java_class.name
|
27
|
+
netty_connector_class_name = Java::org.hornetq.core.remoting.impl.netty.NettyConnectorFactory.java_class.name
|
28
|
+
|
29
|
+
transport_conf_params = java.util.HashMap.new
|
30
|
+
transport_conf_params.put('host', '0.0.0.0')
|
31
|
+
transport_conf_params.put('port', 5445)
|
32
|
+
transport_conf = Java::org.hornetq.api.core.TransportConfiguration.new(netty_acceptor_class_name, transport_conf_params);
|
33
|
+
|
34
|
+
transport_conf_set = java.util.HashSet.new
|
35
|
+
transport_conf_set.add(transport_conf)
|
36
|
+
|
37
|
+
config.acceptor_configurations = transport_conf_set
|
38
|
+
|
39
|
+
if is_backup
|
40
|
+
puts "backup"
|
41
|
+
config.backup = true
|
42
|
+
config.shared_store = false
|
43
|
+
else
|
44
|
+
puts "live"
|
45
|
+
backup_params = java.util.HashMap.new
|
46
|
+
backup_params.put('host', backup_host)
|
47
|
+
backup_params.put('port', 5445)
|
48
|
+
#backup_params.put('reconnectAttempts', -1)
|
49
|
+
backup_connector_conf = Java::org.hornetq.api.core.TransportConfiguration.new(netty_connector_class_name, backup_params);
|
50
|
+
|
51
|
+
connector_conf_map = java.util.HashMap.new
|
52
|
+
connector_conf_map.put('backup-connector', backup_connector_conf)
|
53
|
+
|
54
|
+
config.connector_configurations = connector_conf_map
|
55
|
+
config.backup_connector_name = 'backup-connector'
|
56
|
+
end
|
57
|
+
|
58
|
+
server = Java::org.hornetq.core.server.HornetQServers.newHornetQServer(config)
|
59
|
+
server.start
|
data/examples/server.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Consumer:
|
3
|
+
# Reply to a request
|
4
|
+
#
|
5
|
+
|
6
|
+
# Allow examples to be run in-place without requiring a gem install
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'hornetq'
|
12
|
+
|
13
|
+
timeout = (ARGV[0] || 60000).to_i
|
14
|
+
|
15
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/hornetq.yml')['development']
|
16
|
+
|
17
|
+
# Create a HornetQ session
|
18
|
+
HornetQClient::Factory.create_session(config) do |session|
|
19
|
+
server = session.create_server('jms.queue.ExampleQueue', timeout)
|
20
|
+
session.start
|
21
|
+
|
22
|
+
count = 0
|
23
|
+
start_time = Time.now
|
24
|
+
server.run do |request_message|
|
25
|
+
count = count + 1
|
26
|
+
#puts "=================================="
|
27
|
+
text = request_message.body
|
28
|
+
#p text
|
29
|
+
#p request_message
|
30
|
+
#print "."
|
31
|
+
puts "#{count}" if count%1000 == 0
|
32
|
+
puts "Durable" if request_message.durable
|
33
|
+
reply_message = session.create_message(HornetQClient::Message::TEXT_TYPE, false)
|
34
|
+
reply_message << "Test Response"
|
35
|
+
reply_message
|
36
|
+
end
|
37
|
+
|
38
|
+
duration = Time.now - start_time - timeout/1000
|
39
|
+
puts "\nReceived #{count} requests in #{duration} seconds at #{count/duration} messages per second"
|
40
|
+
|
41
|
+
server.close
|
42
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module HornetQClient
|
2
|
+
|
3
|
+
# Send a request to a server and wait for a reply
|
4
|
+
class ClientRequestor
|
5
|
+
def initialize(session, request_address)
|
6
|
+
@session = session
|
7
|
+
@producer = session.create_producer(request_address)
|
8
|
+
reply_queue = "#{request_address}.#{Java::java.util::UUID.randomUUID.toString}"
|
9
|
+
begin
|
10
|
+
session.create_temporary_queue(reply_queue, reply_queue)
|
11
|
+
rescue NativeException => exc
|
12
|
+
p exc
|
13
|
+
end
|
14
|
+
@consumer = session.create_consumer(reply_queue)
|
15
|
+
end
|
16
|
+
|
17
|
+
def request(request_message, timeout)
|
18
|
+
request_message.putStringProperty(Java::OrgHornetqCoreClientImpl::ClientMessageImpl::REPLYTO_HEADER_NAME, @consumer.queue_name);
|
19
|
+
@producer.send(request_message)
|
20
|
+
@consumer.receive(timeout)
|
21
|
+
end
|
22
|
+
|
23
|
+
def close
|
24
|
+
@producer.close if @producer
|
25
|
+
@consumer.close if @consumer
|
26
|
+
@session.delete_queue(@consumer.queue_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module HornetQClient
|
2
|
+
# Create a Server for receiving requests and replying
|
3
|
+
# to arbitrary queues
|
4
|
+
# Create an instance of this class per thread
|
5
|
+
class ClientServer
|
6
|
+
def initialize(session, request_queue, timeout)
|
7
|
+
@session = session
|
8
|
+
@consumer = session.create_consumer(request_queue)
|
9
|
+
@producer = session.create_producer
|
10
|
+
@timeout = timeout
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(&block)
|
14
|
+
while request_message = @consumer.receive(@timeout)
|
15
|
+
# Block should return a message reply object, pass in request
|
16
|
+
# TODO: ensure..
|
17
|
+
reply_message = block.call(request_message)
|
18
|
+
|
19
|
+
# Send a reply?
|
20
|
+
reply(request_message, reply_message) if request_message.request?
|
21
|
+
request_message.acknowledge
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Send a reply to the received request message
|
26
|
+
# request: is the message received
|
27
|
+
# reply: is the message to send to the client
|
28
|
+
def reply(request_message, reply_message)
|
29
|
+
if request_message.request?
|
30
|
+
# Reply should have same durability as request
|
31
|
+
reply_message.durable = request_message.durable?
|
32
|
+
reply_to = request_message.getSimpleStringProperty(Java::OrgHornetqCoreClientImpl::ClientMessageImpl::REPLYTO_HEADER_NAME);
|
33
|
+
# Send request message id back in reply message for correlation purposes
|
34
|
+
reply_message.user_id = request_message.user_id
|
35
|
+
@producer.send(reply_to, reply_message)
|
36
|
+
#puts "Sent reply to #{reply_to.to_s}: #{reply_message.inspect}"
|
37
|
+
end
|
38
|
+
request_message.acknowledge
|
39
|
+
end
|
40
|
+
|
41
|
+
# Close out resources
|
42
|
+
def close
|
43
|
+
@consumer.close if @consumer
|
44
|
+
@producer.close if @producer
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|