jruby-jms 1.1.0-java

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