jruby-hornetq 0.2.0.alpha
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/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
|