jruby-hornetq 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|