jsparrow 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Leandro Silva (CodeZone) <leandrodoze@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ = jsparrow
2
+
3
+ JSparrow is a JMS client based on JRuby. Previously it has been called Sparrow, but changed his name because has another project with the same name.
4
+
5
+ === Install
6
+
7
+ Make gem install:
8
+
9
+ sudo gem install jsparrow -s http://gemcutter.org
10
+
11
+ === Example
12
+
13
+ ===== Six steps to send and receive JMS messages to/from a JMS middleware.
14
+
15
+ WARNING: OpenJMS will be used as JMS middleware, but any other could be used with no problems.
16
+
17
+ 1) Create my_jsparrow_test.rb file and require the gems
18
+
19
+ require 'rubygems'
20
+ require 'jsparrow'
21
+
22
+ 2) Setup indispensable informations to connect your JMS middleware
23
+
24
+ JSparrow::Connection.configure do |connection|
25
+ connection.use_jms_client_jar '/opt/openjms/lib/openjms-0.7.7-beta-1.jar'
26
+
27
+ connection.use_jndi_properties :initial_context_factory => 'org.exolab.jms.jndi.InitialContextFactory',
28
+ :provider_url => 'tcp://localhost:3035'
29
+ # :security_principal => 'user',
30
+ # :security_credentials => 'password'
31
+
32
+ connection.enable_connection_factories :queue_connection_factory => 'ConnectionFactory',
33
+ :topic_connection_factory => 'ConnectionFactory'
34
+ end
35
+
36
+ 3) Create the client and setup a queue
37
+
38
+ jms_client = JSparrow::Connection.new_client
39
+ jms_client.enable_queues :my_queue => 'MyQueue'
40
+
41
+ 4) After appropriate setup, start the client
42
+
43
+ jms_client.start
44
+
45
+ 5) OK! Now you can send and receive messages right now!
46
+
47
+ jms_client.queue_sender(:my_queue).send_text_message('jsparrow rocks!') do |msg|
48
+ msg.set_string_property('recipient', 'jsparrow-example')
49
+ end
50
+
51
+ jms_client.queue_receiver(:my_queue).receive_message(
52
+ :timeout => 5000,
53
+ :selector => "recipient = 'jsparrow-example'"
54
+ ) do |msg|
55
+
56
+ puts "is text message? #{msg.is_text_message?}" # is text message? true
57
+ puts "message: #{msg.text}" # message: jsparrow rocks!
58
+ end
59
+
60
+ 6) After you receive your amazing messages, stop the client
61
+
62
+ jms_client.stop
63
+
64
+ So, now that you did code and save it, start the OpenJMS server, create the queue (MyQueue), and run above script:
65
+
66
+ jruby my_jsparrow_test.rb
67
+
68
+ jsparrow rocks! =)
69
+
70
+ ===== Sample code
71
+
72
+ Or, if you don't want write code, only do it:
73
+
74
+ jruby sample/sample.rb
75
+
76
+ == Copyright
77
+
78
+ Copyright (c) 2009 Leandro Silva (CodeZone) <leandrodoze@gmail.com>. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "jsparrow"
8
+ gem.summary = "JSparrow is a JMS client based on JRuby"
9
+ gem.email = "leandrodoze@gmail.com"
10
+ gem.homepage = "http://github.com/leandrosilva/jsparrow"
11
+ gem.authors = ["Leandro Silva"]
12
+ gem.files = FileList["[A-Z]*", "{lib,sample,spec}/**/*"]
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
17
+ end
18
+
19
+ require 'rake/rdoctask'
20
+ Rake::RDocTask.new do |rdoc|
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = 'jsparrow'
23
+ rdoc.options << '--line-numbers' << '--inline-source'
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = false
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/*_test.rb'
40
+ test.verbose = true
41
+ end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+
49
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 1
4
+ :build:
5
+ :minor: 1
data/lib/connection.rb ADDED
@@ -0,0 +1,278 @@
1
+ # Classes Java usadas nesse arquivo
2
+ import 'java.util.Hashtable'
3
+ import 'javax.naming.InitialContext'
4
+
5
+ module JSparrow
6
+ module Connection
7
+
8
+ #
9
+ # Metodo usado para configurar a conexao com o middleware de JMS.
10
+ #
11
+ def self.configure
12
+ @@properties = ConnectionProperties.new
13
+
14
+ yield @@properties
15
+ end
16
+
17
+ #
18
+ # Metodo usado para obter a configuracao para conexao com o middleware de JMS.
19
+ #
20
+ def self.connection_properties
21
+ @@properties
22
+ end
23
+
24
+ #
25
+ # Metodo usado para criar um novo Client JMS.
26
+ #
27
+ def self.new_client
28
+ jndi_context_builder = JNDI::ContextBuilder.new(@@properties.jms_client_jar, @@properties.jndi_properties)
29
+
30
+ Client.new(@@properties, jndi_context_builder)
31
+ end
32
+
33
+ #
34
+ # Configuracoes necessarias para que clientes JMS se conetem
35
+ # ao middleware de mensageria via contexto JNDI.
36
+ #
37
+ class ConnectionProperties
38
+ attr_reader :jms_client_jar, :jndi_properties,
39
+ :enabled_connection_factories, :enabled_queues, :enabled_topics
40
+
41
+ def use_jms_client_jar(client_jar)
42
+ @jms_client_jar = client_jar
43
+ end
44
+
45
+ def use_jndi_properties(jndi_properties = {})
46
+ @jndi_properties = jndi_properties
47
+ end
48
+
49
+ def enable_connection_factories(jndi_names = {})
50
+ @enabled_connection_factories = jndi_names
51
+ end
52
+
53
+ def enable_queues(jndi_names = {})
54
+ @enabled_queues = jndi_names
55
+ end
56
+
57
+ def enable_topics(jndi_names = {})
58
+ @enabled_topics = jndi_names
59
+ end
60
+ end
61
+
62
+ #
63
+ # Cliente JMS que possibilita a conexao com o servidor de aplicacoes Java EE
64
+ # que prove o servico JMS.
65
+ #
66
+ class Client
67
+ def initialize(connection_properties, jndi_context_builder)
68
+ @connection_properties = connection_properties
69
+ @jndi_context_builder = jndi_context_builder
70
+
71
+ @jndi_name_of_enabled_connection_factories = @connection_properties.enabled_connection_factories
72
+ @jndi_name_of_enabled_queues = {}
73
+ @jndi_name_of_enabled_topics = {}
74
+
75
+ # Conexoes, filas, topicos, senders e receivers que serao habilitados
76
+ @connection_factories = {}
77
+ @queues = {}
78
+ @queue_senders = {}
79
+ @queue_receivers = {}
80
+ @topics = {}
81
+ @topic_senders = {}
82
+ @topic_receivers = {}
83
+
84
+ # Foi startado?
85
+ @started = false
86
+ end
87
+
88
+ def is_started?
89
+ @started
90
+ end
91
+
92
+ def start
93
+ raise InvalidClientStateError.new('started', 'start') if is_started?
94
+
95
+ begin
96
+ @jndi_context = @jndi_context_builder.build
97
+ rescue => cause
98
+ raise ClientInitializationError.new(@connection_properties, cause)
99
+ end
100
+
101
+ @connection_factories = lookup_resource(@jndi_name_of_enabled_connection_factories)
102
+ @queues = lookup_resource(@jndi_name_of_enabled_queues)
103
+ @topics = lookup_resource(@jndi_name_of_enabled_topics)
104
+
105
+ @started = true
106
+ end
107
+
108
+ def is_stoped?
109
+ !@started
110
+ end
111
+
112
+ def stop
113
+ raise InvalidClientStateError.new('stoped', 'stop') if is_stoped?
114
+
115
+ @jndi_context.close
116
+
117
+ @started = false
118
+ end
119
+
120
+ def queue_connection_factory_enabled?
121
+ @jndi_name_of_enabled_connection_factories.include?(:queue_connection_factory)
122
+ end
123
+
124
+ def queue_connection_factory
125
+ @connection_factories[:queue_connection_factory]
126
+ end
127
+
128
+ def topic_connection_factory_enabled?
129
+ @jndi_name_of_enabled_connection_factories.include?(:topic_connection_factory)
130
+ end
131
+
132
+ def topic_connection_factory
133
+ @connection_factories[:topic_connection_factory]
134
+ end
135
+
136
+ def enable_queues(jndi_names = {})
137
+ raise InvalidClientStateError.new('started', 'enable_queues') if is_started?
138
+
139
+ @jndi_name_of_enabled_queues = jndi_names
140
+ end
141
+
142
+ def queue_enabled?(queue_name)
143
+ @jndi_name_of_enabled_queues.include?(queue_name)
144
+ end
145
+
146
+ def queue(queue_name)
147
+ raise NameError, "Queue '#{queue_name}' does not exist." unless queue_enabled?(queue_name)
148
+
149
+ @queues[queue_name]
150
+ end
151
+
152
+ def queue_sender(queue_name)
153
+ @queue_senders[queue_name] ||=
154
+ Messaging::Sender.new(queue_connection_factory, queue(queue_name))
155
+ end
156
+
157
+ def queue_receiver(queue_name)
158
+ @queue_receivers[queue_name] ||=
159
+ Messaging::Receiver.new(queue_connection_factory, queue(queue_name))
160
+ end
161
+
162
+ def enable_topics(jndi_names = {})
163
+ raise InvalidClientStateError.new('started', 'enable_topics') if is_started?
164
+
165
+ @jndi_name_of_enabled_topics = jndi_names
166
+ end
167
+
168
+ def topic_enabled?(topic_name)
169
+ @jndi_name_of_enabled_topics.include?(topic_name)
170
+ end
171
+
172
+ def topic(topic_name)
173
+ raise NameError, "Topic '#{topic_name}' does not exist." unless topic_enabled?(topic_name)
174
+
175
+ @topics[topic_name]
176
+ end
177
+
178
+ def topic_sender(topic_name)
179
+ @topic_senders[topic_name] ||=
180
+ Messaging::Sender.new(topic_connection_factory, topic(topic_name))
181
+ end
182
+
183
+ def topic_receiver(topic_name)
184
+ @topic_receivers[topic_name] ||=
185
+ Messaging::Receiver.new(topic_connection_factory, topic(topic_name))
186
+ end
187
+
188
+ # -- Private methods -- #
189
+ private
190
+
191
+ def lookup_resource(jndi_names = {})
192
+ lookuped = {}
193
+
194
+ jndi_names.each do |key, jndi_name|
195
+ lookuped[key] = @jndi_context.lookup(jndi_name)
196
+ end
197
+
198
+ lookuped
199
+ end
200
+ end
201
+
202
+ class ClientInitializationError < StandardError
203
+ attr_reader :properties, :cause
204
+
205
+ def initialize(properties, cause)
206
+ super("Could not open connection to server. Verify the properties's properties.")
207
+
208
+ @properties = properties
209
+ @cause = cause
210
+ end
211
+ end
212
+
213
+ class InvalidClientStateError < StandardError
214
+ attr_reader :state, :operation
215
+
216
+ def initialize(state, operation)
217
+ super("Could not did #{operation} because client is #{state}.")
218
+
219
+ @state = state
220
+ @operation = operation
221
+ end
222
+ end
223
+ end
224
+
225
+ module JNDI
226
+
227
+ #
228
+ # Builder para construcao de contexto JNDI para conexao com o middleware
229
+ # de JMS.
230
+ #
231
+ class ContextBuilder
232
+ attr_accessor :jms_client_jar, :jndi_properties
233
+
234
+ def initialize(jms_client_jar, jndi_properties)
235
+ @jms_client_jar = jms_client_jar
236
+ @jndi_properties = jndi_properties
237
+ end
238
+
239
+ #
240
+ # Constroi um contexto JNDI inicial a partir das configuracoes atuais.
241
+ #
242
+ def build
243
+ # Carrega a biblioteca cliente do servidor de aplicacoes
244
+ require @jms_client_jar
245
+
246
+ InitialContext.new(to_jndi_environment_hashtable)
247
+ end
248
+
249
+ # --- Private methods --- #
250
+ private
251
+
252
+ #
253
+ # Cria um Hashtable Java contendo as configuracoes atuais.
254
+ #
255
+ def to_jndi_environment_hashtable
256
+ jndi_env = Hashtable.new
257
+
258
+ jndi_env.put(
259
+ InitialContext::INITIAL_CONTEXT_FACTORY,
260
+ @jndi_properties[:initial_context_factory])
261
+
262
+ jndi_env.put(
263
+ InitialContext::PROVIDER_URL,
264
+ @jndi_properties[:provider_url])
265
+
266
+ jndi_env.put(
267
+ InitialContext::SECURITY_PRINCIPAL,
268
+ @jndi_properties[:security_principal]) if @jndi_properties[:security_principal]
269
+
270
+ jndi_env.put(
271
+ InitialContext::SECURITY_CREDENTIALS,
272
+ @jndi_properties[:security_credentials]) if @jndi_properties[:security_credentials]
273
+
274
+ jndi_env
275
+ end
276
+ end
277
+ end
278
+ end
data/lib/error.rb ADDED
@@ -0,0 +1,9 @@
1
+ module JSparrow
2
+ module Error
3
+ class AbstractMethodError < StandardError
4
+ def initialize(class_name, method_name)
5
+ super("The '#{class_name}##{method_name}' is a abstract method. Definition is a subclass responsibility.")
6
+ end
7
+ end
8
+ end
9
+ end
Binary file
data/lib/jms/jms.jar ADDED
Binary file
Binary file
data/lib/jms.rb ADDED
@@ -0,0 +1,14 @@
1
+ # Libs directory definition
2
+ JEE_LIB_DIR = File.expand_path(File.dirname(__FILE__)) + '/jms'
3
+
4
+ # Befor all, the fundamental require for us
5
+ require 'java'
6
+
7
+ # Lib to JMS integration (contain the META-INF/applicationContext.xml)
8
+ require "#{JEE_LIB_DIR}/jsparrow-essential.jar"
9
+
10
+ # Java EE
11
+ require "#{JEE_LIB_DIR}/javaee-1.5.jar"
12
+
13
+ # JMS API
14
+ require "#{JEE_LIB_DIR}/jms.jar"
data/lib/jsparrow.rb ADDED
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(File.expand_path(__FILE__)))
2
+
3
+ # Bibliotecas necessarias usar JMS
4
+ require 'jms.rb'
5
+
6
+ # Bibliotecas do JSparrow
7
+ require 'connection.rb'
8
+ require 'messaging.rb'
9
+ require 'error.rb'
data/lib/messaging.rb ADDED
@@ -0,0 +1,244 @@
1
+ # Classes Java usadas nesse arquivo
2
+ import 'javax.jms.Session'
3
+ import 'javax.jms.MessageListener'
4
+
5
+ module JSparrow
6
+ module Messaging
7
+
8
+ #
9
+ # Tempo padrao de timeout no recebimento de mensagens = 1 milesegundo.
10
+ #
11
+ DEFAULT_RECEIVER_TIMEOUT = 1000
12
+
13
+ #
14
+ # Classe base para mensageiros, que enviam ou recebem mensagens, tanto
15
+ # para filas ou topicos.
16
+ #
17
+ class Base
18
+ def initialize(connection_factory, destination)
19
+ # Fabrica de conexoes JMS
20
+ @connection_factory = connection_factory
21
+
22
+ # Destino JMS para envio ou recebimento de mensagens
23
+ @destination = destination
24
+ end
25
+ end
26
+
27
+ #
28
+ # Emissor de mensagens.
29
+ #
30
+ class Sender < Base
31
+ def send_text_message(text)
32
+ send_message do |session|
33
+ text_message = session.create_text_message(text)
34
+
35
+ if block_given?
36
+ yield(text_message)
37
+ end
38
+
39
+ text_message
40
+ end
41
+ end
42
+
43
+ def send_object_message(object)
44
+ send_message do |session|
45
+ object_message = session.create_object_message(object)
46
+
47
+ if block_given?
48
+ yield(object_message)
49
+ end
50
+
51
+ object_message
52
+ end
53
+ end
54
+
55
+ def send_map_message
56
+ send_message do |session|
57
+ map_message = session.create_map_message
58
+
59
+ if block_given?
60
+ yield(map_message)
61
+ end
62
+
63
+ map_message
64
+ end
65
+ end
66
+
67
+ def send_messages(&message_sender)
68
+ # Cria uma conexao, uma sessao e um emissor de qualquer tipo de mensagem
69
+ connection = @connection_factory.create_connection
70
+ session = connection.create_session(true, Session::AUTO_ACKNOWLEDGE)
71
+ producer = session.create_producer(@destination)
72
+
73
+ # Passa o controle que trata a emissao de mensagens
74
+ message_sender.call(session, producer)
75
+
76
+ # Fecha a conexao
77
+ connection.close
78
+ end
79
+
80
+ # --- Private methods --- #
81
+ private
82
+
83
+ def send_message(&message_creator)
84
+ # Cria uma conexao, uma sessao e um emissor de qualquer tipo de mensagem
85
+ connection = @connection_factory.create_connection
86
+ session = connection.create_session(true, Session::AUTO_ACKNOWLEDGE)
87
+ producer = session.create_producer(@destination)
88
+
89
+ # Obtem uma mensagem (TextMessage, ObjectMessage ou MapMessage) do criador especifico
90
+ message = message_creator.call(session)
91
+
92
+ # Envia a mensagem
93
+ producer.send(message)
94
+
95
+ # Commita a sessao e fecha a conexao
96
+ session.commit
97
+ connection.close
98
+ end
99
+ end
100
+
101
+ #
102
+ # Receptor de mensagens.
103
+ #
104
+ class Receiver < Base
105
+ def receive_message(criteria_for_receiving = {:timeout => DEFAULT_RECEIVER_TIMEOUT, :selector => ''}, &message_handler)
106
+ # Cria uma conexao, uma sessao e um consumidor de qualquer tipo de mensagem
107
+ connection = @connection_factory.create_connection
108
+ session = connection.create_session(false, Session::AUTO_ACKNOWLEDGE)
109
+ consumer = session.create_consumer(@destination, criteria_for_receiving[:selector])
110
+
111
+ # Prepara a conexao para receber mensagens
112
+ connection.start
113
+
114
+ # Inicia o recebimento de mensagens
115
+ timeout = criteria_for_receiving[:timeout] || DEFAULT_RECEIVER_TIMEOUT
116
+
117
+ while (received_message = consumer.receive(timeout))
118
+ # Inclui o modulo de identificacao de mensagem, util para o message_handler
119
+ class << received_message
120
+ include MessageType
121
+ end
122
+
123
+ # Delega o tratamento da mensagem para o bloco recebido
124
+ message_handler.call(received_message)
125
+ end
126
+
127
+ # Fecha a conexao
128
+ connection.close
129
+ end
130
+ end
131
+
132
+ #
133
+ # Ouvintes de mensagens.
134
+ #
135
+ # TODO: Completar a implementacao. Ainda nao esta legal. (Ja dei um tapinha,
136
+ # acho que agora ta bem proximo do que deve ser.)
137
+ #
138
+ class Listener < Base
139
+ include MessageListener
140
+
141
+ attr_reader :connection_factory_name, :destination_name, :criteria_to_receiving
142
+
143
+ #
144
+ # Estes parametros serao injetados pelo listener manager de acordo com o
145
+ # que houver sido definido pelos metodos connection_factory_name e destination_name.
146
+ #
147
+ def initialize(connection_factory, destination)
148
+ super(connection_factory, destination)
149
+
150
+ @connection_factory_name = 'undefined'
151
+ @destination_name = 'undefined'
152
+ @criteria_to_receiving = {}
153
+ end
154
+
155
+ #
156
+ # Nome JNDI da connection factory que ser usada para criar conexoes JMS.
157
+ #
158
+ # Invariavelmente deve ser usado pelas subclasses para informar qual devera
159
+ # ser a connection factory usada por esse listener.
160
+ #
161
+ def use_connection_factory(jndi_name)
162
+ @connection_factory_name = jndi_name
163
+ end
164
+
165
+ #
166
+ # Nome JNDI do destino JMS que sera escutado.
167
+ #
168
+ # Invariavelmente deve ser usado pelas subclasses, para informar o nome
169
+ # da queue ou topico que sera escutado.
170
+ #
171
+ def listen_to_destination(jndi_name)
172
+ @destination_name = jndi_name
173
+ end
174
+
175
+ #
176
+ # Criterios de selecao de mensagens, seguindo o padrao JMS.
177
+ #
178
+ # Invariavelmente as subclasses precisam usar esse metodo para definir
179
+ # os criterios de recebimento que este listener levara em conta.
180
+ #
181
+ def receive_only_in_criteria(criteria = {:timeout => DEFAULT_RECEIVER_TIMEOUT, :selector => ''})
182
+ # Valor default para timeout, caso nao tenha sido informado
183
+ @criteria_to_receiving[:timeout] = criteria[:timeout] || DEFAULT_RECEIVER_TIMEOUT
184
+ end
185
+
186
+ #
187
+ # Inicia a escuta de mensagens.
188
+ #
189
+ def start_listening
190
+ # Cria uma conexao, uma sessao e um consumidor de qualquer tipo de mensagem
191
+ connection = @connection_factory.create_connection
192
+ session = connection.create_session(false, Session::AUTO_ACKNOWLEDGE)
193
+ consumer = session.create_consumer(@destination, @criteria_for_receiving[:selector])
194
+
195
+ # Registra-se como ouvinte
196
+ consumer.message_listener = self
197
+
198
+ # Inicia a escuta de mensagens
199
+ connection.start
200
+ end
201
+
202
+ #
203
+ # Faz o enriquecimento do objeto mensagem e delega para o metodo on_receive_message
204
+ # que, implementado pelas subclasses, efetivamente trata a mensagem.
205
+ #
206
+ # Nao deve ser re-implementado por subclasses.
207
+ #
208
+ def on_message(received_message)
209
+ class << received_message
210
+ include MessageType
211
+ end
212
+
213
+ on_receive_message(received_message)
214
+ end
215
+
216
+ #
217
+ # E executado todas as vezes que chega uma mensagem que atenda aos criterios
218
+ # definido para este listener (na variavel de instancia @criteria_for_receiving).
219
+ #
220
+ # Invariavelmente deve ser re-implementado nas subclasses.
221
+ #
222
+ def on_receive_message(received_message)
223
+ raise Error::AbstractMethodError.new('on_receive_message')
224
+ end
225
+ end
226
+ end
227
+
228
+ #
229
+ # Identifica o tipo de uma mensagem.
230
+ #
231
+ module MessageType
232
+ def is_text_message?
233
+ respond_to? :get_text
234
+ end
235
+
236
+ def is_object_message?
237
+ (respond_to? :get_object and !(respond_to? :get_long))
238
+ end
239
+
240
+ def is_map_message?
241
+ respond_to? :get_long
242
+ end
243
+ end
244
+ end
data/sample/sample.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'jsparrow'
3
+
4
+ JSparrow::Connection.configure do |connection|
5
+ connection.use_jms_client_jar '/opt/openjms/lib/openjms-0.7.7-beta-1.jar'
6
+
7
+ connection.use_jndi_properties :initial_context_factory => 'org.exolab.jms.jndi.InitialContextFactory',
8
+ :provider_url => 'tcp://localhost:3035'
9
+ # :security_principal => 'user',
10
+ # :security_credentials => 'password'
11
+
12
+ connection.enable_connection_factories :queue_connection_factory => 'ConnectionFactory',
13
+ :topic_connection_factory => 'ConnectionFactory'
14
+ end
15
+
16
+ jms_client = JSparrow::Connection.new_client
17
+ jms_client.enable_queues :pardal_queue => 'PardalQueue'
18
+
19
+ jms_client.start
20
+
21
+ jms_client.queue_sender(:pardal_queue).send_text_message('jsparrow rocks!') do |msg|
22
+ msg.set_string_property('recipient', 'jsparrow-example')
23
+ end
24
+
25
+ jms_client.queue_receiver(:pardal_queue).receive_message(
26
+ :timeout => 5000,
27
+ :selector => "recipient = 'jsparrow-example'"
28
+ ) do |msg|
29
+
30
+ puts "is text message? #{msg.is_text_message?}" # is text message? true
31
+ puts "message: #{msg.text}" # message: jsparrow rocks!
32
+ end
33
+
34
+ jms_client.stop
@@ -0,0 +1,120 @@
1
+ require File.dirname(File.expand_path(__FILE__)) + '/spec_helper.rb'
2
+
3
+ #
4
+ # Cenario que testa o start e stop do cliente JMS.
5
+ #
6
+ describe JSparrow::Connection::Client, ', quando criado,' do
7
+
8
+ before(:all) do
9
+ @jms_client = create_jms_client
10
+ end
11
+
12
+ it 'deveria permitir ser iniciado e parado' do
13
+ @jms_client.start
14
+
15
+ @jms_client.is_started?.should be true
16
+ @jms_client.is_stoped?.should be false
17
+
18
+ @jms_client.stop
19
+
20
+ @jms_client.is_started?.should be false
21
+ @jms_client.is_stoped?.should be true
22
+ end
23
+ end
24
+
25
+ #
26
+ # Cenario de configuracao do cliente JMS, quando sao informadas as propriedades de ambiente
27
+ # para conexao com o servidor de aplicacoes e a inicializacao do contexto JNDI inicial,
28
+ # onde estao criadas as connection factories, queues e topics.
29
+ #
30
+ # Importante: nesse momento o cliente JMS ainda nao sera iniciado, ja que nao deve haver
31
+ # configuracao depois inicia-lo.
32
+ #
33
+ describe JSparrow::Connection::Client, ', quando esta sendo configurado, mas ainda nao iniciado,' do
34
+
35
+ before(:all) do
36
+ @jms_client = create_jms_client
37
+ end
38
+
39
+ it 'deveria ter uma connection factory especifica para queues' do
40
+ @jms_client.queue_connection_factory_enabled?.should be true
41
+ end
42
+
43
+ it 'deveria ter uma connection factory especifica para topics' do
44
+ @jms_client.topic_connection_factory_enabled?.should be true
45
+ end
46
+
47
+ it 'deveria permitir habilitar uma Queue especifica' do
48
+ @jms_client.enable_queues :pardal_queue => 'PardalQueue'
49
+
50
+ @jms_client.queue_enabled?(:pardal_queue).should eql true
51
+ end
52
+
53
+ it 'deveria permitir habilitar um Topic especifico' do
54
+ @jms_client.enable_topics :pardal_topic => 'PardalTopic'
55
+
56
+ @jms_client.topic_enabled?(:pardal_topic).should eql true
57
+ end
58
+ end
59
+
60
+ #
61
+ # Cenario de configuracao do cliente JMS apos ter sido iniciado.
62
+ #
63
+ # Importante: Como o cliente JMS ja esta iniciado, deve lancar erro, nao permitindo
64
+ # qualquer configuracao.
65
+ #
66
+ describe JSparrow::Connection::Client, ', quando esta sendo configurado, apos iniciado,' do
67
+
68
+ before(:all) do
69
+ @jms_client = create_jms_client
70
+ @jms_client.start
71
+ end
72
+
73
+ after(:all) do
74
+ @jms_client.stop
75
+ end
76
+
77
+ it 'nao deveria permitir habilitar uma Queue especifica' do
78
+ lambda {
79
+ @jms_client.enable_queues(:pardal_queue => 'PardalQueue')
80
+ }.should raise_error JSparrow::Connection::InvalidClientStateError
81
+ end
82
+
83
+ it 'nao deveria permitir habilitar um Topic especifico' do
84
+ lambda {
85
+ @jms_client.enable_topics(:pardal_topic => 'PardalTopic')
86
+ }.should raise_error JSparrow::Connection::InvalidClientStateError
87
+ end
88
+ end
89
+
90
+ #
91
+ # Cenario pos-configuracao do cliente JMS, quando as queues e os topicos ja devem estar
92
+ # disponiveis, e entao e possivel obter sender/receiver para elas.
93
+ #
94
+ describe JSparrow::Connection::Client, ', depois de ter sido configurado,' do
95
+
96
+ before(:all) do
97
+ @jms_client = create_and_setup_jms_client
98
+ @jms_client.start
99
+ end
100
+
101
+ after(:all) do
102
+ @jms_client.stop
103
+ end
104
+
105
+ it 'deveria possibilitar obter um Sender para uma Queue especifica' do
106
+ @jms_client.queue_sender(:pardal_queue).should_not be nil
107
+ end
108
+
109
+ it 'deveria possibilitar obter um Receiver para uma Queue especifica' do
110
+ @jms_client.queue_receiver(:pardal_queue).should_not be nil
111
+ end
112
+
113
+ it 'deveria possibilitar obter um Sender para um Topic especifico' do
114
+ @jms_client.topic_sender(:pardal_topic).should_not be nil
115
+ end
116
+
117
+ it 'deveria possibilitar obter um Receiver para um Topic especifico' do
118
+ @jms_client.topic_receiver(:pardal_topic).should_not be nil
119
+ end
120
+ end
@@ -0,0 +1,142 @@
1
+ require File.dirname(File.expand_path(__FILE__)) + '/spec_helper.rb'
2
+
3
+ #
4
+ # Cenario pos-obtencao de um Sender e um Receiver, quando deve ser possivel enviar e
5
+ # receber mensagens de tres tipos (Texto, Objeto e Mapa) de uma queue especifica,
6
+ # individualmente ou em lote.
7
+ #
8
+ describe JSparrow::Messaging, ', quando tem um Sender e um Receiver para uma Queue especifica,' do
9
+
10
+ before(:all) do
11
+ @jms_client = create_and_setup_jms_client
12
+ @jms_client.start
13
+
14
+ @sender = @jms_client.queue_sender(:pardal_queue)
15
+ @receiver = @jms_client.queue_receiver(:pardal_queue)
16
+ end
17
+
18
+ after(:all) do
19
+ @jms_client.stop
20
+ end
21
+
22
+ it 'deveria possibilitar enviar uma mensagem de texto e recebe-la' do
23
+ my_text = 'Mensagem de texto enviada da spec'
24
+
25
+ @sender.send_text_message(my_text) do |msg|
26
+ msg.set_string_property('recipient', 'jsparrow-spec')
27
+ end
28
+
29
+ received_text = nil
30
+
31
+ @receiver.receive_message(:selector => "recipient = 'jsparrow-spec'") do |msg|
32
+ received_text = msg.text
33
+ end
34
+
35
+ received_text.should eql my_text
36
+ end
37
+
38
+ it 'deveria possibilitar enviar um objeto e recebe-lo' do
39
+ my_object = java.util.ArrayList.new
40
+ my_object << 'Obj1 enviado da spec'
41
+
42
+ @sender.send_object_message(my_object) do |msg|
43
+ msg.set_string_property('recipient', 'jsparrow-spec')
44
+ end
45
+
46
+ received_object = nil
47
+
48
+ @receiver.receive_message(:selector => "recipient = 'jsparrow-spec'") do |msg|
49
+ received_object = msg.object
50
+ end
51
+
52
+ received_object.should eql my_object
53
+ end
54
+
55
+ it 'deveria possibilitar enviar uma mensagem mapa e recebe-la' do
56
+ my_id_long = 1234567
57
+
58
+ @sender.send_map_message do |msg|
59
+ msg.set_string_property('recipient', 'jsparrow-spec')
60
+ msg.set_long('id', my_id_long)
61
+ end
62
+
63
+ received_id_long = nil
64
+
65
+ @receiver.receive_message(:selector => "recipient = 'jsparrow-spec'") do |msg|
66
+ received_id_long = msg.get_long('id')
67
+ end
68
+
69
+ received_id_long.should eql my_id_long
70
+ end
71
+
72
+ it 'deveria possibilitar enviar varias mensagens de qualquer tipo e recebe-las' do
73
+ my_text = 'Mensagem de texto enviada da spec'
74
+
75
+ my_object = java.util.ArrayList.new
76
+ my_object << 'Obj1 enviado da spec'
77
+
78
+ my_id_long = 1234567
79
+
80
+ @sender.send_messages do |session, producer|
81
+ #--- TextMessage
82
+ text_message = session.create_text_message(my_text)
83
+ text_message.set_string_property('recipient', 'jsparrow-spec')
84
+ producer.send(text_message)
85
+
86
+ #--- objectMessage
87
+ object_message = session.create_object_message(my_object)
88
+ object_message.set_string_property('recipient', 'jsparrow-spec')
89
+ producer.send(object_message)
90
+
91
+ #--- MapMessage
92
+ map_message = session.create_map_message
93
+ map_message.set_string_property('recipient', 'jsparrow-spec')
94
+ map_message.set_long('id', my_id_long)
95
+ producer.send(map_message)
96
+
97
+ # Commita as tres mensagens enviadas na sessao
98
+ session.commit
99
+ end
100
+
101
+ received_text = nil
102
+ received_object = nil
103
+ received_id_long = nil
104
+
105
+ @receiver.receive_message(:timeout => 1000, :selector => "recipient = 'jsparrow-spec'") do |msg|
106
+ if msg.is_text_message?
107
+ received_text = msg.text
108
+ end
109
+
110
+ if msg.is_object_message?
111
+ received_object = msg.object
112
+ end
113
+
114
+ if msg.is_map_message?
115
+ received_id_long = msg.get_long('id')
116
+ end
117
+ end
118
+
119
+ received_text.should eql my_text
120
+ received_object.should eql my_object
121
+ received_id_long.should eql my_id_long
122
+ end
123
+ end
124
+
125
+ #
126
+ # Cenario pos-configuracao do cliente JMS, quando deve ser possivel escutar mensagens
127
+ # atraves de objetos listeners.
128
+ #
129
+ describe JSparrow::Messaging::Listener,
130
+ ', quando um Listener se registra para escutar uma Queue especifica,' do
131
+
132
+ before(:all) do
133
+ @jms_client = create_jms_client
134
+ @jms_client.start
135
+ end
136
+
137
+ after(:all) do
138
+ @jms_client.stop
139
+ end
140
+
141
+ it 'deveria possibilitar escutar mensagens atraves de um listener'
142
+ end
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.dirname(File.expand_path(__FILE__)) + '/../lib/jsparrow.rb'
5
+
6
+ #
7
+ # Modulo com metodos uteis para as specs.
8
+ #
9
+ module JSparrowHelperMethods
10
+
11
+ #
12
+ # Apenas cria, mas nao faz o setup do cliente JMS.
13
+ #
14
+ def create_jms_client
15
+ configure_connection
16
+
17
+ JSparrow::Connection.new_client
18
+ end
19
+
20
+ def create_and_setup_jms_client
21
+ configure_connection
22
+
23
+ jms_client = JSparrow::Connection.new_client
24
+ jms_client.enable_queues :pardal_queue => 'PardalQueue'
25
+ jms_client.enable_topics :pardal_topic => 'PardalTopic'
26
+
27
+ jms_client
28
+ end
29
+
30
+ # --- Private methods --- #
31
+ private
32
+
33
+ def configure_connection
34
+ JSparrow::Connection.configure do |connection|
35
+ connection.use_jms_client_jar '/opt/openjms/lib/openjms-0.7.7-beta-1.jar'
36
+
37
+ connection.use_jndi_properties :initial_context_factory => 'org.exolab.jms.jndi.InitialContextFactory',
38
+ :provider_url => 'tcp://localhost:3035'
39
+ # :security_principal => 'user',
40
+ # :security_credentials => 'password'
41
+
42
+ connection.enable_connection_factories :queue_connection_factory => 'ConnectionFactory',
43
+ :topic_connection_factory => 'ConnectionFactory'
44
+ end
45
+ end
46
+ end
47
+
48
+ #
49
+ # Enriquece a classe Spec::Example::ExampleGroup com o helper.
50
+ #
51
+ class Spec::Example::ExampleGroup
52
+ include JSparrowHelperMethods
53
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsparrow
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leandro Silva
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-15 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: leandrodoze@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION.yml
30
+ - lib/connection.rb
31
+ - lib/error.rb
32
+ - lib/jms.rb
33
+ - lib/jms/javaee-1.5.jar
34
+ - lib/jms/jms.jar
35
+ - lib/jms/jsparrow-essential.jar
36
+ - lib/jsparrow.rb
37
+ - lib/messaging.rb
38
+ - sample/sample.rb
39
+ - spec/connection_spec.rb
40
+ - spec/messaging_spec.rb
41
+ - spec/spec_helper.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/leandrosilva/jsparrow
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.5
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: JSparrow is a JMS client based on JRuby
70
+ test_files:
71
+ - spec/connection_spec.rb
72
+ - spec/messaging_spec.rb
73
+ - spec/spec_helper.rb