jsparrow 1.1.0

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.
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