jruby-jms 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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