jruby-jms 0.9.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.
@@ -0,0 +1,91 @@
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.MapMessage
18
+ module javax.jms::MapMessage
19
+ # Since each is defined, add support for: inject, map, include?, and find_all?
20
+ # <=> also allows support for: min, max, and sort
21
+ include Enumerable
22
+
23
+ # Return Map Message as a hash
24
+ def to_h
25
+ h = {}
26
+ each_pair {|key, value| h[key] = value}
27
+ h
28
+ end
29
+
30
+ # Return Map Message as a hash
31
+ def data
32
+ to_h
33
+ end
34
+
35
+ # Copy values from supplied hash into this MapMessage
36
+ # Converts Ruby types to Java native Data types as follows:
37
+ # Fixnum => long
38
+ # Float => double
39
+ # Bignum => long
40
+ # true => boolean
41
+ # false => boolean
42
+ # nil => null
43
+ # Otherwise it calls ::to_s on the supplied data type
44
+ def data=(data)
45
+ data.each_pair do |key,val|
46
+ case
47
+ when val.class == Fixnum # 1
48
+ setLong(key.to_s,val)
49
+ when val.class == Float #1.1
50
+ setDouble(key.to_s,val)
51
+ when val.class == Bignum # 11111111111111111
52
+ setLong(key.to_s,val)
53
+ when (val.class == TrueClass) || (val.class == FalseClass)
54
+ setBoolean(key.to_s,val)
55
+ when val.class == NilClass
56
+ setObject(key.to_s,val)
57
+ else
58
+ setString(key.to_s,val.to_s)
59
+ end
60
+ end
61
+ end
62
+
63
+ # Return each name value pair
64
+ def each(&proc)
65
+ # When key and value are expected separately. Should actually be calling each_pair anyway
66
+ if proc.arity == 2
67
+ each_pair(proc)
68
+ else
69
+ enum = getMapNames
70
+ while enum.has_more_elements
71
+ key = enum.next_element
72
+ proc.call [key, getObject(key)]
73
+ end
74
+ end
75
+ end
76
+
77
+ # Return each name value pair
78
+ def each_pair(&proc)
79
+ enum = getMapNames
80
+ while enum.has_more_elements
81
+ key = enum.next_element
82
+ proc.call key, getObject(key)
83
+ end
84
+ end
85
+
86
+ # Does map include specified key
87
+ def include?(key)
88
+ # Ensure a Ruby true is returned
89
+ item_exists key == true
90
+ end
91
+ end
@@ -0,0 +1,264 @@
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
+ # Extend JMS Message Interface with Ruby methods
18
+ #
19
+ # A Message is the item that can be put on a queue, or obtained from a queue.
20
+ #
21
+ # A Message consists of 3 major parts:
22
+ # - Header
23
+ # Accessible as attributes of the Message class
24
+ # - Properties
25
+ # Accessible via [] and []= methods
26
+ # - Data
27
+ # The actual data portion of the message
28
+ # See the specific message types for details on how to access the data
29
+ # portion of the message
30
+ #
31
+ # For further help on javax.jms.Message
32
+ # http://download.oracle.com/javaee/6/api/index.html?javax/jms/Message.html
33
+ #
34
+ # Interface javax.jms.Message
35
+ module javax.jms::Message
36
+
37
+ # Methods directly exposed from the Java class:
38
+
39
+ # call-seq:
40
+ # acknowledge
41
+ #
42
+ # Acknowledges all consumed messages of the session of this consumed message
43
+ #
44
+
45
+ # call-seq:
46
+ # clear_body
47
+ #
48
+ # Clears out the message body
49
+ #
50
+
51
+ # call-seq:
52
+ # clear_properties
53
+ #
54
+ # Clears out the properties of this message
55
+ #
56
+
57
+ # Header Fields - Attributes of the message
58
+
59
+ # Return the JMS Delivery Mode as a symbol
60
+ # :peristent
61
+ # :non_peristent
62
+ # other: Value from javax.jms.DeliveryMode
63
+ def jms_delivery_mode
64
+ case getJMSDeliveryMode
65
+ when javax.jms.DeliveryMode::PERSISTENT
66
+ :peristent
67
+ when javax.jms.DeliveryMode::NON_PERSISTENT
68
+ :non_peristent
69
+ else
70
+ getJMSDeliveryMode
71
+ end
72
+ end
73
+
74
+ # Set the JMS Delivery Mode
75
+ # Valid values for mode
76
+ # :peristent
77
+ # :non_peristent
78
+ # other: Any constant from javax.jms.DeliveryMode
79
+ def jms_delivery_mode=(mode)
80
+ val = case mode
81
+ when :peristent
82
+ javax.jms.DeliveryMode::PERSISTENT
83
+ when :non_peristent
84
+ javax.jms.DeliveryMode::NON_PERSISTENT
85
+ else
86
+ mode
87
+ end
88
+ self.setJMSDeliveryMode(val)
89
+ end
90
+
91
+ # Is the message persistent?
92
+ def persistent?
93
+ getJMSDeliveryMode == javax.jms.DeliveryMode::PERSISTENT
94
+ end
95
+
96
+ # Returns the Message correlation ID as a String
97
+ # The resulting string may contain nulls
98
+ def jms_correlation_id
99
+ String.from_java_bytes(getJMSCorrelationIDAsBytes) if getJMSCorrelationIDAsBytes
100
+ end
101
+
102
+ # Set the Message correlation ID
103
+ # correlation_id: String
104
+ # Also supports embedded nulls within the correlation id
105
+ def jms_correlation_id=(correlation_id)
106
+ setJMSCorrelationIDAsBytes(correlation_id.nil? ? nil : correlation_id.to_java_bytes)
107
+ end
108
+
109
+ # Returns the Message Destination
110
+ # Instance of javax.jms.Destination
111
+ def jms_destination
112
+ getJMSDestination
113
+ end
114
+
115
+ # Set the Message Destination
116
+ # jms_destination: Must be an instance of javax.jms.Destination
117
+ def jms_destination=(destination)
118
+ setJMSDestination(destination)
119
+ end
120
+
121
+ # Return the message expiration value as an Integer
122
+ def jms_expiration
123
+ getJMSExpiration
124
+ end
125
+
126
+ # Set the Message expiration value
127
+ # expiration: Integer
128
+ def jms_expiration=(expiration)
129
+ setJMSExpiration(expiration)
130
+ end
131
+
132
+ # Returns the Message ID as a String
133
+ # The resulting string may contain embedded nulls
134
+ def jms_message_id
135
+ getJMSMessageID
136
+ end
137
+
138
+ # Set the Message correlation ID
139
+ # message_id: String
140
+ # Also supports nulls within the message id
141
+ def jms_message_id=(message_id)
142
+ setJMSMessageID(message_id)
143
+ end
144
+
145
+ # Returns the Message Priority level as an Integer
146
+ def jms_priority
147
+ getJMSPriority
148
+ end
149
+
150
+ # Set the Message priority level
151
+ # priority: Integer
152
+ def jms_priority=(priority)
153
+ setJMSPriority(priority)
154
+ end
155
+
156
+ # Indicates whether the Message was redelivered?
157
+ def jms_redelivered?
158
+ getJMSRedelivered
159
+ end
160
+
161
+ # Set whether the Message was redelivered
162
+ # bool: Boolean
163
+ def jms_redelivered=(bool)
164
+ setJMSPriority(bool)
165
+ end
166
+
167
+ # Returns the Message reply to Destination
168
+ # Instance of javax.jms.Destination
169
+ def jms_reply_to
170
+ getJMSReplyTo
171
+ end
172
+
173
+ # Set the Message reply to Destination
174
+ # reply_to: Must be an instance of javax.jms.Destination
175
+ def jms_reply_to=(reply_to)
176
+ setJMSReplyTo(reply_to)
177
+ end
178
+
179
+ # Returns the Message timestamp as Java Timestamp Integer
180
+ #TODO Return Ruby Time object?
181
+ def jms_timestamp
182
+ getJMSTimestamp
183
+ end
184
+
185
+ # Set the Message reply to Destination
186
+ # timestamp: Must be an Java Timestamp Integer
187
+ #TODO Support Ruby Time
188
+ def jms_timestamp=(timestamp)
189
+ setJMSTimestamp(timestamp)
190
+ end
191
+
192
+ # Returns the Message type supplied by the client when the message was sent
193
+ def jms_type
194
+ getJMSType
195
+ end
196
+
197
+ # Sets the Message type
198
+ # type: String
199
+ def jms_type=(type)
200
+ setJMSType(type)
201
+ end
202
+
203
+ # Return the attributes (header fields) of the message as a Hash
204
+ def attributes
205
+ {
206
+ :jms_correlation_id => jms_correlation_id,
207
+ :jms_delivery_mode => jms_delivery_mode,
208
+ :jms_destination => jms_destination,
209
+ :jms_expiration => jms_expiration,
210
+ :jms_message_id => jms_message_id,
211
+ :jms_priority => jms_priority,
212
+ :jms_redelivered => jms_redelivered?,
213
+ :jms_reply_to => jms_reply_to,
214
+ :jms_timestamp => jms_timestamp,
215
+ :jms_type => jms_type,
216
+ }
217
+ end
218
+
219
+ # Methods for manipulating the message properties
220
+
221
+ # Get the value of a property
222
+ def [](key)
223
+ getObjectProperty key.to_s
224
+ end
225
+
226
+ # Set a property
227
+ def []=(key, value)
228
+ setObjectProperty(key.to_s, value)
229
+ end
230
+
231
+ # Does message include specified property?
232
+ def include?(key)
233
+ # Ensure a Ruby true is returned
234
+ property_exists key == true
235
+ end
236
+
237
+ # Return Properties as a hash
238
+ def properties
239
+ h = {}
240
+ properties_each_pair {|k,v| h[k]=v}
241
+ h
242
+ end
243
+
244
+ # Set Properties from an existing hash
245
+ def properties=(h)
246
+ clear_properties
247
+ h.each_pair {|k,v| setObjectProperty(k.to_s, v)}
248
+ h
249
+ end
250
+
251
+ # Return each name value pair
252
+ def properties_each_pair(&proc)
253
+ enum = getPropertyNames
254
+ while enum.has_more_elements
255
+ key = enum.next_element
256
+ proc.call key, getObjectProperty(key)
257
+ end
258
+ end
259
+
260
+ def inspect
261
+ "#{self.class.name}: #{data}\nAttributes: #{attributes.inspect}\nProperties: #{properties.inspect}"
262
+ end
263
+
264
+ end
@@ -0,0 +1,114 @@
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
+ module javax.jms::MessageConsumer
18
+ # Obtain a message from the Destination or Topic
19
+ # In JMS terms, the message is received from the Destination
20
+ # :timeout follows the rules for MQSeries:
21
+ # -1 : Wait forever
22
+ # 0 : Return immediately if no message is available
23
+ # x : Wait for x milli-seconds for a message to be received from the broker
24
+ # Note: Messages may still be on the queue, but the broker has not supplied any messages
25
+ # in the time interval specified
26
+ # Default: 0
27
+ def get(parms={})
28
+ timeout = parms[:timeout] || 0
29
+ if timeout == -1
30
+ self.receive
31
+ elsif timeout == 0
32
+ self.receiveNoWait
33
+ else
34
+ self.receive(timeout)
35
+ end
36
+ end
37
+
38
+ # For each message available to be consumed call the Proc supplied
39
+ # Returns the statistics gathered when :statistics => true, otherwise nil
40
+ #
41
+ # Parameters:
42
+ # :timeout How to timeout waiting for messages on the Queue or Topic
43
+ # -1 : Wait forever
44
+ # 0 : Return immediately if no message is available
45
+ # x : Wait for x milli-seconds for a message to be received from the broker
46
+ # Note: Messages may still be on the queue, but the broker has not supplied any messages
47
+ # in the time interval specified
48
+ # Default: 0
49
+ #
50
+ # :statistics Capture statistics on how many messages have been read
51
+ # true : This method will capture statistics on the number of messages received
52
+ # and the time it took to process them.
53
+ # The statistics can be reset by calling MessageConsumer::each again
54
+ # with :statistics => true
55
+ #
56
+ # The statistics gathered are returned when :statistics => true and :async => false
57
+ def each(parms={}, &proc)
58
+ raise "Destination::each requires a code block to be executed for each message received" unless proc
59
+
60
+ message_count = nil
61
+ start_time = nil
62
+
63
+ if parms[:statistics]
64
+ message_count = 0
65
+ start_time = Time.now
66
+ end
67
+
68
+ # Receive messages according to timeout
69
+ while message = self.get(parms) do
70
+ proc.call(message)
71
+ message_count += 1 if message_count
72
+ end
73
+
74
+ unless message_count.nil?
75
+ duration = Time.now - start_time
76
+ {:messages => message_count,
77
+ :duration => duration,
78
+ :messages_per_second => (message_count/duration).to_i}
79
+ end
80
+ end
81
+
82
+ # Receive messages in a separate thread when they arrive
83
+ # Allows messages to be recieved in a separate thread. I.e. Asynchronously
84
+ # This method will return to the caller before messages are processed.
85
+ # It is then the callers responsibility to keep the program active so that messages
86
+ # can then be processed.
87
+ #
88
+ # Parameters:
89
+ # :statistics Capture statistics on how many messages have been read
90
+ # true : This method will capture statistics on the number of messages received
91
+ # and the time it took to process them.
92
+ # The timer starts when each() is called and finishes when either the last message was received,
93
+ # or when Destination::statistics is called. In this case MessageConsumer::statistics
94
+ # can be called several times during processing without affecting the end time.
95
+ # Also, the start time and message count is not reset until MessageConsumer::each
96
+ # is called again with :statistics => true
97
+ #
98
+ # The statistics gathered are returned when :statistics => true and :async => false
99
+ #
100
+ def on_message(parms={}, &proc)
101
+ raise "MessageConsumer::on_message requires a code block to be executed for each message received" unless proc
102
+
103
+ @listener = JMS::MessageListener.new(parms,&proc)
104
+ self.setMessageListener @listener
105
+ end
106
+
107
+ # Return the current statistics for a running MessageConsumer::on_message
108
+ def on_message_statistics
109
+ stats = @listener.statistics if @listener
110
+ raise "First call MessageConsumer::on_message with :statistics=>true before calling MessageConsumer::statistics()" unless stats
111
+ stats
112
+ end
113
+
114
+ end