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,168 @@
1
+ require 'gene_pool'
2
+
3
+ module JMS
4
+ # Since a Session can only be used by one thread at a time, we could create
5
+ # a Session for every thread. That could result in excessive unused Sessions.
6
+ # An alternative is to create a pool of sessions that can be shared by
7
+ # multiple threads.
8
+ #
9
+ # Each thread can request a session and then return it once it is no longer
10
+ # needed by that thread. The only way to get a session is pass a block so that
11
+ # the Session is automatically returned to the pool upon completion of the block.
12
+ #
13
+ # Parameters:
14
+ # see regular session parameters from: JMS::Connection#initialize
15
+ #
16
+ # Additional parameters for controlling the session pool itself
17
+ # :pool_name Name of the pool as it shows up in the logger.
18
+ # Default: 'JMS::SessionPool'
19
+ # :pool_size Maximum Pool Size. Default: 10
20
+ # The pool only grows as needed and will never exceed
21
+ # :pool_size
22
+ # :pool_timeout Number of seconds to wait before raising a TimeoutError
23
+ # if no sessions are available in the poo
24
+ # Default: 60
25
+ # :pool_warn_timeout Number of seconds to wait before logging a warning when a
26
+ # session in the pool is not available
27
+ # Default: 5
28
+ # :pool_logger Supply a logger that responds to #debug, #info, #warn and #debug?
29
+ # For example: Rails.logger
30
+ # Default: JMS.logger
31
+ # Example:
32
+ # session_pool = connection.create_session_pool(config)
33
+ # session_pool.session do |session|
34
+ # ....
35
+ # end
36
+ class SessionPool
37
+ def initialize(connection, params={})
38
+ # Save Session params since it will be used every time a new session is
39
+ # created in the pool
40
+ session_params = params.nil? ? {} : params.dup
41
+ logger = session_params[:pool_logger] || JMS.logger
42
+ # Define how GenePool can create new sessions
43
+ @pool = GenePool.new(
44
+ :name => session_params[:pool_name] || self.class.name,
45
+ :pool_size => session_params[:pool_size] || 10,
46
+ :warn_timeout => session_params[:pool_warn_timeout] || 5,
47
+ :timeout => session_params[:pool_timeout] || 60,
48
+ :close_proc => nil,
49
+ :logger => logger) do
50
+ connection.create_session(session_params)
51
+ end
52
+
53
+ # Handle connection failures
54
+ connection.on_exception do |jms_exception|
55
+ logger.error "JMS Connection Exception has occurred: #{jms_exception}" if logger
56
+ #TODO: Close all sessions in the pool and release from the pool?
57
+ end
58
+ end
59
+
60
+ # Obtain a session from the pool and pass it to the supplied block
61
+ # The session is automatically returned to the pool once the block completes
62
+ #
63
+ # In the event a JMS Exception is thrown the session will be closed and removed
64
+ # from the pool to prevent re-using sessions that are no longer valid
65
+ def session(&block)
66
+ s = nil
67
+ begin
68
+ s = @pool.checkout
69
+ block.call(s)
70
+ rescue javax.jms.JMSException => e
71
+ s.close rescue nil
72
+ @pool.remove(s)
73
+ s = nil # Do not check back in since we have removed it
74
+ raise e
75
+ ensure
76
+ @pool.checkin(s) if s
77
+ end
78
+ end
79
+
80
+ # Obtain a session from the pool and create a MessageConsumer.
81
+ # Pass both into the supplied block.
82
+ # Once the block is complete the consumer is closed and the session is
83
+ # returned to the pool.
84
+ #
85
+ # Parameters:
86
+ # :queue_name => String: Name of the Queue to return
87
+ # Symbol: :temporary => Create temporary queue
88
+ # Mandatory unless :topic_name is supplied
89
+ # Or,
90
+ # :topic_name => String: Name of the Topic to write to or subscribe to
91
+ # Symbol: :temporary => Create temporary topic
92
+ # Mandatory unless :queue_name is supplied
93
+ # Or,
94
+ # :destination=> Explicit javaxJms::Destination to use
95
+ #
96
+ # :selector => Filter which messages should be returned from the queue
97
+ # Default: All messages
98
+ # :no_local => Determine whether messages published by its own connection
99
+ # should be delivered to it
100
+ # Default: false
101
+ #
102
+ # Example
103
+ # session_pool.consumer(:queue_name => 'MyQueue') do |session, consumer|
104
+ # message = consumer.receive(timeout)
105
+ # puts message.data if message
106
+ # end
107
+ def consumer(params, &block)
108
+ session do |s|
109
+ consumer = nil
110
+ begin
111
+ consumer = s.consumer(params)
112
+ block.call(s, consumer)
113
+ ensure
114
+ consumer.close if consumer
115
+ end
116
+ end
117
+ end
118
+
119
+ # Obtain a session from the pool and create a MessageProducer.
120
+ # Pass both into the supplied block.
121
+ # Once the block is complete the producer is closed and the session is
122
+ # returned to the pool.
123
+ #
124
+ # Parameters:
125
+ # :queue_name => String: Name of the Queue to send messages to
126
+ # Symbol: :temporary => Create temporary queue
127
+ # Mandatory unless :topic_name is supplied
128
+ # Or,
129
+ # :topic_name => String: Name of the Topic to send message to
130
+ # Symbol: :temporary => Create temporary topic
131
+ # Mandatory unless :queue_name is supplied
132
+ # Or,
133
+ # :destination=> Explicit JMS::Destination to use
134
+ #
135
+ # Example
136
+ # session_pool.producer(:queue_name => 'ExampleQueue') do |session, producer|
137
+ # producer.send(session.message("Hello World"))
138
+ # end
139
+ def producer(params, &block)
140
+ session do |s|
141
+ producer = nil
142
+ begin
143
+ producer = s.producer(params)
144
+ block.call(s, producer)
145
+ ensure
146
+ producer.close if producer
147
+ end
148
+ end
149
+ end
150
+
151
+ # Immediately Close all sessions in the pool and release from the pool
152
+ #
153
+ # Note: This is an immediate close, active sessions will be aborted
154
+ #
155
+ # Note: Once closed a session pool cannot be re-used. A new instance must
156
+ # be created
157
+ #
158
+ # TODO: Allow an option to wait for active sessions to be returned before
159
+ # closing
160
+ def close
161
+ @pool.each do |s|
162
+ s.close
163
+ end
164
+ end
165
+
166
+ end
167
+
168
+ end
@@ -0,0 +1,31 @@
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.TextMessage
18
+ module JMS::TextMessage
19
+ def data
20
+ getText
21
+ end
22
+
23
+ def data=(val)
24
+ setText(val.to_s)
25
+ end
26
+
27
+ def to_s
28
+ data
29
+ end
30
+
31
+ end
@@ -0,0 +1,3 @@
1
+ module JMS #:nodoc
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ file.reference.jruby-jms-examples=/Users/rmorrison/Sandbox/jruby-jms/examples
2
+ file.reference.jruby-jms-lib=/Users/rmorrison/Sandbox/jruby-jms/lib
3
+ file.reference.jruby-jms-test=/Users/rmorrison/Sandbox/jruby-jms/test
@@ -0,0 +1,5 @@
1
+ clean=Remove any temporary products.
2
+ clobber=Remove any generated file.
3
+ doc=Generate RDOC documentation
4
+ gem=Build gem
5
+ test=Run Test Suite
@@ -0,0 +1,21 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain gem's version:
4
+ require 'jms/version'
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'jruby-jms'
9
+ spec.version = JMS::VERSION
10
+ spec.platform = 'java'
11
+ spec.authors = ['Reid Morrison']
12
+ spec.email = ['reidmo@gmail.com']
13
+ spec.homepage = 'https://github.com/reidmorrison/jruby-jms'
14
+ spec.summary = 'JRuby interface into JMS'
15
+ spec.description = 'JRuby-JMS is a Java and Ruby library that exposes the Java JMS API in a ruby friendly way. For JRuby only.'
16
+ spec.files = FileList["./**/*"].exclude('*.gem', './nbproject/*').map{|f| f.sub(/^\.\//, '')}
17
+ spec.test_files = Dir["test/**/*"]
18
+ spec.license = "Apache License V2.0"
19
+ spec.has_rdoc = true
20
+ spec.add_dependency 'gene_pool'
21
+ end
@@ -0,0 +1,160 @@
1
+ # Allow examples to be run in-place without requiring a gem install
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'shoulda'
7
+ require 'jms'
8
+ require 'yaml'
9
+
10
+ # Set Log4J properties file so that it does not need to be in the CLASSPATH
11
+ java.lang.System.properties['log4j.configuration'] = "test/log4j.properties"
12
+
13
+ class JMSTest < Test::Unit::TestCase
14
+ context 'JMS Connection' do
15
+ # Load configuration from jms.yml
16
+ setup do
17
+ # To change the JMS provider, edit jms.yml and change :default
18
+
19
+ # Load Connection parameters from configuration file
20
+ cfg = YAML.load_file(File.join(File.dirname(__FILE__), 'jms.yml'))
21
+ jms_provider = cfg['default']
22
+ @config = cfg[jms_provider]
23
+ raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless @config
24
+ @queue_name = @config.delete(:queue_name) || raise("Mandatory :queue_name missing from jms.yml")
25
+ @topic_name = @config.delete(:topic_name) || raise("Mandatory :topic_name missing from jms.yml")
26
+ end
27
+
28
+ should 'Create Connection to the Broker/Server' do
29
+ connection = JMS::Connection.new(@config)
30
+ JMS::logger.info connection.to_s
31
+ assert_not_nil connection
32
+ connection.close
33
+ end
34
+
35
+ should 'Create and start Connection to the Broker/Server with block' do
36
+ JMS::Connection.start(@config) do |connection|
37
+ assert_not_nil connection
38
+ end
39
+ end
40
+
41
+ should 'Create and start Connection to the Broker/Server with block and start one session' do
42
+ JMS::Connection.session(@config) do |session|
43
+ assert_not_nil session
44
+ end
45
+ end
46
+
47
+ should 'Start and stop connection' do
48
+ connection = JMS::Connection.new(@config)
49
+ assert_not_nil connection
50
+ assert_nil connection.start
51
+
52
+ assert_nil connection.stop
53
+ assert_nil connection.close
54
+ end
55
+
56
+ should 'Create a session from the connection' do
57
+ connection = JMS::Connection.new(@config)
58
+
59
+ session_parms = {
60
+ :transacted => true,
61
+ :options => JMS::Session::AUTO_ACKNOWLEDGE
62
+ }
63
+
64
+ session = connection.create_session
65
+ assert_not_nil session
66
+ assert_equal session.transacted?, false
67
+ assert_nil session.close
68
+
69
+ assert_nil connection.stop
70
+ assert_nil connection.close
71
+ end
72
+
73
+ should 'Create a session with a block' do
74
+ connection = JMS::Connection.new(@config)
75
+
76
+ connection.session do |session|
77
+ assert_not_nil session
78
+ assert_equal session.transacted?, false
79
+ end
80
+
81
+ assert_nil connection.stop
82
+ assert_nil connection.close
83
+ end
84
+
85
+ should 'create a session without a block and throw exception' do
86
+ connection = JMS::Connection.new(@config)
87
+
88
+ assert_raise(RuntimeError) { connection.session }
89
+
90
+ assert_nil connection.stop
91
+ assert_nil connection.close
92
+ end
93
+
94
+ should 'Create a session from the connection with params' do
95
+ connection = JMS::Connection.new(@config)
96
+
97
+ session_parms = {
98
+ :transacted => true,
99
+ :options => JMS::Session::AUTO_ACKNOWLEDGE
100
+ }
101
+
102
+ session = connection.create_session(session_parms)
103
+ assert_not_nil session
104
+ assert_equal session.transacted?, true
105
+ # When session is transacted, options are ignore, so ack mode must be transacted
106
+ assert_equal session.acknowledge_mode, JMS::Session::SESSION_TRANSACTED
107
+ assert_nil session.close
108
+
109
+ assert_nil connection.stop
110
+ assert_nil connection.close
111
+ end
112
+
113
+ should 'Create a session from the connection with block and params' do
114
+ JMS::Connection.start(@config) do |connection|
115
+
116
+ session_parms = {
117
+ :transacted => true,
118
+ :options => JMS::Session::CLIENT_ACKNOWLEDGE
119
+ }
120
+
121
+ connection.session(session_parms) do |session|
122
+ assert_not_nil session
123
+ assert_equal session.transacted?, true
124
+ # When session is transacted, options are ignore, so ack mode must be transacted
125
+ assert_equal session.acknowledge_mode, JMS::Session::SESSION_TRANSACTED
126
+ end
127
+ end
128
+ end
129
+
130
+ should 'Create a session from the connection with block and params opposite test' do
131
+ JMS::Connection.start(@config) do |connection|
132
+
133
+ session_parms = {
134
+ :transacted => false,
135
+ :options => JMS::Session::AUTO_ACKNOWLEDGE
136
+ }
137
+
138
+ connection.session(session_parms) do |session|
139
+ assert_not_nil session
140
+ assert_equal session.transacted?, false
141
+ assert_equal session.acknowledge_mode, JMS::Session::AUTO_ACKNOWLEDGE
142
+ end
143
+ end
144
+ end
145
+
146
+ context 'JMS Connection additional capabilities' do
147
+
148
+ should 'start an on_message handler' do
149
+ JMS::Connection.start(@config) do |connection|
150
+ value = nil
151
+ connection.on_message(:transacted => true, :queue_name => :temporary) do |message|
152
+ value = "received"
153
+ end
154
+ end
155
+ end
156
+
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,111 @@
1
+ # This YAML file contains the configuration options for several different
2
+ # JMS Providers
3
+ #
4
+ # The Examples that ship with jruby-jms will use the entry 'default' unless
5
+ # overriden at the command line. For example:
6
+ # jruby producer.rb activemq
7
+ #
8
+ ---
9
+ # Which JMS Provider to use by default
10
+
11
+ #default: hornetq222
12
+ #default: hornetq225
13
+ #default: activemq543
14
+ #default: activemq551
15
+ default: activemq590
16
+ #default: webspheremq6
17
+ #default: webspheremq7
18
+
19
+ activemq543:
20
+ :factory: org.apache.activemq.ActiveMQConnectionFactory
21
+ :broker_url: tcp://localhost:61616
22
+ :require_jars:
23
+ - ~/jms/apache-activemq-5.4.3/activemq-all-5.4.3.jar
24
+ :queue_name: TestQueue
25
+ :topic_name: TestTopic
26
+
27
+ activemq551:
28
+ :factory: org.apache.activemq.ActiveMQConnectionFactory
29
+ :broker_url: tcp://localhost:61616
30
+ :require_jars:
31
+ - ~/jms/apache-activemq-5.5.1/activemq-all-5.5.1.jar
32
+ - ~/jms/apache-activemq-5.5.1/lib/optional/slf4j-log4j12-1.5.11.jar
33
+ - ~/jms/apache-activemq-5.5.1/lib/optional/log4j-1.2.14.jar
34
+ :queue_name: TestQueue
35
+ :topic_name: TestTopic
36
+
37
+ activemq590:
38
+ :factory: org.apache.activemq.ActiveMQConnectionFactory
39
+ :broker_url: tcp://localhost:61616
40
+ :require_jars:
41
+ - /usr/local/Cellar/activemq/5.9.0/libexec/activemq-all-5.9.0.jar
42
+ - /usr/local/Cellar/activemq/5.9.0/libexec/lib/optional/log4j-1.2.17.jar
43
+ :queue_name: TestQueue
44
+ :topic_name: TestTopic
45
+
46
+ hornetq225:
47
+ # Connect to a local HornetQ Broker using JNDI
48
+ :jndi_name: /ConnectionFactory
49
+ :jndi_context:
50
+ java.naming.factory.initial: org.jnp.interfaces.NamingContextFactory
51
+ java.naming.provider.url: jnp://localhost:1099
52
+ java.naming.factory.url.pkgs: org.jboss.naming:org.jnp.interfaces
53
+ java.naming.security.principal: guest
54
+ java.naming.security.credentials: guest
55
+ :require_jars:
56
+ - ~/jms/hornetq-2.2.5.Final/lib/hornetq-core-client.jar
57
+ - ~/jms/hornetq-2.2.5.Final/lib/netty.jar
58
+ - ~/jms/hornetq-2.2.5.Final/lib/hornetq-jms-client.jar
59
+ - ~/jms/hornetq-2.2.5.Final/lib/jboss-jms-api.jar
60
+ - ~/jms/hornetq-2.2.5.Final/lib/jnp-client.jar
61
+ :queue_name: TestQueue
62
+ :topic_name: TestTopic
63
+
64
+ hornetq222:
65
+ # Connect to a local HornetQ Broker using JNDI
66
+ :jndi_name: /ConnectionFactory
67
+ :jndi_context:
68
+ java.naming.factory.initial: org.jnp.interfaces.NamingContextFactory
69
+ java.naming.provider.url: jnp://localhost:1099
70
+ java.naming.factory.url.pkgs: org.jboss.naming:org.jnp.interfaces
71
+ java.naming.security.principal: guest
72
+ java.naming.security.credentials: guest
73
+ :require_jars:
74
+ - ~/jms/hornetq-2.2.2.Final/lib/hornetq-core-client.jar
75
+ - ~/jms/hornetq-2.2.2.Final/lib/netty.jar
76
+ - ~/jms/hornetq-2.2.2.Final/lib/hornetq-jms-client.jar
77
+ - ~/jms/hornetq-2.2.2.Final/lib/jboss-jms-api.jar
78
+ - ~/jms/hornetq-2.2.2.Final/lib/jnp-client.jar
79
+ :queue_name: TestQueue
80
+ :topic_name: TestTopic
81
+
82
+ webspheremq7:
83
+ :factory: com.ibm.mq.jms.MQConnectionFactory
84
+ :queue_manager: MYQM
85
+ :host_name: 127.0.0.1
86
+ :channel: SRVCONCHA
87
+ :port: 61414
88
+ # Transport Type: com.ibm.mq.jms.JMSC::MQJMS_TP_CLIENT_MQ_TCPIP
89
+ :transport_type: 1
90
+ :username: mqm
91
+ :require_jars:
92
+ - ~/jms/libs-ibmqm7/com.ibm.mqjms.jar
93
+ - ~/jms/libs-ibmqm7/jms.jar
94
+ - ~/jms/libs-ibmqm7/com.ibm.mq.jmqi.jar
95
+ - ~/jms/libs-ibmqm7/dhbcore.jar
96
+ :queue_name: TestQueue
97
+ :topic_name: TestTopic
98
+
99
+ webspheremq6:
100
+ :factory: com.ibm.mq.jms.MQConnectionFactory
101
+ :queue_manager: MYQM
102
+ :host_name: 127.0.0.1
103
+ :channel: SRVCONCHA
104
+ :port: 61414
105
+ # Transport Type: com.ibm.mq.jms.JMSC::MQJMS_TP_CLIENT_MQ_TCPIP
106
+ :transport_type: 1
107
+ :username: mqm
108
+ :require_jars:
109
+ - ~/jms/libs-ibmqm6/com.ibm.mqjms.jar
110
+ :queue_name: TestQueue
111
+ :topic_name: TestTopic