jruby-jms 0.10.2 → 0.11.0
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 +15 -0
- data/README.md +27 -28
- data/Rakefile +7 -1
- data/doc/classes/JMS.html +265 -0
- data/doc/classes/JMS/BytesMessage.html +215 -0
- data/doc/classes/JMS/Connection.html +1145 -0
- data/doc/classes/JMS/MapMessage.html +333 -0
- data/doc/classes/JMS/Message.html +1085 -0
- data/doc/classes/JMS/MessageConsumer.html +316 -0
- data/doc/classes/JMS/MessageListenerImpl.html +262 -0
- data/doc/classes/JMS/ObjectMessage.html +170 -0
- data/doc/classes/JMS/OracleAQConnectionFactory.html +184 -0
- data/doc/classes/JMS/QueueBrowser.html +155 -0
- data/doc/classes/JMS/Session.html +947 -0
- data/doc/classes/JMS/SessionPool.html +411 -0
- data/doc/classes/JMS/TextMessage.html +194 -0
- data/doc/created.rid +1 -0
- data/doc/files/README_md.html +440 -0
- data/doc/files/lib/jms/bytes_message_rb.html +122 -0
- data/doc/files/lib/jms/connection_rb.html +140 -0
- data/doc/files/lib/jms/imports_rb.html +108 -0
- data/doc/files/lib/jms/logging_rb.html +129 -0
- data/doc/files/lib/jms/map_message_rb.html +122 -0
- data/doc/files/lib/jms/message_consumer_rb.html +122 -0
- data/doc/files/lib/jms/message_listener_impl_rb.html +122 -0
- data/doc/files/lib/jms/message_rb.html +122 -0
- data/doc/files/lib/jms/object_message_rb.html +122 -0
- data/doc/files/lib/jms/oracle_a_q_connection_factory_rb.html +122 -0
- data/doc/files/lib/jms/queue_browser_rb.html +122 -0
- data/doc/files/lib/jms/session_pool_rb.html +108 -0
- data/doc/files/lib/jms/session_rb.html +164 -0
- data/doc/files/lib/jms/text_message_rb.html +122 -0
- data/doc/files/lib/jms_rb.html +131 -0
- data/doc/fr_class_index.html +39 -0
- data/doc/fr_file_index.html +42 -0
- data/doc/fr_method_index.html +120 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/examples/advanced/session_pool.rb +37 -0
- data/examples/client-server/replier.rb +29 -0
- data/examples/client-server/requestor.rb +40 -0
- data/examples/jms.yml +85 -9
- data/examples/performance/consumer.rb +6 -8
- data/examples/performance/producer.rb +10 -10
- data/examples/producer-consumer/browser.rb +24 -0
- data/examples/{consumer.rb → producer-consumer/consumer.rb} +5 -4
- data/examples/producer-consumer/consumer_async.rb +30 -0
- data/examples/{producer.rb → producer-consumer/producer.rb} +5 -3
- data/examples/publish-subscribe/publish.rb +24 -0
- data/examples/publish-subscribe/subscribe.rb +31 -0
- data/lib/jms/bytes_message.rb +52 -0
- data/lib/jms/connection.rb +170 -162
- data/lib/jms/imports.rb +21 -0
- data/lib/jms/logging.rb +17 -1
- data/lib/jms/{javax_jms_map_message.rb → map_message.rb} +2 -2
- data/lib/jms/message.rb +285 -0
- data/lib/jms/{javax_jms_message_consumer.rb → message_consumer.rb} +6 -3
- data/lib/jms/{message_listener.rb → message_listener_impl.rb} +3 -3
- data/lib/jms/{javax_jms_object_message.rb → object_message.rb} +1 -1
- data/lib/jms/oracle_a_q_connection_factory.rb +35 -0
- data/lib/jms/{javax_jms_queue_browser.rb → queue_browser.rb} +5 -4
- data/lib/jms/{javax_jms_session.rb → session.rb} +23 -25
- data/lib/jms/session_pool.rb +148 -0
- data/lib/jms/{javax_jms_text_message.rb → text_message.rb} +1 -1
- data/test/connection_test.rb +31 -29
- data/test/jms.yml +8 -9
- data/test/message_test.rb +29 -29
- data/test/session_test.rb +39 -39
- metadata +62 -22
- data/lib/jms/javax_jms_message.rb +0 -264
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Sample Consumer:
|
2
|
+
# Sample Consumer:
|
3
3
|
# Retrieve all messages from a queue
|
4
4
|
#
|
5
5
|
|
@@ -10,18 +10,16 @@ require 'rubygems'
|
|
10
10
|
require 'yaml'
|
11
11
|
require 'jms'
|
12
12
|
|
13
|
-
jms_provider = ARGV[
|
13
|
+
jms_provider = ARGV[0] || 'activemq'
|
14
14
|
|
15
15
|
# Load Connection parameters from configuration file
|
16
16
|
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
17
|
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
18
|
|
19
19
|
JMS::Connection.session(config) do |session|
|
20
|
-
session.
|
21
|
-
|
22
|
-
puts "=================================="
|
23
|
-
p message
|
24
|
-
end
|
25
|
-
puts "STATISTICS :" + stats.inspect
|
20
|
+
stats = session.consume(:queue_name => 'ExampleQueue', :statistics => true) do |message|
|
21
|
+
# Do nothing in this example with each message
|
26
22
|
end
|
23
|
+
|
24
|
+
JMS::logger.info "Consumed #{stats[:messages]} messages. Average #{stats[:ms_per_msg]}ms per message"
|
27
25
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Sample Producer:
|
3
|
-
# Write messages to the queue
|
3
|
+
# Write multiple messages to the queue
|
4
4
|
#
|
5
5
|
|
6
6
|
# Allow examples to be run in-place without requiring a gem install
|
@@ -9,23 +9,23 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
|
9
9
|
require 'rubygems'
|
10
10
|
require 'yaml'
|
11
11
|
require 'jms'
|
12
|
-
|
12
|
+
require 'benchmark'
|
13
|
+
|
13
14
|
jms_provider = ARGV[0] || 'activemq'
|
14
|
-
count = (ARGV[1] ||
|
15
|
+
count = (ARGV[1] || 10).to_i
|
15
16
|
|
16
17
|
# Load Connection parameters from configuration file
|
17
18
|
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
18
19
|
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
19
20
|
|
20
21
|
JMS::Connection.session(config) do |session|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
duration = Benchmark.realtime do
|
23
|
+
session.producer(:queue_name => 'ExampleQueue') do |producer|
|
24
|
+
count.times do |i|
|
25
|
+
producer.send(session.message("Hello Producer #{i}"))
|
26
|
+
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
-
puts "Delivered #{count} messages in #{duration} seconds at #{count/duration} messages per second"
|
30
|
+
JMS::logger.info "Produced #{count} messages. Average #{duration*1000/count}ms per message"
|
31
31
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Sample Browsing Consumer:
|
3
|
+
# Browse all messages on a queue without removing them
|
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 'jms'
|
11
|
+
require 'yaml'
|
12
|
+
|
13
|
+
jms_provider = ARGV[0] || 'activemq'
|
14
|
+
|
15
|
+
# Load Connection parameters from configuration file
|
16
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
|
+
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
|
+
|
19
|
+
# Consume all available messages on the queue
|
20
|
+
JMS::Connection.session(config) do |session|
|
21
|
+
session.browse(:queue_name => 'ExampleQueue', :timeout=>1000) do |message|
|
22
|
+
JMS::logger.info message.inspect
|
23
|
+
end
|
24
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
#
|
2
|
-
# Sample Consumer:
|
2
|
+
# Sample Consumer:
|
3
3
|
# Retrieve all messages from a queue
|
4
4
|
#
|
5
5
|
|
6
6
|
# Allow examples to be run in-place without requiring a gem install
|
7
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
8
8
|
|
9
9
|
require 'rubygems'
|
10
10
|
require 'jms'
|
@@ -13,11 +13,12 @@ require 'yaml'
|
|
13
13
|
jms_provider = ARGV[0] || 'activemq'
|
14
14
|
|
15
15
|
# Load Connection parameters from configuration file
|
16
|
-
config = YAML.load_file(File.join(File.dirname(__FILE__), 'jms.yml'))[jms_provider]
|
16
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
17
|
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
18
|
|
19
|
+
# Consume all available messages on the queue
|
19
20
|
JMS::Connection.session(config) do |session|
|
20
21
|
session.consume(:queue_name => 'ExampleQueue', :timeout=>1000) do |message|
|
21
|
-
|
22
|
+
JMS::logger.info message.inspect
|
22
23
|
end
|
23
24
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Sample Asynchronous Consumer:
|
3
|
+
# Retrieve all messages from the queue in a separate thread
|
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 'jms'
|
11
|
+
require 'yaml'
|
12
|
+
|
13
|
+
jms_provider = ARGV[0] || 'activemq'
|
14
|
+
|
15
|
+
# Load Connection parameters from configuration file
|
16
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
|
+
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
|
+
|
19
|
+
# Consume all available messages on the queue
|
20
|
+
JMS::Connection.start(config) do |connection|
|
21
|
+
|
22
|
+
# Define Asynchronous code block to be called every time a message is receive
|
23
|
+
connection.on_message(:queue_name => 'ExampleQueue') do |message|
|
24
|
+
JMS::logger.info message.inspect
|
25
|
+
end
|
26
|
+
|
27
|
+
# Since the on_message handler above is in a separate thread the thread needs
|
28
|
+
# to do some other work. For this example it will just sleep for 10 seconds
|
29
|
+
sleep 10
|
30
|
+
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
# Allow examples to be run in-place without requiring a gem install
|
7
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '
|
7
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
8
8
|
|
9
9
|
require 'rubygems'
|
10
10
|
require 'yaml'
|
@@ -13,11 +13,13 @@ require 'jms'
|
|
13
13
|
jms_provider = ARGV[0] || 'activemq'
|
14
14
|
|
15
15
|
# Load Connection parameters from configuration file
|
16
|
-
config = YAML.load_file(File.join(File.dirname(__FILE__), 'jms.yml'))[jms_provider]
|
16
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
17
|
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
18
|
|
19
19
|
JMS::Connection.session(config) do |session|
|
20
20
|
session.producer(:queue_name => 'ExampleQueue') do |producer|
|
21
|
-
producer.
|
21
|
+
producer.delivery_mode = JMS::DeliveryMode::NON_PERSISTENT
|
22
|
+
producer.send(session.message("Hello World: #{Time.now}"))
|
23
|
+
JMS::logger.info "Successfully sent one message to queue ExampleQueue"
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Sample Publisher:
|
3
|
+
# Write messages to a topic
|
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 'jms'
|
12
|
+
|
13
|
+
jms_provider = ARGV[0] || 'activemq'
|
14
|
+
|
15
|
+
# Load Connection parameters from configuration file
|
16
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
17
|
+
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
18
|
+
|
19
|
+
JMS::Connection.session(config) do |session|
|
20
|
+
session.producer(:topic_name => 'SampleTopic') do |producer|
|
21
|
+
producer.send(session.message("Hello World: #{Time.now}"))
|
22
|
+
JMS::logger.info "Successfully published one message to topic SampleTopic"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Sample Topic Subscriber:
|
3
|
+
# Retrieve all messages from a topic using a non-durable subscription
|
4
|
+
#
|
5
|
+
# Try starting multiple copies of this Consumer. All active instances should
|
6
|
+
# receive the same messages
|
7
|
+
#
|
8
|
+
# Since the topic subscription is non-durable, it will only receive new messages.
|
9
|
+
# Any messages sent prior to the instance starting will not be received.
|
10
|
+
# Also, any messages sent after the instance has stopped will not be received
|
11
|
+
# when the instance is re-started, only new messages sent after it started will
|
12
|
+
# be received.
|
13
|
+
|
14
|
+
# Allow examples to be run in-place without requiring a gem install
|
15
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
16
|
+
|
17
|
+
require 'rubygems'
|
18
|
+
require 'jms'
|
19
|
+
require 'yaml'
|
20
|
+
|
21
|
+
jms_provider = ARGV[0] || 'activemq'
|
22
|
+
|
23
|
+
# Load Connection parameters from configuration file
|
24
|
+
config = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'jms.yml'))[jms_provider]
|
25
|
+
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
26
|
+
|
27
|
+
JMS::Connection.session(config) do |session|
|
28
|
+
session.consume(:topic_name => 'SampleTopic', :timeout=>30000) do |message|
|
29
|
+
JMS::logger.info message.inspect
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright 2008, 2009, 2010, 2011 J. Reid Morrison
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
################################################################################
|
16
|
+
|
17
|
+
#Interface javax.jms.BytesMessage
|
18
|
+
module JMS::BytesMessage
|
19
|
+
def data
|
20
|
+
# Puts the message body in read-only mode and repositions the stream of
|
21
|
+
# bytes to the beginning
|
22
|
+
self.reset
|
23
|
+
|
24
|
+
available = self.body_length
|
25
|
+
|
26
|
+
return nil if available == 0
|
27
|
+
|
28
|
+
result = ""
|
29
|
+
bytes_size = 1024
|
30
|
+
bytes = Java::byte[bytes_size].new
|
31
|
+
|
32
|
+
while (n = available < bytes_size ? available : bytes_size) > 0
|
33
|
+
self.read_bytes(bytes, n)
|
34
|
+
if n == bytes_size
|
35
|
+
result << String.from_java_bytes(bytes)
|
36
|
+
else
|
37
|
+
result << String.from_java_bytes(bytes)[0..n-1]
|
38
|
+
end
|
39
|
+
available -= n
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def data=(val)
|
45
|
+
self.write_bytes(val.respond_to?(:to_java_bytes) ? val.to_java_bytes : val)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
data
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/jms/connection.rb
CHANGED
@@ -32,15 +32,15 @@ module JMS
|
|
32
32
|
# require 'jms'
|
33
33
|
#
|
34
34
|
# JMS::Connection.create_session(
|
35
|
-
# :
|
36
|
-
# :
|
37
|
-
# :
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
35
|
+
# :factory => 'org.apache.activemq.ActiveMQConnectionFactory',
|
36
|
+
# :broker_url => 'tcp://localhost:61616',
|
37
|
+
# :require_jars => [
|
38
|
+
# '~/Applications/apache-activemq-5.5.0/activemq-all-5.5.0.jar',
|
39
|
+
# '~/Applications/apache-activemq-5.5.0/lib/optional/slf4j-log4j12-1.5.11.jar',
|
40
|
+
# '~/Applications/apache-activemq-5.5.0/lib/optional/log4j-1.2.14.jar',
|
41
|
+
# ]
|
42
42
|
# ) do |session|
|
43
|
-
# session.consumer(:queue_name=>'TEST'
|
43
|
+
# session.consumer(:queue_name=>'TEST') do |consumer|
|
44
44
|
# if message = consumer.receive_no_wait
|
45
45
|
# puts "Data Received: #{message.data}"
|
46
46
|
# else
|
@@ -70,13 +70,16 @@ module JMS
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
# Connect to a JMS Broker, create
|
73
|
+
# Connect to a JMS Broker, create and start the session,
|
74
|
+
# then call the code block passing in the session.
|
74
75
|
# Both the Session and Connection are closed on termination of the block
|
75
76
|
#
|
76
77
|
# Shortcut convenience method to both connect to the broker and create a session
|
77
78
|
# Useful when only a single session is required in the current thread
|
78
79
|
#
|
79
80
|
# Note: It is important that each thread have its own session to support transactions
|
81
|
+
# This method will also start the session immediately so that any
|
82
|
+
# consumers using this session will start immediately
|
80
83
|
def self.session(params = {}, &proc)
|
81
84
|
self.start(params) do |connection|
|
82
85
|
connection.session(params, &proc)
|
@@ -101,22 +104,25 @@ module JMS
|
|
101
104
|
# TODO make this a class method
|
102
105
|
def fetch_dependencies(jar_list)
|
103
106
|
jar_list.each do |jar|
|
104
|
-
JMS::logger.
|
107
|
+
JMS::logger.debug "Loading Jar File:#{jar}"
|
105
108
|
begin
|
106
109
|
require jar
|
107
110
|
rescue Exception => exc
|
108
111
|
JMS::logger.error "Failed to Load Jar File:#{jar}. #{exc.to_s}"
|
109
112
|
end
|
110
113
|
end if jar_list
|
111
|
-
|
112
|
-
require 'jms/
|
113
|
-
require 'jms/
|
114
|
-
require 'jms/
|
115
|
-
require 'jms/
|
116
|
-
require 'jms/
|
117
|
-
require 'jms/
|
118
|
-
require 'jms/
|
119
|
-
require 'jms/
|
114
|
+
|
115
|
+
require 'jms/imports'
|
116
|
+
require 'jms/message_listener_impl'
|
117
|
+
require 'jms/message'
|
118
|
+
require 'jms/text_message'
|
119
|
+
require 'jms/map_message'
|
120
|
+
require 'jms/bytes_message'
|
121
|
+
require 'jms/object_message'
|
122
|
+
require 'jms/session'
|
123
|
+
require 'jms/message_consumer'
|
124
|
+
require 'jms/queue_browser'
|
125
|
+
require 'jms/oracle_a_q_connection_factory'
|
120
126
|
end
|
121
127
|
|
122
128
|
# Create a connection to the JMS provider
|
@@ -139,101 +145,42 @@ module JMS
|
|
139
145
|
# :jndi_context => Mandatory if jndi lookup is being used, contains details
|
140
146
|
# on how to connect to JNDI server etc.
|
141
147
|
#
|
148
|
+
# :require_jars => An optional array of Jar file names to load for the specified
|
149
|
+
# JMS provider. By using this option it is not necessary
|
150
|
+
# to put all the JMS Provider specific jar files into the
|
151
|
+
# environment variable CLASSPATH prior to starting JRuby
|
152
|
+
#
|
153
|
+
# :username => Username to connect to JMS provider with
|
154
|
+
# :password => Password to use when to connecting to the JMS provider
|
155
|
+
# Note: :password is ignored if :username is not supplied
|
156
|
+
#
|
142
157
|
# :factory and :jndi_name are mutually exclusive, both cannot be supplied at the
|
143
158
|
# same time. :factory takes precedence over :jndi_name
|
144
159
|
#
|
145
160
|
# JMS Provider specific properties can be set if the JMS Factory itself
|
146
|
-
# has setters for those properties.
|
147
|
-
#
|
148
|
-
#
|
149
|
-
# :factory => 'org.hornetq.jms.client.HornetQConnectionFactory',
|
150
|
-
# :discovery_address => '127.0.0.1',
|
151
|
-
# :discovery_port => '5445',
|
152
|
-
# :username => 'guest',
|
153
|
-
# :password => 'guest'
|
154
|
-
#
|
155
|
-
# For HornetQ using JNDI lookup technique
|
156
|
-
# :jndi_name => '/ConnectionFactory',
|
157
|
-
# :jndi_context => {
|
158
|
-
# 'java.naming.factory.initial' => 'org.jnp.interfaces.NamingContextFactory',
|
159
|
-
# 'java.naming.provider.url' => 'jnp://localhost:1099',
|
160
|
-
# 'java.naming.factory.url.pkgs' => 'org.jboss.naming:org.jnp.interfaces',
|
161
|
-
# 'java.naming.security.principal' => 'guest',
|
162
|
-
# 'java.naming.security.credentials' => 'guest'
|
163
|
-
# }
|
164
|
-
#
|
165
|
-
# On Java 6, HornetQ needs the following jar files on your CLASSPATH:
|
166
|
-
# hornetq-core-client.jar
|
167
|
-
# netty.jar
|
168
|
-
# hornetq-jms-client.jar
|
169
|
-
# jboss-jms-api.jar
|
170
|
-
# jnp-client.jar
|
171
|
-
#
|
172
|
-
# On Java 5, HornetQ needs the following jar files on your CLASSPATH:
|
173
|
-
# hornetq-core-client-java5.jar
|
174
|
-
# netty.jar
|
175
|
-
# hornetq-jms-client-java5.jar
|
176
|
-
# jboss-jms-api.jar
|
177
|
-
# jnp-client.jar
|
178
|
-
#
|
179
|
-
# For: WebSphere MQ
|
180
|
-
# :factory => 'com.ibm.mq.jms.MQQueueConnectionFactory',
|
181
|
-
# :queue_manager=>'REID',
|
182
|
-
# :host_name=>'localhost',
|
183
|
-
# :channel=>'MY.CLIENT.CHL',
|
184
|
-
# :port=>1414,
|
185
|
-
# :transport_type => com.ibm.mq.jms.JMSC::MQJMS_TP_CLIENT_MQ_TCPIP,
|
186
|
-
# :username => 'mqm'
|
187
|
-
#
|
188
|
-
# For: Active MQ
|
189
|
-
# :factory => 'org.apache.activemq.ActiveMQConnectionFactory',
|
190
|
-
# :broker_url => 'tcp://localhost:61616'
|
191
|
-
#
|
192
|
-
# ActiveMQ requires the following jar files on your CLASSPATH
|
193
|
-
#
|
194
|
-
# For Oracle AQ 9 Server
|
195
|
-
# :factory => 'JMS::OracleAQConnectionFactory',
|
196
|
-
# :url => 'jdbc:oracle:thin:@hostname:1521:instanceid',
|
197
|
-
# :username => 'aquser',
|
198
|
-
# :password => 'mypassword'
|
199
|
-
#
|
200
|
-
# For JBoss, which uses JNDI lookup technique
|
201
|
-
# :jndi_name => 'ConnectionFactory',
|
202
|
-
# :jndi_context => {
|
203
|
-
# 'java.naming.factory.initial' => 'org.jnp.interfaces.NamingContextFactory',
|
204
|
-
# 'java.naming.provider.url' => 'jnp://localhost:1099'
|
205
|
-
# 'java.naming.security.principal' => 'user',
|
206
|
-
# 'java.naming.security.credentials' => 'pwd'
|
207
|
-
# }
|
208
|
-
#
|
209
|
-
# For Apache Qpid / Redhat Messaging, using Factory class directly
|
210
|
-
# :factory: org.apache.qpid.client.AMQConnectionFactory
|
211
|
-
# :broker_url: tcp://localhost:5672
|
212
|
-
#
|
213
|
-
# For Apache Qpid / Redhat Messaging, via JNDI lookup
|
214
|
-
# :jndi_name => 'local',
|
215
|
-
# :jndi_context => {
|
216
|
-
# 'java.naming.factory.initial' => 'org.apache.qpid.jndi.PropertiesFileInitialContextFactory',
|
217
|
-
# 'connectionfactory.local' => "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"
|
218
|
-
# }
|
161
|
+
# has setters for those properties.
|
162
|
+
#
|
163
|
+
# For some known examples, see: [Example jms.yml](https://github.com/reidmorrison/jruby-jms/blob/master/examples/jms.yml)
|
219
164
|
#
|
220
165
|
def initialize(params = {})
|
221
166
|
# Used by ::on_message
|
222
167
|
@sessions = []
|
223
168
|
@consumers = []
|
224
169
|
|
170
|
+
options = params.dup
|
171
|
+
|
225
172
|
# Load Jar files on demand so that they do not need to be in the CLASSPATH
|
226
173
|
# of JRuby lib directory
|
227
|
-
fetch_dependencies(
|
174
|
+
fetch_dependencies(options.delete(:require_jars))
|
228
175
|
|
229
176
|
connection_factory = nil
|
230
|
-
factory =
|
177
|
+
factory = options.delete(:factory)
|
231
178
|
if factory
|
232
179
|
# If factory is a string, then it is the name of a class, not the class itself
|
233
180
|
factory = eval(factory) if factory.respond_to? :to_str
|
234
181
|
connection_factory = factory.new
|
235
|
-
elsif jndi_name =
|
236
|
-
raise "Missing mandatory parameter :jndi_context missing in call to Connection::connect" unless jndi_context =
|
182
|
+
elsif jndi_name = options[:jndi_name]
|
183
|
+
raise "Missing mandatory parameter :jndi_context missing in call to Connection::connect" unless jndi_context = options[:jndi_context]
|
237
184
|
jndi = javax.naming.InitialContext.new(java.util.Hashtable.new(jndi_context))
|
238
185
|
begin
|
239
186
|
connection_factory = jndi.lookup jndi_name
|
@@ -243,17 +190,25 @@ module JMS
|
|
243
190
|
else
|
244
191
|
raise "Missing mandatory parameter :factory or :jndi_name missing in call to Connection::connect"
|
245
192
|
end
|
193
|
+
options.delete(:jndi_name)
|
194
|
+
options.delete(:jndi_context)
|
246
195
|
|
247
196
|
JMS::logger.debug "Using Factory: #{connection_factory.java_class}" if connection_factory.respond_to? :java_class
|
248
|
-
|
197
|
+
options.each_pair do |key, val|
|
198
|
+
next if [:username, :password].include?(key)
|
199
|
+
|
249
200
|
method = key.to_s+'='
|
250
201
|
if connection_factory.respond_to? method
|
251
202
|
connection_factory.send method, val
|
252
|
-
JMS::logger.debug " #{key} = #{connection_factory.send key}" if connection_factory.respond_to? key.to_sym
|
203
|
+
JMS::logger.debug " #{key} = #{connection_factory.send key.to_sym}" if connection_factory.respond_to? key.to_sym
|
204
|
+
else
|
205
|
+
JMS::logger.warn "#{connection_factory.java_class} does not understand option: :#{key}=#{val}, ignoring :#{key}" if connection_factory.respond_to? :java_class
|
253
206
|
end
|
254
207
|
end
|
255
|
-
|
256
|
-
|
208
|
+
|
209
|
+
# Check for username and password
|
210
|
+
if options[:username]
|
211
|
+
@jms_connection = connection_factory.create_connection(options[:username], options[:password])
|
257
212
|
else
|
258
213
|
@jms_connection = connection_factory.create_connection
|
259
214
|
end
|
@@ -266,7 +221,7 @@ module JMS
|
|
266
221
|
def start
|
267
222
|
@jms_connection.start
|
268
223
|
end
|
269
|
-
|
224
|
+
|
270
225
|
# Temporarily stop delivery of incoming messages on this connection
|
271
226
|
# Useful during a hot code update or other changes that need to be completed
|
272
227
|
# without any new messages being processed
|
@@ -285,8 +240,25 @@ module JMS
|
|
285
240
|
# Determines whether transactions are supported within this session.
|
286
241
|
# I.e. Whether commit or rollback can be called
|
287
242
|
# Default: false
|
288
|
-
#
|
289
|
-
#
|
243
|
+
# Note: :options below are ignored if this value is set to :true
|
244
|
+
#
|
245
|
+
# :options => any of the JMS::Session constants:
|
246
|
+
# Note: :options are ignored if :transacted => true
|
247
|
+
# JMS::Session::AUTO_ACKNOWLEDGE
|
248
|
+
# With this acknowledgment mode, the session automatically acknowledges
|
249
|
+
# a client's receipt of a message either when the session has successfully
|
250
|
+
# returned from a call to receive or when the message listener the session has
|
251
|
+
# called to process the message successfully returns.
|
252
|
+
# JMS::Session::CLIENT_ACKNOWLEDGE
|
253
|
+
# With this acknowledgment mode, the client acknowledges a consumed
|
254
|
+
# message by calling the message's acknowledge method.
|
255
|
+
# JMS::Session::DUPS_OK_ACKNOWLEDGE
|
256
|
+
# This acknowledgment mode instructs the session to lazily acknowledge
|
257
|
+
# the delivery of messages.
|
258
|
+
# JMS::Session::SESSION_TRANSACTED
|
259
|
+
# This value is returned from the method getAcknowledgeMode if the
|
260
|
+
# session is transacted.
|
261
|
+
# Default: JMS::Session::AUTO_ACKNOWLEDGE
|
290
262
|
#
|
291
263
|
def session(params={}, &proc)
|
292
264
|
raise "Missing mandatory Block when calling JMS::Connection#session" unless proc
|
@@ -310,28 +282,29 @@ module JMS
|
|
310
282
|
# Determines whether transactions are supported within this session.
|
311
283
|
# I.e. Whether commit or rollback can be called
|
312
284
|
# Default: false
|
313
|
-
# Note: :options below
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
285
|
+
# Note: :options below are ignored if this value is set to :true
|
286
|
+
#
|
287
|
+
# :options => any of the JMS::Session constants:
|
288
|
+
# Note: :options are ignored if :transacted => true
|
289
|
+
# JMS::Session::AUTO_ACKNOWLEDGE
|
317
290
|
# With this acknowledgment mode, the session automatically acknowledges
|
318
291
|
# a client's receipt of a message either when the session has successfully
|
319
292
|
# returned from a call to receive or when the message listener the session has
|
320
293
|
# called to process the message successfully returns.
|
321
|
-
#
|
294
|
+
# JMS::Session::CLIENT_ACKNOWLEDGE
|
322
295
|
# With this acknowledgment mode, the client acknowledges a consumed
|
323
296
|
# message by calling the message's acknowledge method.
|
324
|
-
#
|
297
|
+
# JMS::Session::DUPS_OK_ACKNOWLEDGE
|
325
298
|
# This acknowledgment mode instructs the session to lazily acknowledge
|
326
299
|
# the delivery of messages.
|
327
|
-
#
|
300
|
+
# JMS::Session::SESSION_TRANSACTED
|
328
301
|
# This value is returned from the method getAcknowledgeMode if the
|
329
302
|
# session is transacted.
|
330
|
-
# Default:
|
303
|
+
# Default: JMS::Session::AUTO_ACKNOWLEDGE
|
331
304
|
#
|
332
305
|
def create_session(params={})
|
333
306
|
transacted = params[:transacted] || false
|
334
|
-
options = params[:options] ||
|
307
|
+
options = params[:options] || JMS::Session::AUTO_ACKNOWLEDGE
|
335
308
|
@jms_connection.create_session(transacted, options)
|
336
309
|
end
|
337
310
|
|
@@ -346,65 +319,62 @@ module JMS
|
|
346
319
|
|
347
320
|
@jms_connection.close if @jms_connection
|
348
321
|
end
|
349
|
-
|
322
|
+
|
350
323
|
# Gets the client identifier for this connection.
|
351
324
|
def client_id
|
352
325
|
@jms_connection.getClientID
|
353
326
|
end
|
354
|
-
|
327
|
+
|
355
328
|
# Sets the client identifier for this connection.
|
356
329
|
def client_id=(client_id)
|
357
330
|
@jms_connection.setClientID(client_id)
|
358
331
|
end
|
359
|
-
|
332
|
+
|
360
333
|
# Returns the ExceptionListener object for this connection
|
361
|
-
# Returned class implements interface
|
334
|
+
# Returned class implements interface JMS::ExceptionListener
|
362
335
|
def exception_listener
|
363
336
|
@jms_connection.getExceptionListener
|
364
337
|
end
|
365
|
-
|
338
|
+
|
366
339
|
# Sets an exception listener for this connection
|
367
340
|
# See ::on_exception to set a Ruby Listener
|
368
341
|
# Returns: nil
|
369
342
|
def exception_listener=(listener)
|
370
|
-
setExceptionListener(listener)
|
343
|
+
@jms_connection.setExceptionListener(listener)
|
371
344
|
end
|
372
|
-
|
345
|
+
|
373
346
|
# Whenever an exception occurs the supplied block is called
|
374
347
|
# This is important when Connection::on_message has been used, since
|
375
348
|
# failures to the connection would be lost otherwise
|
376
|
-
#
|
377
|
-
# For details on the supplied parameter when the block is called,
|
349
|
+
#
|
350
|
+
# For details on the supplied parameter when the block is called,
|
378
351
|
# see: http://download.oracle.com/javaee/6/api/javax/jms/JMSException.html
|
379
|
-
#
|
352
|
+
#
|
380
353
|
# Example:
|
381
|
-
# connection.
|
354
|
+
# connection.on_exception do |jms_exception|
|
382
355
|
# puts "JMS Exception has occurred: #{jms_exception}"
|
383
356
|
# end
|
384
357
|
#
|
385
358
|
# Returns: nil
|
386
359
|
def on_exception(&block)
|
387
|
-
setExceptionListener(block)
|
360
|
+
@jms_connection.setExceptionListener(block)
|
388
361
|
end
|
389
|
-
|
362
|
+
|
390
363
|
# Gets the metadata for this connection
|
391
364
|
# see: http://download.oracle.com/javaee/6/api/javax/jms/ConnectionMetaData.html
|
392
365
|
def meta_data
|
393
366
|
@jms_connection.getMetaData
|
394
367
|
end
|
395
|
-
|
368
|
+
|
396
369
|
# Return a string describing the JMS provider and version
|
397
370
|
def to_s
|
398
371
|
md = @jms_connection.getMetaData
|
399
372
|
"JMS::Connection provider: #{md.getJMSProviderName} v#{md.getProviderVersion}, JMS v#{md.getJMSVersion}"
|
400
373
|
end
|
401
374
|
|
402
|
-
# TODO: Return a pretty print version of the current JMS Connection
|
403
|
-
# def to_s
|
404
|
-
# end
|
405
|
-
|
406
375
|
# Receive messages in a separate thread when they arrive
|
407
|
-
#
|
376
|
+
#
|
377
|
+
# Allows messages to be received Asynchronously in a separate thread.
|
408
378
|
# This method will return to the caller before messages are processed.
|
409
379
|
# It is then the callers responsibility to keep the program active so that messages
|
410
380
|
# can then be processed.
|
@@ -414,19 +384,36 @@ module JMS
|
|
414
384
|
# Determines whether transactions are supported within this session.
|
415
385
|
# I.e. Whether commit or rollback can be called
|
416
386
|
# Default: false
|
417
|
-
#
|
418
|
-
#
|
387
|
+
# Note: :options below are ignored if this value is set to :true
|
388
|
+
#
|
389
|
+
# :options => any of the JMS::Session constants:
|
390
|
+
# Note: :options are ignored if :transacted => true
|
391
|
+
# JMS::Session::AUTO_ACKNOWLEDGE
|
392
|
+
# With this acknowledgment mode, the session automatically acknowledges
|
393
|
+
# a client's receipt of a message either when the session has successfully
|
394
|
+
# returned from a call to receive or when the message listener the session has
|
395
|
+
# called to process the message successfully returns.
|
396
|
+
# JMS::Session::CLIENT_ACKNOWLEDGE
|
397
|
+
# With this acknowledgment mode, the client acknowledges a consumed
|
398
|
+
# message by calling the message's acknowledge method.
|
399
|
+
# JMS::Session::DUPS_OK_ACKNOWLEDGE
|
400
|
+
# This acknowledgment mode instructs the session to lazily acknowledge
|
401
|
+
# the delivery of messages.
|
402
|
+
# JMS::Session::SESSION_TRANSACTED
|
403
|
+
# This value is returned from the method getAcknowledgeMode if the
|
404
|
+
# session is transacted.
|
405
|
+
# Default: JMS::Session::AUTO_ACKNOWLEDGE
|
419
406
|
#
|
420
407
|
# :session_count : Number of sessions to create, each with their own consumer which
|
421
|
-
# in turn will call the supplied
|
422
|
-
# Note: The supplied
|
408
|
+
# in turn will call the supplied code block.
|
409
|
+
# Note: The supplied block must be thread safe since it will be called
|
423
410
|
# by several threads at the same time.
|
424
411
|
# I.e. Don't change instance variables etc. without the
|
425
412
|
# necessary semaphores etc.
|
426
413
|
# Default: 1
|
427
414
|
#
|
428
415
|
# Consumer Parameters:
|
429
|
-
# :queue_name
|
416
|
+
# :queue_name => String: Name of the Queue to return
|
430
417
|
# Symbol: :temporary => Create temporary queue
|
431
418
|
# Mandatory unless :topic_name is supplied
|
432
419
|
# Or,
|
@@ -438,8 +425,9 @@ module JMS
|
|
438
425
|
#
|
439
426
|
# :selector => Filter which messages should be returned from the queue
|
440
427
|
# Default: All messages
|
428
|
+
#
|
441
429
|
# :no_local => Determine whether messages published by its own connection
|
442
|
-
# should be delivered to
|
430
|
+
# should be delivered to the supplied block
|
443
431
|
# Default: false
|
444
432
|
#
|
445
433
|
# :statistics Capture statistics on how many messages have been read
|
@@ -451,18 +439,15 @@ module JMS
|
|
451
439
|
# Also, the start time and message count is not reset until MessageConsumer::each
|
452
440
|
# is called again with :statistics => true
|
453
441
|
#
|
454
|
-
#
|
455
|
-
#
|
456
|
-
# Usage: For transacted sessions (the default) the Proc supplied must return
|
457
|
-
# either true or false:
|
442
|
+
# Usage: For transacted sessions the block supplied must return either true or false:
|
458
443
|
# true => The session is committed
|
459
444
|
# false => The session is rolled back
|
460
445
|
# Any Exception => The session is rolled back
|
461
446
|
#
|
462
|
-
# Note:
|
447
|
+
# Note: Separately invoke Connection#on_exception so that connection failures can be handled
|
448
|
+
# since on_message will Not be called if the connection is lost
|
463
449
|
#
|
464
|
-
|
465
|
-
def on_message(params, &proc)
|
450
|
+
def on_message(params, &block)
|
466
451
|
raise "JMS::Connection must be connected prior to calling JMS::Connection::on_message" unless @sessions && @consumers
|
467
452
|
|
468
453
|
consumer_count = params[:session_count] || 1
|
@@ -472,40 +457,63 @@ module JMS
|
|
472
457
|
if session.transacted?
|
473
458
|
consumer.on_message(params) do |message|
|
474
459
|
begin
|
475
|
-
|
460
|
+
block.call(message) ? session.commit : session.rollback
|
476
461
|
rescue => exc
|
477
462
|
session.rollback
|
478
463
|
throw exc
|
479
464
|
end
|
480
465
|
end
|
481
466
|
else
|
482
|
-
consumer.on_message(params, &
|
467
|
+
consumer.on_message(params, &block)
|
483
468
|
end
|
484
469
|
@consumers << consumer
|
485
470
|
@sessions << session
|
486
471
|
end
|
487
472
|
end
|
488
473
|
|
474
|
+
# Return the statistics for every active Connection#on_message consumer
|
475
|
+
# in an Array
|
476
|
+
#
|
477
|
+
# For details on the contents of each element in the array, see: Consumer#on_message_statistics
|
489
478
|
def on_message_statistics
|
490
|
-
@consumers.collect{|consumer| consumer.on_message_statistics}
|
479
|
+
@consumers.collect { |consumer| consumer.on_message_statistics }
|
491
480
|
end
|
492
481
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
#
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
482
|
+
# Since a Session can only be used by one thread at a time, we could create
|
483
|
+
# a Session for every thread. That could result in excessive unused Sessions.
|
484
|
+
# An alternative is to create a pool of sessions that can be shared by
|
485
|
+
# multiple threads.
|
486
|
+
#
|
487
|
+
# Each thread can request a session and then return it once it is no longer
|
488
|
+
# needed by that thread. The only way to get a session is to pass a block so that
|
489
|
+
# the Session is automatically returned to the pool upon completion of the block.
|
490
|
+
#
|
491
|
+
# Parameters:
|
492
|
+
# see regular session parameters from: JMS::Connection#initialize
|
493
|
+
#
|
494
|
+
# Additional parameters for controlling the session pool itself
|
495
|
+
# :pool_name Name of the pool as it shows up in the logger.
|
496
|
+
# Default: 'JMS::SessionPool'
|
497
|
+
# :pool_size Maximum Pool Size. Default: 10
|
498
|
+
# The pool only grows as needed and will never exceed
|
499
|
+
# :pool_size
|
500
|
+
# :pool_warn_timeout Number of seconds to wait before logging a warning when a
|
501
|
+
# session in the pool is not available. Measured in seconds
|
502
|
+
# Default: 5.0
|
503
|
+
# :pool_logger Supply a logger that responds to #debug, #info, #warn and #debug?
|
504
|
+
# For example: Rails.logger
|
505
|
+
# Default: None
|
506
|
+
# Example:
|
507
|
+
# session_pool = connection.create_session_pool(config)
|
508
|
+
#
|
509
|
+
# session_pool.session do |session|
|
510
|
+
# producer.send(session.message("Hello World"))
|
511
|
+
# end
|
512
|
+
def create_session_pool(params={})
|
513
|
+
require 'jms/session_pool' unless defined? JMS::SessionPool
|
514
|
+
JMS::SessionPool.new(self, params)
|
508
515
|
end
|
516
|
+
|
509
517
|
end
|
510
518
|
|
511
519
|
end
|