jruby-hornetq 0.3.3 → 0.4.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 +5 -0
- data/README.md +4 -11
- data/Rakefile +1 -1
- data/examples/producer-consumer/browse_all.rb +25 -0
- data/examples/producer-consumer/consume_all.rb +1 -1
- data/lib/hornetq.rb +5 -0
- data/lib/hornetq/client/connection.rb +241 -116
- data/lib/hornetq/client/org_hornetq_api_core_client_client_session.rb +4 -5
- data/lib/hornetq/client/org_hornetq_core_client_impl_client_message_impl.rb +24 -10
- data/lib/hornetq/client/requestor_pattern.rb +94 -13
- data/lib/hornetq/client/server_pattern.rb +1 -0
- data/lib/hornetq/java/hornetq-core-client.jar +0 -0
- data/lib/hornetq/java/hornetq-core.jar +0 -0
- data/lib/hornetq/java/netty.jar +0 -0
- metadata +3 -2
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -3,17 +3,11 @@ jruby-hornetq
|
|
3
3
|
|
4
4
|
* http://github.com/ClarityServices/jruby-hornetq
|
5
5
|
|
6
|
-
### WARNING: Alpha code!!
|
7
|
-
|
8
|
-
This code should only be used for prototyping at this time, since breaking
|
9
|
-
changes are made between every release. Once the code goes to V1.0.0 we will
|
10
|
-
make every effort to not break the existing interface in any way.
|
11
|
-
|
12
6
|
Feedback is welcome and appreciated :)
|
13
7
|
|
14
8
|
### Introduction
|
15
9
|
|
16
|
-
jruby-hornetq
|
10
|
+
jruby-hornetq create a Ruby friendly API into the HornetQ Java libraries without
|
17
11
|
compromising performance. It does this by sprinkling "Ruby-goodness" into the
|
18
12
|
existing HornetQ Java classes and interfaces, I.e. By adding Ruby methods to
|
19
13
|
the existing classes and interfaces. Since jruby-hornetq exposes the HornetQ
|
@@ -36,15 +30,14 @@ several reasons for choosing the HornetQ Core API over its JMS API:
|
|
36
30
|
* The HornetQ team recommend the Core API for performance
|
37
31
|
* The HornetQ JMS API is just another wrapper on top of its Core API
|
38
32
|
|
39
|
-
To use the JMS API
|
40
|
-
let me know if you want it :) )
|
33
|
+
To use the JMS API from JRuby see the jruby-jms project
|
41
34
|
|
42
35
|
HornetQ
|
43
36
|
-------
|
44
37
|
|
45
|
-
For information on the HornetQ messaging and queuing system, see:
|
38
|
+
For information on the HornetQ messaging and queuing system, see: http://www.jboss.org/hornetq
|
46
39
|
|
47
|
-
For more documentation on any of the classes, see: http://
|
40
|
+
For more documentation on any of the classes, see: http://docs.jboss.org/hornetq/2.2.2.Final/api/index.html
|
48
41
|
|
49
42
|
Concepts & Terminology
|
50
43
|
----------------------
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ desc "Build gem"
|
|
9
9
|
task :gem do |t|
|
10
10
|
gemspec = Gem::Specification.new do |s|
|
11
11
|
s.name = 'jruby-hornetq'
|
12
|
-
s.version = '0.
|
12
|
+
s.version = '0.4.0'
|
13
13
|
s.authors = ['Reid Morrison', 'Brad Pardee']
|
14
14
|
s.email = ['rubywmq@gmail.com', 'bpardee@gmail.com']
|
15
15
|
s.homepage = 'https://github.com/ClarityServices/jruby-hornetq'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# HornetQ Consumer:
|
3
|
+
# Read a single message from 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 'hornetq'
|
11
|
+
|
12
|
+
# Using Connect.start since a session must be started in order to consume messages
|
13
|
+
HornetQ::Client::Connection.start_session('hornetq://localhost') do |session|
|
14
|
+
|
15
|
+
# Create a non-durable TestQueue to receive messages sent to the TestAddress
|
16
|
+
session.create_queue_ignore_exists('TestAddress', 'TestQueue', false)
|
17
|
+
|
18
|
+
# Consume All messages from the queue and gather statistics
|
19
|
+
stats = session.consume(:queue_name => 'TestQueue', :timeout=> 0, :statistics=>true, :browse_only=>true) do |message|
|
20
|
+
p message
|
21
|
+
puts "=================================="
|
22
|
+
message.acknowledge
|
23
|
+
end
|
24
|
+
puts "Browsed #{stats[:count]} messages in #{stats[:duration]} seconds at #{stats[:messages_per_second]} messages per second"
|
25
|
+
end
|
@@ -21,5 +21,5 @@ HornetQ::Client::Connection.start_session('hornetq://localhost') do |session|
|
|
21
21
|
puts "=================================="
|
22
22
|
message.acknowledge
|
23
23
|
end
|
24
|
-
puts "
|
24
|
+
puts "Consumed #{stats[:count]} messages in #{stats[:duration]} seconds at #{stats[:messages_per_second]} messages per second"
|
25
25
|
end
|
data/lib/hornetq.rb
CHANGED
@@ -25,6 +25,11 @@ module HornetQ
|
|
25
25
|
return java.lang.Integer.new(port)
|
26
26
|
end
|
27
27
|
|
28
|
+
# Convert string into a HornetQ SimpleString
|
29
|
+
def self.as_simple_string(str)
|
30
|
+
str.is_a?(Java::org.hornetq.api.core::SimpleString) ? str : Java::org.hornetq.api.core::SimpleString.new(str.to_s)
|
31
|
+
end
|
32
|
+
|
28
33
|
end
|
29
34
|
|
30
35
|
require 'hornetq/server'
|
@@ -34,7 +34,7 @@ module HornetQ
|
|
34
34
|
# block. Upon completion the session and connection are both closed
|
35
35
|
# See Connection::initialize and Connection::create_session for the list
|
36
36
|
# of parameters
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# Returns result of block
|
39
39
|
def self.start_session(params={},&proc)
|
40
40
|
session(params) do |session|
|
@@ -63,50 +63,8 @@ module HornetQ
|
|
63
63
|
|
64
64
|
# Create a new Connection from which sessions can be created
|
65
65
|
#
|
66
|
-
# Parameters:
|
67
|
-
# * a Hash consisting of one or more of the named parameters
|
68
|
-
# * Summary of parameters and their default values
|
69
|
-
# HornetQ::Client::Connection.new(
|
70
|
-
# :uri => 'hornetq://localhost',
|
71
|
-
# :ack_batch_size => ,
|
72
|
-
# :auto_group => ,
|
73
|
-
# :block_on_acknowledge => ,
|
74
|
-
# :block_on_durable_send => ,
|
75
|
-
# :block_on_non_durable_send => ,
|
76
|
-
# :cache_large_messages_client => ,
|
77
|
-
# :call_timeout => ,
|
78
|
-
# :client_failure_check_period => ,
|
79
|
-
# :confirmation_window_size => ,
|
80
|
-
# :connection_load_balancing_policy_class_name => ,
|
81
|
-
# :connection_ttl => ,
|
82
|
-
# :consumer_max_rate => ,
|
83
|
-
# :consumer_window_size => ,
|
84
|
-
# :discovery_address => ,
|
85
|
-
# :discovery_initial_wait_timeout => ,
|
86
|
-
# :discovery_port => ,
|
87
|
-
# :discovery_refresh_timeout => ,
|
88
|
-
# :failover_on_initial_connection => true,
|
89
|
-
# :failover_on_server_shutdown => true,
|
90
|
-
# :group_id => ,
|
91
|
-
# :initial_message_packet_size => ,
|
92
|
-
# :java_object => ,
|
93
|
-
# :local_bind_address => ,
|
94
|
-
# :max_retry_interval => ,
|
95
|
-
# :min_large_message_size => ,
|
96
|
-
# :pre_acknowledge => ,
|
97
|
-
# :producer_max_rate => ,
|
98
|
-
# :producer_window_size => ,
|
99
|
-
# :reconnect_attempts => 1,
|
100
|
-
# :retry_interval => ,
|
101
|
-
# :retry_interval_multiplier => ,
|
102
|
-
# :scheduled_thread_pool_max_size => ,
|
103
|
-
# :static_connectors => ,
|
104
|
-
# :thread_pool_max_size => ,
|
105
|
-
# :use_global_pools =>
|
106
|
-
# )
|
107
|
-
#
|
108
66
|
# Mandatory Parameters
|
109
|
-
# * :uri
|
67
|
+
# * :uri => 'hornetq://localhost',
|
110
68
|
# * The hornetq uri as to which server to connect with and which
|
111
69
|
# transport protocol to use. Format:
|
112
70
|
# hornetq://server:port,backupserver:port/?protocol=[netty|discover]
|
@@ -118,44 +76,204 @@ module HornetQ
|
|
118
76
|
# hornetq://server:port/?protocol=discovery
|
119
77
|
# * To use HornetQ within the current JVM
|
120
78
|
# hornetq://invm
|
121
|
-
#
|
122
79
|
# Optional Parameters
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
# *
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
|
80
|
+
#
|
81
|
+
# High Availability
|
82
|
+
#
|
83
|
+
# * :ha => true | false,
|
84
|
+
# true: Receives cluster topology updates from the cluster as
|
85
|
+
# servers leave or join and new backups are appointed or removed.
|
86
|
+
# false: Uses the suplied static list of hosts in :uri
|
87
|
+
# and no HA backup information is propagated to the client
|
88
|
+
# Default: false
|
89
|
+
#
|
90
|
+
# Flow Control
|
91
|
+
#
|
92
|
+
# :ack_batch_size => integer,
|
93
|
+
# Sets the acknowledgements batch size. Must be > 0
|
94
|
+
#
|
95
|
+
# :pre_acknowledge => true | false,
|
96
|
+
# Sets whether messages will pre-acknowledged on the server before
|
97
|
+
# they are sent to the consumers or not
|
98
|
+
# true : Pre-acknowledge consumed messages on the server before they are sent to consumers
|
99
|
+
# false: Clients acknowledge the message they consume.
|
100
|
+
# Default: false
|
101
|
+
#
|
102
|
+
# Grouping:
|
103
|
+
#
|
104
|
+
# :auto_group => true | false,
|
105
|
+
# Sets whether producers will automatically assign a group ID
|
106
|
+
# to sent messages
|
107
|
+
# true: A random unique group ID is created and set on each message
|
108
|
+
# for the property Message.HDR_GROUP_ID
|
109
|
+
# Default: false
|
110
|
+
#
|
111
|
+
# :group_id => string,
|
112
|
+
# Sets the group ID that will be set on each message sent
|
113
|
+
# Default: nil (no goup id will be set)
|
114
|
+
#
|
115
|
+
# Blocking calls:
|
116
|
+
#
|
117
|
+
# :block_on_acknowledge => true | false,
|
118
|
+
# Sets whether consumers created through this factory will block
|
119
|
+
# while sending message acknowledgements or do it asynchronously.
|
120
|
+
# Default: false
|
121
|
+
#
|
122
|
+
# :block_on_durable_send => true | false,
|
123
|
+
# Sets whether producers will block while sending durable messages
|
124
|
+
# or do it asynchronously.
|
125
|
+
# If the session is configured to send durable message asynchronously,
|
126
|
+
# the client can set a SendAcknowledgementHandler on the ClientSession
|
127
|
+
# to be notified once the message has been handled by the server.
|
128
|
+
# Default: true
|
129
|
+
#
|
130
|
+
# :block_on_non_durable_send => true | false,
|
131
|
+
# Sets whether producers will block while sending non-durable messages
|
132
|
+
# or do it asynchronously.
|
133
|
+
# If the session is configured to send non-durable message asynchronously,
|
134
|
+
# the client can set a SendAcknowledgementHandler on the ClientSession
|
135
|
+
# to be notified once the message has been handled by the server.
|
136
|
+
# Default: false
|
137
|
+
#
|
138
|
+
# :call_timeout => long,
|
139
|
+
# Sets the blocking calls timeout in milliseconds. If client's blocking calls to the
|
140
|
+
# server take more than this timeout, the call will throw a
|
141
|
+
# HornetQException with the code HornetQException.CONNECTION_TIMEDOUT.
|
142
|
+
# Value is in milliseconds, default value is HornetQClient.DEFAULT_CALL_TIMEOUT.
|
143
|
+
# Must be >= 0
|
144
|
+
#
|
145
|
+
# Client Reconnection Parameters:
|
146
|
+
#
|
147
|
+
# :connection_ttl => long,
|
148
|
+
# Set the connection time-to-live
|
149
|
+
# -1 : Disable
|
150
|
+
# >=0 : milliseconds the server will keep a connection alive in the
|
151
|
+
# absence of any data arriving from the client.
|
152
|
+
# Default: 60,000
|
153
|
+
#
|
154
|
+
# :client_failure_check_period => long,
|
155
|
+
# Sets the period in milliseconds used to check if a client has
|
156
|
+
# failed to receive pings from the server.
|
157
|
+
# Value must be -1 (to disable) or greater than 0
|
158
|
+
# Default: 30,000
|
159
|
+
#
|
160
|
+
# :initial_connect_attempts => int,
|
161
|
+
# ?
|
162
|
+
#
|
163
|
+
# :failover_on_initial_connection => true | false,
|
164
|
+
# Sets whether the client will automatically attempt to connect to
|
165
|
+
# the backup server if the initial connection to the live server fails
|
166
|
+
# true : If live server is not reachable try to connect to backup server
|
167
|
+
# false: Fail to start if live server is not reachable
|
168
|
+
# Default: false
|
169
|
+
#
|
170
|
+
# :max_retry_interval => long,
|
171
|
+
# Sets the maximum retry interval in milliseconds.
|
172
|
+
# Only appicable if the retry interval multiplier has been specified
|
173
|
+
# Default: 2000 (2 seconds)
|
174
|
+
#
|
175
|
+
# :reconnect_attempts => 1,
|
176
|
+
# :retry_interval => long,
|
177
|
+
# Returns the time to retry the connection after failure.
|
178
|
+
# Value is in milliseconds.
|
179
|
+
# Default: 2000 (2 seconds)
|
180
|
+
#
|
181
|
+
# :retry_interval_multiplier => double,
|
182
|
+
# Sets the multiplier to apply to successive retry intervals.
|
183
|
+
# Value must be positive.
|
184
|
+
# Default: 1
|
185
|
+
#
|
186
|
+
# Large Message parameters:
|
187
|
+
#
|
188
|
+
# :cache_large_messages_client => true | false,
|
189
|
+
# Sets whether large messages received by consumers will be
|
190
|
+
# cached in temporary files or not.
|
191
|
+
# When true, consumers will create temporary files to cache large messages.
|
192
|
+
# There is 1 temporary file created for each large message.
|
193
|
+
# Default: false
|
194
|
+
#
|
195
|
+
# :min_large_message_size => int,
|
196
|
+
# Sets the large message size threshold in bytes. Value must be > 0
|
197
|
+
# Messages whose size is if greater than this value will be handled as large messages
|
198
|
+
# Default: 102400 bytes (100 KBytes)
|
199
|
+
#
|
200
|
+
# :compress_large_message => true | false,
|
201
|
+
#
|
202
|
+
# Message Rate Management:
|
203
|
+
#
|
204
|
+
# :consumer_max_rate => int,
|
205
|
+
# Sets the maximum rate of message consumption for consumers.
|
206
|
+
# Controls the rate at which a consumer can consume messages.
|
207
|
+
# A consumer will never consume messages at a rate faster than the
|
208
|
+
# rate specified.
|
209
|
+
# -1 : Disable
|
210
|
+
# >=0 : Maximum desired message consumption rate specified
|
211
|
+
# in units of messages per second.
|
212
|
+
# Default: -1
|
213
|
+
#
|
214
|
+
# :producer_max_rate => int,
|
215
|
+
# Sets the maximum rate of message production for producers.
|
216
|
+
# Controls the rate at which a producer can produce messages.
|
217
|
+
# A producer will never produce messages at a rate faster than the rate specified.
|
218
|
+
# -1 : Disabled
|
219
|
+
# >0 : Maximum desired message production rate specified in units of messages per second.
|
220
|
+
# Default: -1 (Disabled)
|
221
|
+
#
|
222
|
+
# Thread Pools:
|
223
|
+
#
|
224
|
+
# :scheduled_thread_pool_max_size => int,
|
225
|
+
# Sets the maximum size of the scheduled thread pool.
|
226
|
+
# This setting is relevant only if this factory does not use global pools.
|
227
|
+
# Value must be greater than 0.
|
228
|
+
# Default: 5
|
229
|
+
#
|
230
|
+
# :thread_pool_max_size => int,
|
231
|
+
# Sets the maximum size of the thread pool.
|
232
|
+
# This setting is relevant only if this factory does not use
|
233
|
+
# global pools.
|
234
|
+
# -1 : Unlimited thread pool
|
235
|
+
# >0 : Number of threads in pool
|
236
|
+
# Default: -1 (Unlimited)
|
237
|
+
#
|
238
|
+
# :use_global_pools => true | false,
|
239
|
+
# Sets whether this factory will use global thread pools
|
240
|
+
# (shared among all the factories in the same JVM) or its own pools.
|
241
|
+
# true: Uses global JVM thread pools across all HornetQ connections
|
242
|
+
# false: Use a thread pool just for this connection
|
243
|
+
# Default: true
|
244
|
+
#
|
245
|
+
# Window Sizes:
|
246
|
+
#
|
247
|
+
# :confirmation_window_size => int,
|
248
|
+
# Set the size in bytes for the confirmation window of this connection.
|
249
|
+
# -1 : Disable the window
|
250
|
+
# >0 : Size in bytes
|
251
|
+
# Default: -1 (Disabled)
|
252
|
+
#
|
253
|
+
# :consumer_window_size => int,
|
254
|
+
# Sets the window size for flow control for consumers.
|
255
|
+
# -1 : Disable flow control
|
256
|
+
# 0 : Do Not buffer any messages
|
257
|
+
# >0 : Set the maximum size of the buffer
|
258
|
+
# Default: 1048576 (1 MB)
|
259
|
+
#
|
260
|
+
# :producer_window_size => int,
|
261
|
+
# Sets the window size for flow control of the producers.
|
262
|
+
# -1 : Disable flow control
|
263
|
+
# >0 : The maximum amount of bytes at any give time (to prevent overloading the connection).
|
264
|
+
# Default: 65536 (64 KBytes)
|
265
|
+
#
|
266
|
+
# Other:
|
267
|
+
#
|
268
|
+
# :connection_load_balancing_policy_class_name => string,
|
269
|
+
# Set the class name of the connection load balancing policy
|
270
|
+
# Value must be the name of a class implementing org.hornetq.api.core.client.loadbalance.ConnectionLoadBalancingPolicy
|
271
|
+
# Default: "org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy"
|
272
|
+
#
|
273
|
+
# :initial_message_packet_size => int,
|
274
|
+
# Sets the initial size of messages in bytes
|
275
|
+
# Value must be greater than 0
|
276
|
+
#
|
159
277
|
def initialize(params={})
|
160
278
|
params =params.clone
|
161
279
|
uri = nil
|
@@ -170,50 +288,55 @@ module HornetQ
|
|
170
288
|
params = uri.params.merge(params)
|
171
289
|
end
|
172
290
|
|
173
|
-
@connection = nil
|
174
|
-
@sessions = []
|
175
|
-
@consumers = []
|
176
291
|
# In-VM Transport has no fail-over or additional parameters
|
177
292
|
@is_invm = uri.host == 'invm'
|
293
|
+
transport_list = []
|
178
294
|
if @is_invm
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# Unless already created, then the connection will use the netty protocol
|
191
|
-
unless @connection
|
192
|
-
# Primary Transport
|
193
|
-
transport = Java::org.hornetq.api.core.TransportConfiguration.new(HornetQ::NETTY_CONNECTOR_CLASS_NAME, {'host' => uri.host, 'port' => uri.port })
|
295
|
+
transport_list << Java::org.hornetq.api.core::TransportConfiguration.new(HornetQ::INVM_CONNECTOR_CLASS_NAME)
|
296
|
+
else
|
297
|
+
case params[:protocol]
|
298
|
+
when 'discovery'
|
299
|
+
#TODO: Also support: DiscoveryGroupConfiguration(String name, String localBindAddress, String groupAddress, int groupPort, long refreshTimeout, long discoveryInitialWaitTimeout)
|
300
|
+
transport_list << Java::org.hornetq.api.core::DiscoveryGroupConfiguration.new(uri.host, uri.port)
|
301
|
+
when 'netty', nil
|
302
|
+
transport_list << Java::org.hornetq.api.core::TransportConfiguration.new(HornetQ::NETTY_CONNECTOR_CLASS_NAME, {'host' => uri.host, 'port' => uri.port })
|
194
303
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
@connection = Java::org.hornetq.api.core.client.HornetQClient.create_client_session_factory(transport, backup_transport)
|
304
|
+
if uri.backup_host
|
305
|
+
transport_list << Java::org.hornetq.api.core::TransportConfiguration.new(HornetQ::NETTY_CONNECTOR_CLASS_NAME, {'host' => uri.backup_host, 'port' => uri.backup_port })
|
306
|
+
end
|
199
307
|
else
|
200
|
-
|
308
|
+
raise "Unknown HornetQ protocol:'#{params[:protocol]}'"
|
201
309
|
end
|
202
310
|
end
|
203
311
|
|
204
|
-
#
|
312
|
+
#TODO: Support: server_locator.addInterceptor
|
313
|
+
|
314
|
+
# Create server locator with or without HA. Without HA being the default
|
315
|
+
@server_locator = if params[:ha]
|
316
|
+
Java::org.hornetq.api.core.client::HornetQClient.createServerLocatorWithHA(*transport_list)
|
317
|
+
#TODO: Support: server_locator.addClusterTopologyListener
|
318
|
+
else
|
319
|
+
Java::org.hornetq.api.core.client::HornetQClient.createServerLocatorWithoutHA(*transport_list)
|
320
|
+
end
|
321
|
+
|
322
|
+
# If any other options were supplied, apply them to the server locator
|
205
323
|
params.each_pair do |key, val|
|
206
324
|
method = key.to_s+'='
|
207
|
-
if @
|
208
|
-
@
|
209
|
-
|
325
|
+
if @server_locator.respond_to? method
|
326
|
+
@server_locator.send method, val
|
327
|
+
HornetQ.logger.trace { "HornetQ ServerLocator setting: #{key} = #{@connection.send key}" } if @server_locator.respond_to? key.to_sym
|
210
328
|
else
|
211
|
-
HornetQ.logger.warn "Warning: Option:#{key}, with value:#{val} is invalid and
|
329
|
+
HornetQ.logger.warn "Warning: Option:#{key}, with value:#{val} is invalid and will be ignored"
|
212
330
|
end
|
213
331
|
end
|
332
|
+
|
333
|
+
@connection = @server_locator.createSessionFactory
|
334
|
+
# For handling managed sessions and consumers
|
335
|
+
@sessions = []
|
336
|
+
@consumers = []
|
214
337
|
end
|
215
338
|
|
216
|
-
# Return true if this connection was configured
|
339
|
+
# Return true if this connection was configured to use INVM transport protocol
|
217
340
|
def invm?
|
218
341
|
@is_invm
|
219
342
|
end
|
@@ -370,9 +493,9 @@ module HornetQ
|
|
370
493
|
end
|
371
494
|
end
|
372
495
|
|
373
|
-
# Create a session, start the session, call the supplied block
|
496
|
+
# Create a session, start the session, call the supplied block
|
374
497
|
# and once the block completes close the session.
|
375
|
-
#
|
498
|
+
#
|
376
499
|
# See: #session_create for the Parameters
|
377
500
|
#
|
378
501
|
# Returns the result of the block
|
@@ -417,7 +540,9 @@ module HornetQ
|
|
417
540
|
def close
|
418
541
|
@sessions.each { |session| session.close }
|
419
542
|
@connection.close if @connection
|
543
|
+
@server_locator.close if @server_locator
|
420
544
|
@connection = nil
|
545
|
+
@server_locator = nil
|
421
546
|
end
|
422
547
|
|
423
548
|
# Receive messages in a separate thread when they arrive
|
@@ -490,12 +615,12 @@ module HornetQ
|
|
490
615
|
def on_message_statistics
|
491
616
|
@consumers.collect{|consumer| consumer.on_message_statistics}
|
492
617
|
end
|
493
|
-
|
618
|
+
|
494
619
|
# Start all sessions managed by this connection
|
495
|
-
#
|
620
|
+
#
|
496
621
|
# Sessions created via #create_session are not managed unless
|
497
622
|
# :managed => true was specified when the session was created
|
498
|
-
#
|
623
|
+
#
|
499
624
|
# Session are Only managed when created through the following methods:
|
500
625
|
# Connection#on_message
|
501
626
|
# Connection#create_session And :managed => true
|
@@ -513,5 +638,5 @@ module HornetQ
|
|
513
638
|
@sessions.each {|session| session.stop}
|
514
639
|
end
|
515
640
|
end
|
516
|
-
end
|
641
|
+
end
|
517
642
|
end
|
@@ -284,17 +284,16 @@ module Java::org.hornetq.api.core.client::ClientSession
|
|
284
284
|
end
|
285
285
|
|
286
286
|
# To be consistent create Requestor from Session
|
287
|
-
def create_requestor(request_address)
|
288
|
-
|
289
|
-
HornetQ::Client::RequestorPattern.new(self, request_address)
|
287
|
+
def create_requestor(request_address, reply_address=nil, reply_queue=nil)
|
288
|
+
HornetQ::Client::RequestorPattern.new(self, request_address, reply_address, reply_queue)
|
290
289
|
end
|
291
290
|
|
292
291
|
# Creates a RequestorPattern to send a request and to synchronously wait for
|
293
292
|
# the reply, call the supplied block, then close the requestor
|
294
293
|
# Returns the result from the block
|
295
|
-
def requestor(request_address
|
294
|
+
def requestor(request_address, reply_address=nil, reply_queue=nil, &block)
|
296
295
|
begin
|
297
|
-
requestor = self.create_requestor(request_address)
|
296
|
+
requestor = self.create_requestor(request_address, reply_address, reply_queue)
|
298
297
|
block.call(requestor)
|
299
298
|
ensure
|
300
299
|
requestor.close if requestor
|
@@ -53,6 +53,12 @@
|
|
53
53
|
#
|
54
54
|
# long message_id()
|
55
55
|
# Returns the messageID
|
56
|
+
# This is an internal message id used by HornetQ itself, it cannot be
|
57
|
+
# set by the user.
|
58
|
+
# The message is only visible when consuming messages, when producing
|
59
|
+
# messages the message_id is Not returned to the caller
|
60
|
+
# Use user_id to carry user supplied message id's for correlating
|
61
|
+
# responses to requests
|
56
62
|
#
|
57
63
|
# byte priority()
|
58
64
|
# Returns the message priority.
|
@@ -136,14 +142,22 @@ class Java::OrgHornetqCoreClientImpl::ClientMessageImpl
|
|
136
142
|
# requestor = session.create_requestor('Request Queue')
|
137
143
|
#
|
138
144
|
def reply_to_address=(name)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
145
|
+
put_string_property(Java::OrgHornetqCoreClientImpl::ClientMessageImpl::REPLYTO_HEADER_NAME, HornetQ::as_simple_string(name))
|
146
|
+
end
|
147
|
+
|
148
|
+
# Generate a new user_id
|
149
|
+
#
|
150
|
+
# Sets the user_id to a newly generated id, using a UUID algorithm
|
151
|
+
#
|
152
|
+
# The user_id is similar to the message_id in other JMS based messaging systems
|
153
|
+
# in fact the HornetQ JMS API uses the user_id as the JMS Message ID.
|
154
|
+
#
|
155
|
+
# The internal message_id is set by the HornetQ Server and is Not returned
|
156
|
+
# when sending messages
|
157
|
+
#
|
158
|
+
# Returns generated user_id
|
159
|
+
def generate_user_id
|
160
|
+
self.user_id = Java::org.hornetq.utils::UUIDGenerator.instance.generateUUID
|
147
161
|
end
|
148
162
|
|
149
163
|
# Returns the message type as one of the following symbols
|
@@ -349,7 +363,7 @@ class Java::OrgHornetqCoreClientImpl::ClientMessageImpl
|
|
349
363
|
:priority => priority,
|
350
364
|
:timestamp => timestamp,
|
351
365
|
:type_sym => type_sym,
|
352
|
-
:user_id => user_id,
|
366
|
+
:user_id => user_id.nil? ? nil : user_id.to_s,
|
353
367
|
}
|
354
368
|
end
|
355
369
|
|
@@ -357,5 +371,5 @@ class Java::OrgHornetqCoreClientImpl::ClientMessageImpl
|
|
357
371
|
def inspect
|
358
372
|
"#{self.class.name}:\nBody: #{body.inspect}\nAttributes: #{attributes.inspect}\nProperties: #{properties.inspect}"
|
359
373
|
end
|
360
|
-
|
374
|
+
|
361
375
|
end
|
@@ -1,30 +1,111 @@
|
|
1
1
|
module HornetQ::Client
|
2
2
|
|
3
3
|
# Implements the Requestor Pattern
|
4
|
-
# Send a request to a server and wait for a reply
|
4
|
+
# Send a request to a server and wait for a reply
|
5
|
+
# Parameters
|
6
|
+
# * session
|
7
|
+
# The session to use processing this request
|
8
|
+
# Note: Sessions cannot be shared concurrently by multiple threads
|
9
|
+
# * request_address
|
10
|
+
# Address to send requests to.
|
11
|
+
# It is expected that process listening to requests at this address has
|
12
|
+
# implemented the ServerPattern
|
13
|
+
# * reply_address
|
14
|
+
# If supplied the reply_address must already exist and will be used for
|
15
|
+
# receiving responses
|
16
|
+
# If not supplied a temporary queue will be created and used by this instance
|
17
|
+
# of the RequestorPattern
|
18
|
+
# This optional parameter is normally not used
|
19
|
+
# * reply_queue
|
20
|
+
# If a reply_address is supplied, the reply_queue name can be supplied if it
|
21
|
+
# differs from reply_address
|
5
22
|
class RequestorPattern
|
6
|
-
def initialize(session, request_address)
|
23
|
+
def initialize(session, request_address, reply_address=nil, reply_queue=nil)
|
7
24
|
@session = session
|
8
25
|
@producer = session.create_producer(request_address)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
26
|
+
if reply_address
|
27
|
+
@reply_address = reply_address
|
28
|
+
@reply_queue = reply_queue || reply_address
|
29
|
+
@destroy_temp_queue = false
|
30
|
+
else
|
31
|
+
@reply_queue = @reply_address = "#{request_address}.#{Java::java.util::UUID.randomUUID.toString}"
|
32
|
+
begin
|
33
|
+
session.create_temporary_queue(@reply_address, @reply_queue)
|
34
|
+
@destroy_temp_queue = true
|
35
|
+
rescue NativeException => exc
|
36
|
+
p exc
|
37
|
+
end
|
14
38
|
end
|
15
|
-
@consumer = session.create_consumer(reply_queue)
|
16
39
|
end
|
17
|
-
|
40
|
+
|
41
|
+
# Synchronous Request and wait for reply
|
42
|
+
#
|
43
|
+
# Returns the message received, or nil if no message was received in the
|
44
|
+
# specified timeout.
|
45
|
+
#
|
46
|
+
# The supplied request_message is updated as follows
|
47
|
+
# * The property JMSReplyTo is set to the name of the reply to address
|
48
|
+
# * Creates and sets the message user_id if not already set
|
49
|
+
# * #TODO: The expiry is set to the message timeout if not already set
|
50
|
+
#
|
51
|
+
# Note:
|
52
|
+
# * The request will only look for a reply message with the same
|
53
|
+
# user_id (message id) as the message that was sent. This is critical
|
54
|
+
# since a previous receive may have timed out and we do not want
|
55
|
+
# to pickup the reponse to an earlier request
|
56
|
+
#
|
57
|
+
# To receive a message after a timeout, call wait_for_reply with a nil message
|
58
|
+
# id to receive any message on the queue
|
59
|
+
#
|
60
|
+
# Use: submit_request & then wait_for_reply to break it into
|
61
|
+
# two separate calls
|
18
62
|
def request(request_message, timeout)
|
19
|
-
|
63
|
+
#TODO set message expiry to timeout if not already set
|
64
|
+
message_id = submit_request(request_message)
|
65
|
+
wait_for_reply(message_id, timeout)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Asynchronous Request
|
69
|
+
# Use: submit_request & then wait_for_reply to break the request into
|
70
|
+
# two separate calls.
|
71
|
+
#
|
72
|
+
# For example, submit the request now, do some work, then later on
|
73
|
+
# in the same thread wait for the reply.
|
74
|
+
#
|
75
|
+
# The supplied request_message is updated as follows
|
76
|
+
# * The property JMSReplyTo is set to the name of the reply to address
|
77
|
+
# * Creates and sets the message user_id if not already set
|
78
|
+
# * #TODO: The expiry is set to the message timeout if not already set
|
79
|
+
#
|
80
|
+
# Returns Message id of the message that was sent
|
81
|
+
def submit_request(request_message)
|
82
|
+
request_message.reply_to_address = @reply_address
|
83
|
+
request_message.generate_user_id unless request_message.user_id
|
20
84
|
@producer.send(request_message)
|
21
|
-
|
85
|
+
request_message.user_id
|
86
|
+
end
|
87
|
+
|
88
|
+
# Asynchronous wait for reply
|
89
|
+
#
|
90
|
+
# Parameters:
|
91
|
+
# user_id: the user defined id to correlate a response for
|
92
|
+
#
|
93
|
+
# Supply a nil user_id to receive any message from the queue
|
94
|
+
#
|
95
|
+
# Returns the message received
|
96
|
+
#
|
97
|
+
# Note: Call submit_request before calling this method
|
98
|
+
def wait_for_reply(user_id, timeout)
|
99
|
+
# We only want the reply to the supplied message_id, so set filter on message id
|
100
|
+
filter = "#{Java::org.hornetq.api.core::FilterConstants::HORNETQ_USERID} = 'ID:#{user_id}'" if user_id
|
101
|
+
@session.consumer(:queue_name => @reply_queue, :filter=>filter) do |consumer|
|
102
|
+
consumer.receive(timeout)
|
103
|
+
end
|
22
104
|
end
|
23
105
|
|
24
106
|
def close
|
107
|
+
@session.delete_queue(@reply_queue) if @destroy_temp_queue
|
25
108
|
@producer.close if @producer
|
26
|
-
@consumer.close if @consumer
|
27
|
-
@session.delete_queue(@consumer.queue_name)
|
28
109
|
end
|
29
110
|
end
|
30
111
|
|
@@ -35,6 +35,7 @@ module HornetQ::Client
|
|
35
35
|
reply_message.durable = request_message.durable?
|
36
36
|
# Send request message id back in reply message for correlation purposes
|
37
37
|
reply_message.user_id = request_message.user_id
|
38
|
+
#TODO: Also need to include other attributes such as Expiry
|
38
39
|
# Send to Reply to address supplied by the caller
|
39
40
|
@producer.send(request_message.reply_to_address, reply_message)
|
40
41
|
#puts "Sent reply to #{reply_to.to_s}: #{reply_message.inspect}"
|
Binary file
|
Binary file
|
data/lib/hornetq/java/netty.jar
CHANGED
Binary file
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: jruby-hornetq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Reid Morrison
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
14
|
+
date: 2011-04-01 00:00:00 -04:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- examples/advanced/server.rb
|
60
60
|
- examples/client-server/client.rb
|
61
61
|
- examples/client-server/server.rb
|
62
|
+
- examples/producer-consumer/browse_all.rb
|
62
63
|
- examples/producer-consumer/consume_all.rb
|
63
64
|
- examples/producer-consumer/consume_on_message.rb
|
64
65
|
- examples/producer-consumer/consumer.rb
|