jruby-jms 1.1.0-java

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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +36 -0
  4. data/HISTORY.md +52 -0
  5. data/LICENSE.txt +201 -0
  6. data/README.md +205 -0
  7. data/Rakefile +30 -0
  8. data/examples/advanced/session_pool.rb +37 -0
  9. data/examples/client-server/replier.rb +29 -0
  10. data/examples/client-server/requestor.rb +40 -0
  11. data/examples/file-to-q/files_to_q.rb +51 -0
  12. data/examples/file-to-q/q_to_files.rb +44 -0
  13. data/examples/invm/invm.rb +44 -0
  14. data/examples/invm/log4j.properties +58 -0
  15. data/examples/jms.yml +149 -0
  16. data/examples/performance/consumer.rb +25 -0
  17. data/examples/performance/producer.rb +31 -0
  18. data/examples/producer-consumer/browser.rb +24 -0
  19. data/examples/producer-consumer/consumer.rb +24 -0
  20. data/examples/producer-consumer/consumer_async.rb +41 -0
  21. data/examples/producer-consumer/producer.rb +25 -0
  22. data/examples/publish-subscribe/publish.rb +24 -0
  23. data/examples/publish-subscribe/subscribe.rb +31 -0
  24. data/lib/jms.rb +20 -0
  25. data/lib/jms/bytes_message.rb +52 -0
  26. data/lib/jms/connection.rb +529 -0
  27. data/lib/jms/imports.rb +21 -0
  28. data/lib/jms/logging.rb +50 -0
  29. data/lib/jms/map_message.rb +91 -0
  30. data/lib/jms/message.rb +285 -0
  31. data/lib/jms/message_consumer.rb +117 -0
  32. data/lib/jms/message_listener_impl.rb +79 -0
  33. data/lib/jms/message_producer.rb +59 -0
  34. data/lib/jms/mq_workaround.rb +70 -0
  35. data/lib/jms/object_message.rb +26 -0
  36. data/lib/jms/oracle_a_q_connection_factory.rb +48 -0
  37. data/lib/jms/queue_browser.rb +28 -0
  38. data/lib/jms/session.rb +473 -0
  39. data/lib/jms/session_pool.rb +168 -0
  40. data/lib/jms/text_message.rb +31 -0
  41. data/lib/jms/version.rb +3 -0
  42. data/nbproject/private/private.properties +3 -0
  43. data/nbproject/private/rake-d.txt +5 -0
  44. data/parallel_minion.gemspec +21 -0
  45. data/test/connection_test.rb +160 -0
  46. data/test/jms.yml +111 -0
  47. data/test/log4j.properties +32 -0
  48. data/test/message_test.rb +130 -0
  49. data/test/session_pool_test.rb +86 -0
  50. data/test/session_test.rb +140 -0
  51. metadata +113 -0
@@ -0,0 +1,117 @@
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.MessageConsumer
18
+ module JMS::MessageConsumer
19
+ # Obtain a message from the Destination or Topic
20
+ # In JMS terms, the message is received from the Destination
21
+ # :timeout follows the rules for MQSeries:
22
+ # -1 : Wait forever
23
+ # 0 : Return immediately if no message is available
24
+ # x : Wait for x milli-seconds for a message to be received from the broker
25
+ # Note: Messages may still be on the queue, but the broker has not supplied any messages
26
+ # in the time interval specified
27
+ # Default: 0
28
+ def get(params={})
29
+ timeout = params[:timeout] || 0
30
+ if timeout == -1
31
+ self.receive
32
+ elsif timeout == 0
33
+ self.receiveNoWait
34
+ else
35
+ self.receive(timeout)
36
+ end
37
+ end
38
+
39
+ # For each message available to be consumed call the Proc supplied
40
+ # Returns the statistics gathered when :statistics => true, otherwise nil
41
+ #
42
+ # Parameters:
43
+ # :timeout How to timeout waiting for messages on the Queue or Topic
44
+ # -1 : Wait forever
45
+ # 0 : Return immediately if no message is available
46
+ # x : Wait for x milli-seconds for a message to be received from the broker
47
+ # Note: Messages may still be on the queue, but the broker has not supplied any messages
48
+ # in the time interval specified
49
+ # Default: 0
50
+ #
51
+ # :statistics Capture statistics on how many messages have been read
52
+ # true : This method will capture statistics on the number of messages received
53
+ # and the time it took to process them.
54
+ # The statistics can be reset by calling MessageConsumer::each again
55
+ # with :statistics => true
56
+ #
57
+ # The statistics gathered are returned when :statistics => true and :async => false
58
+ def each(params={}, &proc)
59
+ raise "Destination::each requires a code block to be executed for each message received" unless proc
60
+
61
+ message_count = nil
62
+ start_time = nil
63
+
64
+ if params[:statistics]
65
+ message_count = 0
66
+ start_time = Time.now
67
+ end
68
+
69
+ # Receive messages according to timeout
70
+ while message = self.get(params) do
71
+ proc.call(message)
72
+ message_count += 1 if message_count
73
+ end
74
+
75
+ unless message_count.nil?
76
+ duration = Time.now - start_time
77
+ {:messages => message_count,
78
+ :duration => duration,
79
+ :messages_per_second => duration > 0 ? (message_count/duration).to_i : 0,
80
+ :ms_per_msg => message_count > 0 ? (duration*1000.0)/message_count : 0
81
+ }
82
+ end
83
+ end
84
+
85
+ # Receive messages in a separate thread when they arrive
86
+ # Allows messages to be recieved in a separate thread. I.e. Asynchronously
87
+ # This method will return to the caller before messages are processed.
88
+ # It is then the callers responsibility to keep the program active so that messages
89
+ # can then be processed.
90
+ #
91
+ # Parameters:
92
+ # :statistics Capture statistics on how many messages have been read
93
+ # true : This method will capture statistics on the number of messages received
94
+ # and the time it took to process them.
95
+ # The timer starts when each() is called and finishes when either the last message was received,
96
+ # or when Destination::statistics is called. In this case MessageConsumer::statistics
97
+ # can be called several times during processing without affecting the end time.
98
+ # Also, the start time and message count is not reset until MessageConsumer::each
99
+ # is called again with :statistics => true
100
+ #
101
+ # The statistics gathered are returned when :statistics => true and :async => false
102
+ #
103
+ def on_message(params={}, &proc)
104
+ raise "MessageConsumer::on_message requires a code block to be executed for each message received" unless proc
105
+
106
+ @listener = JMS::MessageListenerImpl.new(params,&proc)
107
+ self.setMessageListener @listener
108
+ end
109
+
110
+ # Return the current statistics for a running MessageConsumer::on_message
111
+ def on_message_statistics
112
+ stats = @listener.statistics if @listener
113
+ raise "First call MessageConsumer::on_message with :statistics=>true before calling MessageConsumer::statistics()" unless stats
114
+ stats
115
+ end
116
+
117
+ end
@@ -0,0 +1,79 @@
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 JMS
18
+
19
+ private
20
+ # For internal use only by JMS::Connection
21
+ class MessageListenerImpl
22
+ include JMS::MessageListener
23
+
24
+ # Parameters:
25
+ # :statistics Capture statistics on how many messages have been read
26
+ # true : This method will capture statistics on the number of messages received
27
+ # and the time it took to process them.
28
+ # The timer starts when the listener instance is created and finishes when either the last message was received,
29
+ # or when Destination::statistics is called. In this case MessageConsumer::statistics
30
+ # can be called several times during processing without affecting the end time.
31
+ # Also, the start time and message count is not reset until MessageConsumer::each
32
+ # is called again with :statistics => true
33
+ #
34
+ # The statistics gathered are returned when :statistics => true and :async => false
35
+ def initialize(params={}, &proc)
36
+ @proc = proc
37
+
38
+ if params[:statistics]
39
+ @message_count = 0
40
+ @start_time = Time.now
41
+ end
42
+ end
43
+
44
+ # Method called for every message received on the queue
45
+ # Per the JMS specification, this method will be called sequentially for each message on the queue.
46
+ # This method will not be called again until its prior invocation has completed.
47
+ # Must be onMessage() since on_message() does not work for interface methods that must be implemented
48
+ def onMessage(message)
49
+ begin
50
+ if @message_count
51
+ @message_count += 1
52
+ @last_time = Time.now
53
+ end
54
+ @proc.call message
55
+ rescue SyntaxError, NameError => boom
56
+ JMS::logger.error "Unhandled Exception processing JMS Message. Doesn't compile: " + boom
57
+ JMS::logger.error "Ignoring poison message:\n#{message.inspect}"
58
+ JMS::logger.error boom.backtrace.join("\n")
59
+ rescue StandardError => bang
60
+ JMS::logger.error "Unhandled Exception processing JMS Message. Doesn't compile: " + bang
61
+ JMS::logger.error "Ignoring poison message:\n#{message.inspect}"
62
+ JMS::logger.error bang.backtrace.join("\n")
63
+ rescue => exc
64
+ JMS::logger.error "Unhandled Exception processing JMS Message. Exception occurred:\n#{exc}"
65
+ JMS::logger.error "Ignoring poison message:\n#{message.inspect}"
66
+ JMS::logger.error exc.backtrace.join("\n")
67
+ end
68
+ end
69
+
70
+ # Return Statistics gathered for this listener
71
+ def statistics
72
+ raise "First call MessageConsumer::on_message with :statistics=>true before calling MessageConsumer::statistics()" unless @message_count
73
+ duration =(@last_time || Time.now) - @start_time
74
+ {:messages => @message_count,
75
+ :duration => duration,
76
+ :messages_per_second => (@message_count/duration).to_i}
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,59 @@
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 Producer Interface with Ruby methods
18
+ #
19
+ # For further help on javax.jms.MessageProducer
20
+ # http://download.oracle.com/javaee/6/api/javax/jms/MessageProducer.html
21
+ #
22
+ # Interface javax.jms.Producer
23
+ module JMS::MessageProducer
24
+
25
+ # Return the Delivery Mode as a Ruby symbol
26
+ # :persistent
27
+ # :non_persistent
28
+ # nil if unknown
29
+ def delivery_mode_sym
30
+ case delivery_mode
31
+ when JMS::DeliveryMode::PERSISTENT
32
+ :persistent
33
+ when JMS::DeliveryMode::NON_PERSISTENT
34
+ :non_persistent
35
+ else
36
+ nil
37
+ end
38
+ end
39
+
40
+ # Set the JMS Delivery Mode from a Ruby Symbol
41
+ # Valid values for mode
42
+ # :persistent
43
+ # :non_persistent
44
+ #
45
+ # Example:
46
+ # producer.delivery_mode_sym = :persistent
47
+ def delivery_mode_sym=(mode)
48
+ val = case mode
49
+ when :persistent
50
+ JMS::DeliveryMode::PERSISTENT
51
+ when :non_persistent
52
+ JMS::DeliveryMode::NON_PERSISTENT
53
+ else
54
+ raise "Unknown delivery mode symbol: #{mode}"
55
+ end
56
+ self.delivery_mode = val
57
+ end
58
+
59
+ end
@@ -0,0 +1,70 @@
1
+ # Workaround for IBM MQ JMS implementation that implements some undocumented methods
2
+
3
+ begin
4
+
5
+ class com.ibm.mq.jms::MQQueueSession
6
+
7
+ if self.instance_methods.include? "consume"
8
+ def consume(params, &proc)
9
+ Java::JavaxJms::Session.instance_method(:consume).bind(self).call(params, &proc)
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+
16
+ class com.ibm.mq.jms::MQSession
17
+
18
+ if self.instance_methods.include? "consume"
19
+ def consume(params, &proc)
20
+ Java::JavaxJms::Session.instance_method(:consume).bind(self).call(params, &proc)
21
+ end
22
+ end
23
+
24
+ if self.instance_methods.include? "create_destination"
25
+ def create_destination(params)
26
+ Java::JavaxJms::Session.instance_method(:create_destination).bind(self).call(params)
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+
33
+ class com.ibm.mq.jms::MQQueueBrowser
34
+
35
+ if self.instance_methods.include? "each"
36
+ def each(params, &proc)
37
+ Java::ComIbmMsgClientJms::JmsQueueBrowser.instance_method(:each).bind(self).call(params, &proc)
38
+ end
39
+ end
40
+ end
41
+
42
+
43
+ class com.ibm.mq.jms::MQQueueReceiver
44
+
45
+ if self.instance_methods.include? "each"
46
+ def each(params, &proc)
47
+ Java::JavaxJms::MessageConsumer.instance_method(:each).bind(self).call(params, &proc)
48
+ end
49
+ end
50
+
51
+ if self.instance_methods.include? "get"
52
+ def get(params={})
53
+ Java::JavaxJms::MessageConsumer.instance_method(:get).bind(self).call(params)
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+
60
+ class com.ibm.mq.jms::MQQueue
61
+
62
+ if self.instance_methods.include? "delete"
63
+ undef_method :delete
64
+ end
65
+
66
+ end
67
+
68
+ rescue NameError
69
+ # Ignore errors (when we aren't using MQ)
70
+ end
@@ -0,0 +1,26 @@
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.ObjectMessage
18
+ module JMS::ObjectMessage
19
+ def data
20
+ getObject
21
+ end
22
+
23
+ def data(val)
24
+ setObject(val)
25
+ end
26
+ end
@@ -0,0 +1,48 @@
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 JMS
18
+ # Full Qualified name causes a Java exception
19
+ java_import 'oracle.jms.AQjmsFactory'
20
+
21
+ # Connection Factory to support Oracle AQ
22
+ class OracleAQConnectionFactory
23
+ attr_accessor :username, :url
24
+ #attr_writer :password
25
+ attr_accessor :password
26
+
27
+ # Creates a connection per standard JMS 1.1 techniques from the Oracle AQ JMS Interface
28
+ def create_connection(*args)
29
+ # Since username and password are not assigned (see lib/jms/connection.rb:200)
30
+ # and connection_factory.create_connection expects 2 arguments when username is not null ...
31
+ if args.length == 2
32
+ @username = args[0]
33
+ @password = args[1]
34
+ end
35
+
36
+ # Full Qualified name causes a Java exception
37
+ #cf = oracle.jms.AQjmsFactory.getConnectionFactory(@url, java.util.Properties.new)
38
+ cf = AQjmsFactory.getConnectionFactory(@url, java.util.Properties.new)
39
+
40
+ if username
41
+ cf.createConnection(@username, @password)
42
+ else
43
+ cf.createConnection()
44
+ end
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,28 @@
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.QueueBrowser
18
+ module JMS::QueueBrowser
19
+ # For each message on the queue call the supplied Proc
20
+ def each(params={}, &block)
21
+ raise "JMS::QueueBrowser::each requires a code block to be executed for each message received" unless block
22
+
23
+ e = self.getEnumeration
24
+ while e.hasMoreElements
25
+ block.call(e.nextElement)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,473 @@
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
+ # For each thread that will be processing messages concurrently a separate
18
+ # session is required. All sessions can share a single connection to the same
19
+ # JMS Provider.
20
+ #
21
+ # Interface javax.jms.Session
22
+ #
23
+ # See: http://download.oracle.com/javaee/6/api/javax/jms/Session.html
24
+ #
25
+ # Other methods still directly accessible through this class:
26
+ #
27
+ # create_browser(queue, message_selector)
28
+ # Creates a QueueBrowser object to peek at the messages on the specified queue using a message selector.
29
+ #
30
+ # create_bytes_message()
31
+ # Creates a BytesMessage object
32
+ #
33
+ # create_consumer(destination)
34
+ # Creates a MessageConsumer for the specified destination
35
+ # See: Connection::consumer
36
+ #
37
+ # Example:
38
+ # destination = session.create_destination(:queue_name => "MyQueue")
39
+ # session.create_consumer(destination)
40
+ #
41
+ # create_consumer(destination, message_selector)
42
+ # Creates a MessageConsumer for the specified destination, using a message selector
43
+ #
44
+ # create_consumer(destination, message_selector, boolean NoLocal)
45
+ # Creates MessageConsumer for the specified destination, using a message selector
46
+ #
47
+ # create_durable_subscriber(Topic topic, java.lang.String name)
48
+ # Creates a durable subscriber to the specified topic
49
+ #
50
+ # create_durable_subscriber(Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal)
51
+ # Creates a durable subscriber to the specified topic, using a message selector and specifying whether messages published by its own connection should be delivered to it.
52
+ #
53
+ # create_map_Message()
54
+ # Creates a MapMessage object
55
+ #
56
+ # create_message()
57
+ # Creates a Message object
58
+ #
59
+ # create_object_message()
60
+ # Creates an ObjectMessage object
61
+ #
62
+ # create_object_message(java.io.Serializable object)
63
+ # Creates an initialized ObjectMessage object
64
+ #
65
+ # create_producer(destination)
66
+ # Creates a MessageProducer to send messages to the specified destination
67
+ #
68
+ # create_queue(queue_name)
69
+ # Creates a queue identity given a Queue name
70
+ #
71
+ # create_stream_message()
72
+ # Creates a StreamMessage object
73
+ #
74
+ # create_temporary_queue()
75
+ # Creates a TemporaryQueue object
76
+ #
77
+ # create_temporary_topic()
78
+ # Creates a TemporaryTopic object
79
+ #
80
+ # create_text_message()
81
+ # Creates a TextMessage object
82
+ #
83
+ # create_text_message(text)
84
+ # Creates an initialized TextMessage object
85
+ #
86
+ # create_topic(topic_name)
87
+ # Creates a topic identity given a Topic name
88
+ #
89
+ # acknowledge_mode()
90
+ # Returns the acknowledgement mode of the session
91
+ #
92
+ # message_listener()
93
+ # Returns the session's distinguished message listener (optional).
94
+ #
95
+ # transacted?
96
+ # Indicates whether the session is in transacted mode
97
+ #
98
+ # recover()
99
+ # Stops message delivery in this session, and restarts message delivery with the oldest unacknowledged message
100
+ #
101
+ # rollback()
102
+ # Rolls back any messages done in this transaction and releases any locks currently held
103
+ #
104
+ # message_listener=(MessageListener listener)
105
+ # Sets the session's distinguished message listener (optional)
106
+ #
107
+ # unsubscribe(name)
108
+ # Unsubscribes a durable subscription that has been created by a client
109
+ #
110
+ # Interface javax.jms.Session
111
+ module JMS::Session
112
+ # Create a new message instance based on the type of the data being supplied
113
+ # String (:to_str) => TextMessage
114
+ # Hash (:each_pair) => MapMessage
115
+ # Duck typing is used to determine the type. If the class responds
116
+ # to :to_str then it is considered a String. Similarly if it responds to
117
+ # :each_pair it is considered to be a Hash
118
+ #
119
+ # If automated duck typing is not desired, the type of the message can be specified
120
+ # by setting the parameter 'type' to any one of:
121
+ # :text => Creates a Text Message
122
+ # :map => Creates a Map Message
123
+ # :bytes => Creates a Bytes Message
124
+ def message(data, type=nil)
125
+ jms_message = nil
126
+ type ||= if data.respond_to?(:to_str, false)
127
+ :text
128
+ elsif data.respond_to?(:each_pair, false)
129
+ :map
130
+ else
131
+ raise "Unknown data type #{data.class.to_s} in Message"
132
+ end
133
+
134
+ case type
135
+ when :text
136
+ jms_message = self.createTextMessage
137
+ jms_message.text = data.to_str
138
+ when :map
139
+ jms_message = self.createMapMessage
140
+ jms_message.data = data
141
+ when :bytes
142
+ jms_message = self.createBytesMessage
143
+ jms_message.write_bytes(data.to_java_bytes)
144
+ else
145
+ raise "Invalid type #{type} requested"
146
+ end
147
+ jms_message
148
+ end
149
+
150
+ # Create the destination based on the parameter supplied
151
+ #
152
+ # The idea behind this method is to allow the decision as to whether
153
+ # one is sending to a topic or destination to be transparent to the code.
154
+ # The supplied parameters can be externalized into say a YAML file
155
+ # so that today it writes to a queue, later it can be changed to write
156
+ # to a topic so that multiple parties can receive the same messages.
157
+ #
158
+ # Note: For Temporary Queues and Topics, remember to delete them when done
159
+ # or just use ::destination instead with a block and it will take care
160
+ # of deleting them for you
161
+ #
162
+ # To create a queue:
163
+ # session.create_destination(:queue_name => 'name of queue')
164
+ #
165
+ # To create a temporary queue:
166
+ # session.create_destination(:queue_name => :temporary)
167
+ #
168
+ # To create a queue:
169
+ # session.create_destination('queue://queue_name')
170
+ #
171
+ # To create a topic:
172
+ # session.create_destination(:topic_name => 'name of queue')
173
+ #
174
+ # To create a temporary topic:
175
+ # session.create_destination(:topic_name => :temporary)
176
+ #
177
+ # To create a topic:
178
+ # session.create_destination('topic://topic_name')
179
+ #
180
+ # Create the destination based on the parameter supplied
181
+ #
182
+ # Parameters:
183
+ # :queue_name => String: Name of the Queue to return
184
+ # Symbol: :temporary => Create temporary queue
185
+ # Mandatory unless :topic_name is supplied
186
+ # Or,
187
+ # :topic_name => String: Name of the Topic to write to or subscribe to
188
+ # Symbol: :temporary => Create temporary topic
189
+ # Mandatory unless :queue_name is supplied
190
+ # Or,
191
+ # :destination=> Explicit javaxJms::Destination to use
192
+ #
193
+ # Returns the result of the supplied block
194
+ def create_destination(params)
195
+ # Allow a Java JMS destination object to be passed in
196
+ return params[:destination] if params[:destination] && params[:destination].java_kind_of?(JMS::Destination)
197
+
198
+ queue_name = nil
199
+ topic_name = nil
200
+
201
+ if params.is_a? String
202
+ queue_name = params['queue://'.length..-1] if params.start_with?('queue://')
203
+ topic_name = params['topic://'.length..-1] if params.start_with?('topic://')
204
+ else
205
+ # :q_name is deprecated
206
+ queue_name = params[:queue_name] || params[:q_name]
207
+ topic_name = params[:topic_name]
208
+ end
209
+
210
+ raise "Missing mandatory parameter :queue_name or :topic_name to Session::producer, Session::consumer, or Session::browser" unless queue_name || topic_name
211
+
212
+ if queue_name
213
+ queue_name == :temporary ? create_temporary_queue : create_queue(queue_name)
214
+ else
215
+ topic_name == :temporary ? create_temporary_topic : create_topic(topic_name)
216
+ end
217
+ end
218
+
219
+ # Create a queue or topic to send or receive messages from
220
+ #
221
+ # A block must be supplied so that if it is a temporary topic or queue
222
+ # it will be deleted after the proc is complete
223
+ #
224
+ # To create a queue:
225
+ # session.destination(:queue_name => 'name of queue')
226
+ #
227
+ # To create a temporary queue:
228
+ # session.destination(:queue_name => :temporary)
229
+ #
230
+ # To create a topic:
231
+ # session.destination(:topic_name => 'name of queue')
232
+ #
233
+ # To create a temporary topic:
234
+ # session.destination(:topic_name => :temporary)
235
+ #
236
+ # Create the destination based on the parameter supplied
237
+ #
238
+ # Parameters:
239
+ # :queue_name => String: Name of the Queue to return
240
+ # Symbol: :temporary => Create temporary queue
241
+ # Mandatory unless :topic_name is supplied
242
+ # Or,
243
+ # :topic_name => String: Name of the Topic to write to or subscribe to
244
+ # Symbol: :temporary => Create temporary topic
245
+ # Mandatory unless :queue_name is supplied
246
+ # Or,
247
+ # :destination=> Explicit javaxJms::Destination to use
248
+ #
249
+ # Returns the result of the supplied block
250
+ def destination(params={}, &block)
251
+ raise "Missing mandatory Block when calling JMS::Session#destination" unless block
252
+ dest = nil
253
+ begin
254
+ dest = create_destination(params)
255
+ block.call(dest)
256
+ ensure
257
+ # Delete Temporary Queue / Topic
258
+ dest.delete if dest && dest.respond_to?(:delete)
259
+ end
260
+ end
261
+
262
+ # Return the queue matching the queue name supplied
263
+ # Call the Proc if supplied
264
+ def queue(queue_name, &block)
265
+ q = create_queue(queue_name)
266
+ block.call(q) if block
267
+ q
268
+ end
269
+
270
+ # Return a temporary queue
271
+ # The temporary queue is deleted once the block completes
272
+ # If no block is supplied then it should be deleted by the caller
273
+ # when no longer needed
274
+ def temporary_queue(&block)
275
+ q = create_temporary_queue
276
+ if block
277
+ begin
278
+ block.call(q)
279
+ ensure
280
+ # Delete Temporary queue on completion of block
281
+ q.delete if q
282
+ q = nil
283
+ end
284
+ end
285
+ q
286
+ end
287
+
288
+ # Return the topic matching the topic name supplied
289
+ # Call the Proc if supplied
290
+ def topic(topic_name, &proc)
291
+ t = create_topic(topic_name)
292
+ proc.call(t) if proc
293
+ t
294
+ end
295
+
296
+ # Return a temporary topic
297
+ # The temporary topic is deleted once the block completes
298
+ # If no block is supplied then it should be deleted by the caller
299
+ # when no longer needed
300
+ def temporary_topic(&block)
301
+ t = create_temporary_topic
302
+ if block
303
+ begin
304
+ block.call(t)
305
+ ensure
306
+ # Delete Temporary topic on completion of block
307
+ t.delete if t
308
+ t = nil
309
+ end
310
+ end
311
+ t
312
+ end
313
+
314
+ # Return a producer for the queue name supplied
315
+ # A producer supports sending messages to a Queue or a Topic
316
+ #
317
+ # Call the Proc if supplied, then automatically close the producer
318
+ #
319
+ # Parameters:
320
+ # :queue_name => String: Name of the Queue to return
321
+ # Symbol: :temporary => Create temporary queue
322
+ # Mandatory unless :topic_name is supplied
323
+ # Or,
324
+ # :topic_name => String: Name of the Topic to write to or subscribe to
325
+ # Symbol: :temporary => Create temporary topic
326
+ # Mandatory unless :queue_name is supplied
327
+ # Or,
328
+ # :destination=> Explicit JMS::Destination to use
329
+ def producer(params, &proc)
330
+ p = self.create_producer(self.create_destination(params))
331
+ if proc
332
+ begin
333
+ proc.call(p)
334
+ ensure
335
+ p.close
336
+ p = nil
337
+ end
338
+ end
339
+ p
340
+ end
341
+
342
+ # Return a consumer for the destination
343
+ # A consumer can read messages from the queue or topic
344
+ #
345
+ # Call the Proc if supplied, then automatically close the consumer
346
+ #
347
+ # Parameters:
348
+ # :queue_name => String: Name of the Queue to return
349
+ # Symbol: :temporary => Create temporary queue
350
+ # Mandatory unless :topic_name is supplied
351
+ # Or,
352
+ # :topic_name => String: Name of the Topic to write to or subscribe to
353
+ # Symbol: :temporary => Create temporary topic
354
+ # Mandatory unless :queue_name is supplied
355
+ # Or,
356
+ # :destination=> Explicit javaxJms::Destination to use
357
+ #
358
+ # :selector => Filter which messages should be returned from the queue
359
+ # Default: All messages
360
+ # :no_local => Determine whether messages published by its own connection
361
+ # should be delivered to it
362
+ # Default: false
363
+ def consumer(params, &proc)
364
+ destination = create_destination(params)
365
+ c = nil
366
+ if params[:no_local]
367
+ c = create_consumer(destination, params[:selector] || '', params[:no_local])
368
+ elsif params[:selector]
369
+ c = create_consumer(destination, params[:selector])
370
+ else
371
+ c = create_consumer(destination)
372
+ end
373
+
374
+ if proc
375
+ begin
376
+ proc.call(c)
377
+ ensure
378
+ c.close
379
+ c = nil
380
+ end
381
+ end
382
+ c
383
+ end
384
+
385
+ # Consume all messages for the destination
386
+ # A consumer can read messages from the queue or topic
387
+ #
388
+ # Parameters:
389
+ # :queue_name => String: Name of the Queue to return
390
+ # Symbol: :temporary => Create temporary queue
391
+ # Mandatory unless :topic_name is supplied
392
+ # Or,
393
+ # :topic_name => String: Name of the Topic to write to or subscribe to
394
+ # Symbol: :temporary => Create temporary topic
395
+ # Mandatory unless :queue_name is supplied
396
+ # Or,
397
+ # :destination=> Explicit javaxJms::Destination to use
398
+ #
399
+ # :selector => Filter which messages should be returned from the queue
400
+ # Default: All messages
401
+ # :no_local => Determine whether messages published by its own connection
402
+ # should be delivered to it
403
+ # Default: false
404
+ #
405
+ # :timeout Follows the rules for MQSeries:
406
+ # -1 : Wait forever
407
+ # 0 : Return immediately if no message is available
408
+ # x : Wait for x milli-seconds for a message to be received from the broker
409
+ # Note: Messages may still be on the queue, but the broker has not supplied any messages
410
+ # in the time interval specified
411
+ # Default: 0
412
+ #
413
+ def consume(params, &proc)
414
+ c = self.consumer(params)
415
+ begin
416
+ c.each(params, &proc)
417
+ ensure
418
+ c.close
419
+ end
420
+ end
421
+
422
+ # Return a browser for the destination
423
+ # A browser can read messages non-destructively from the queue
424
+ # It cannot browse Topics!
425
+ #
426
+ # Call the Proc if supplied, then automatically close the consumer
427
+ #
428
+ # Parameters:
429
+ # :queue_name => String: Name of the Queue to return
430
+ # Symbol: :temporary => Create temporary queue
431
+ # Mandatory unless :topic_name is supplied
432
+ # Or,
433
+ # :destination=> Explicit javaxJms::Destination to use
434
+ #
435
+ # :selector => Filter which messages should be returned from the queue
436
+ # Default: All messages
437
+ def browser(params, &proc)
438
+ raise "Session::browser requires a code block to be executed" unless proc
439
+
440
+ destination = create_destination(params)
441
+ b = nil
442
+ if params[:selector]
443
+ b = create_browser(destination, params[:selector])
444
+ else
445
+ b = create_browser(destination)
446
+ end
447
+
448
+ if proc
449
+ begin
450
+ proc.call(b)
451
+ ensure
452
+ b.close
453
+ b = nil
454
+ end
455
+ end
456
+ b
457
+ end
458
+
459
+ # Browse the specified queue, calling the Proc supplied for each message found
460
+ #
461
+ # Parameters:
462
+ # :queue_name => String: Name of the Queue to return
463
+ # Symbol: :temporary => Create temporary queue
464
+ # Mandatory unless :topic_name is supplied
465
+ # Or,
466
+ # :destination=> Explicit javaxJms::Destination to use
467
+ #
468
+ # :selector => Filter which messages should be returned from the queue
469
+ # Default: All messages
470
+ def browse(params={}, &proc)
471
+ self.browser(params) {|b| b.each(params, &proc)}
472
+ end
473
+ end