jsparrow 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -70,7 +70,7 @@ jsparrow rocks! =)
70
70
 
71
71
  Or, if you don't want write code, only do it:
72
72
 
73
- jruby sample/sample.rb
73
+ jruby sample/sample_queue.rb
74
74
 
75
75
  == Copyright
76
76
 
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 1
3
2
  :major: 1
4
- :build:
5
3
  :minor: 1
4
+ :patch: 2
5
+ :build:
data/lib/client.rb CHANGED
@@ -9,9 +9,8 @@ module JSparrow
9
9
  # que prove o servico JMS.
10
10
  #
11
11
  class Client
12
- def initialize(connection_config, jndi_context_builder)
13
- @connection_config = connection_config
14
- @jndi_context_builder = jndi_context_builder
12
+ def initialize(connection)
13
+ @connection = connection
15
14
 
16
15
  # Conexoes, filas, topicos, senders e receivers que serao habilitados
17
16
  @connection_factories = {}
@@ -21,51 +20,28 @@ module JSparrow
21
20
  @topics = {}
22
21
  @topic_senders = {}
23
22
  @topic_receivers = {}
24
-
25
- # Foi iniciado?
26
- @started = false
27
23
  end
28
24
 
29
25
  def is_started?
30
- @started
26
+ @connection.is_opened?
31
27
  end
32
28
 
33
29
  def start
34
- raise InvalidClientStateError.new('started', 'start') if is_started?
35
-
36
- begin
37
- @jndi_context = @jndi_context_builder.build
38
- rescue => cause
39
- raise ClientInitializationError.new(@connection_config, cause)
40
- end
30
+ @connection.open
41
31
 
42
32
  @connection_factories, @queues, @topics = lookup_resources
43
-
44
- @started = true
45
33
  end
46
34
 
47
35
  def is_stoped?
48
- !@started
36
+ @connection.is_closed?
49
37
  end
50
38
 
51
39
  def stop
52
- raise InvalidClientStateError.new('stoped', 'stop') if is_stoped?
53
-
54
- @jndi_context.close
55
-
56
- @started = false
57
- end
58
-
59
- def queue_connection_factory_enabled?
60
- @connection_config.enabled_connection_factories.include?(:queue_connection_factory)
40
+ @connection.close
61
41
  end
62
42
 
63
- def queue_connection_factory
64
- @connection_factories[:queue_connection_factory]
65
- end
66
-
67
43
  def queue_enabled?(queue_name)
68
- @connection_config.enabled_queues.include?(queue_name)
44
+ @connection.configuration.enabled_queues.include?(queue_name)
69
45
  end
70
46
 
71
47
  def queue(queue_name)
@@ -84,16 +60,8 @@ module JSparrow
84
60
  Messaging::Receiver.new(queue_connection_factory, queue(queue_name))
85
61
  end
86
62
 
87
- def topic_connection_factory_enabled?
88
- @connection_config.enabled_connection_factories.include?(:topic_connection_factory)
89
- end
90
-
91
- def topic_connection_factory
92
- @connection_factories[:topic_connection_factory]
93
- end
94
-
95
63
  def topic_enabled?(topic_name)
96
- @connection_config.enabled_topics.include?(topic_name)
64
+ @connection.configuration.enabled_topics.include?(topic_name)
97
65
  end
98
66
 
99
67
  def topic(topic_name)
@@ -115,47 +83,21 @@ module JSparrow
115
83
  # -- Private methods -- #
116
84
  private
117
85
 
118
- def lookup_resources
119
- @lookuped_connection_factories = lookup_resource(@connection_config.enabled_connection_factories)
120
- @lookuped_queues = lookup_resource(@connection_config.enabled_queues)
121
- @lookuped_topic = lookup_resource(@connection_config.enabled_topics)
122
-
123
- return @lookuped_connection_factories, @lookuped_queues, @lookuped_topic
86
+ def queue_connection_factory
87
+ @connection_factories[:queue_connection_factory]
124
88
  end
125
89
 
126
- def lookup_resource(jndi_names = {})
127
- lookuped = {}
128
-
129
- return lookuped unless jndi_names
130
-
131
- jndi_names.each do |key, jndi_name|
132
- lookuped[key] = @jndi_context.lookup(jndi_name)
133
- end
134
-
135
- lookuped
90
+ def topic_connection_factory
91
+ @connection_factories[:topic_connection_factory]
136
92
  end
137
- end
138
-
139
- class ClientInitializationError < StandardError
140
- attr_reader :config, :cause
141
-
142
- def initialize(config, cause)
143
- super("Could not open connection to server. Verify the config's config.")
144
-
145
- @config = config
146
- @cause = cause
147
- end
148
- end
149
-
150
- class InvalidClientStateError < StandardError
151
- attr_reader :state, :operation
152
93
 
153
- def initialize(state, operation)
154
- super("Could not did #{operation} because client is #{state}.")
155
-
156
- @state = state
157
- @operation = operation
158
- end
94
+ def lookup_resources
95
+ lookuped_connection_factories = @connection.lookup_resources(@connection.configuration.enabled_connection_factories)
96
+ lookuped_queues = @connection.lookup_resources(@connection.configuration.enabled_queues)
97
+ lookuped_topic = @connection.lookup_resources(@connection.configuration.enabled_topics)
98
+
99
+ return lookuped_connection_factories, lookuped_queues, lookuped_topic
100
+ end
159
101
  end
160
102
  end
161
103
  end
data/lib/connection.rb CHANGED
@@ -9,27 +9,97 @@ module JSparrow
9
9
  # Metodo usado para configurar a conexao com o provedor de JMS.
10
10
  #
11
11
  def self.configure
12
- @@config = Configuration.new
12
+ @@configuration = Configuration.new
13
13
 
14
- yield @@config
14
+ yield @@configuration
15
15
 
16
- @@config
16
+ @@jndi_context_builder = JNDI::ContextBuilder.new(@@configuration.jms_client_jar, @@configuration.jndi_properties)
17
+
18
+ @@configuration
17
19
  end
18
20
 
19
21
  #
20
22
  # Metodo usado para obter a configuracao para conexao com o provedor de JMS.
21
23
  #
22
24
  def self.configuration
23
- @@config
25
+ @@configuration
24
26
  end
25
27
 
26
28
  #
27
29
  # Metodo usado para criar um novo Client JMS.
28
30
  #
29
31
  def self.new_client
30
- jndi_context_builder = JNDI::ContextBuilder.new(@@config.jms_client_jar, @@config.jndi_properties)
32
+ connection = Base.new(@@configuration, @@jndi_context_builder)
33
+
34
+ Client.new(connection)
35
+ end
36
+
37
+ #
38
+ # Metodo usado para criar um novo Listener de mensagens JMS.
39
+ #
40
+ def self.new_listener(listener_spec)
41
+ connection = Base.new(@@configuration, @@jndi_context_builder)
31
42
 
32
- Client.new(@@config, jndi_context_builder)
43
+ listener_spec[:as].new(connection)
44
+ end
45
+
46
+ #
47
+ # Classe base para estabelecer conexao com o provedor JMS via JNDI.
48
+ #
49
+ class Base
50
+ attr_reader :configuration
51
+
52
+ def initialize(configuration, jndi_context_builder)
53
+ @configuration = configuration
54
+ @jndi_context_builder = jndi_context_builder
55
+
56
+ # Foi estabelecida?
57
+ @opened = false
58
+ end
59
+
60
+ def is_opened?
61
+ @opened
62
+ end
63
+
64
+ def open
65
+ raise InvalidStateError.new('opened', 'open') if is_opened?
66
+
67
+ begin
68
+ @jndi_context = @jndi_context_builder.build
69
+ rescue => cause
70
+ raise InitializationError.new(@configuration, cause)
71
+ end
72
+
73
+ @opened = true
74
+ end
75
+
76
+ def is_closed?
77
+ not @opened
78
+ end
79
+
80
+ def close
81
+ raise InvalidStateError.new('closed', 'close') if is_closed?
82
+
83
+ @jndi_context.close
84
+
85
+ @opened = false
86
+ end
87
+
88
+ def lookup_resources(resources = {})
89
+ lookuped_resource = {}
90
+
91
+ return lookuped_resource unless resources
92
+
93
+ resources.each do |name, jndi_name|
94
+ lookuped_resource[name] = lookup_resource(jndi_name)
95
+ end
96
+
97
+ lookuped_resource
98
+ end
99
+
100
+ def lookup_resource(jndi_name)
101
+ @jndi_context.lookup(jndi_name)
102
+ end
33
103
  end
34
104
 
35
105
  #
@@ -40,26 +110,83 @@ module JSparrow
40
110
  attr_reader :jms_client_jar, :jndi_properties,
41
111
  :enabled_connection_factories, :enabled_queues, :enabled_topics
42
112
 
113
+ #
114
+ # Use:
115
+ #
116
+ # use_jms_client_jar "path/to/name_of_the_client_jar_file.jar"
117
+ #
43
118
  def use_jms_client_jar(client_jar)
44
119
  @jms_client_jar = client_jar
45
120
  end
46
121
 
122
+ #
123
+ # Use:
124
+ #
125
+ # use_jndi_properties :a_jndi_property_name_in_lower_case => "a_value_of_property",
126
+ # :other_jndi_property_name_in_lower_case => "other_value_of_property"
127
+ #
47
128
  def use_jndi_properties(jndi_properties = {})
48
129
  @jndi_properties = jndi_properties
49
130
  end
50
131
 
132
+ #
133
+ # Use:
134
+ #
135
+ # enable_connection_factories :queue_connection_factory => "jndi_name_of_queue_connection_factory",
136
+ # :topic_connection_factory => "jndi_name_of_topic_connection_factory"
137
+ #
51
138
  def enable_connection_factories(jndi_names = {})
52
139
  @enabled_connection_factories = jndi_names
53
140
  end
54
141
 
142
+ #
143
+ # Use:
144
+ #
145
+ # enable_queues :a_queue_name_in_lower_case => "jndi_name_of_a_queue",
146
+ # :other_queue_name_in_lower_case => "jndi_name_of_other_queue"
147
+ #
55
148
  def enable_queues(jndi_names = {})
56
149
  @enabled_queues = jndi_names
57
150
  end
58
151
 
152
+ #
153
+ # Use:
154
+ #
155
+ # enable_topics :a_topic_name_in_lower_case => "jndi_name_of_a_topic",
156
+ # :other_topic_name_in_lower_case => "jndi_name_of_other_topic"
157
+ #
59
158
  def enable_topics(jndi_names = {})
60
159
  @enabled_topics = jndi_names
61
160
  end
62
161
  end
162
+
163
+ #
164
+ # Erro para quando uma conexao esta num estado invalido para uma operacao (open ou close).
165
+ #
166
+ class InvalidStateError < StandardError
167
+ attr_reader :state, :operation
168
+
169
+ def initialize(state, operation)
170
+ super("Could not did #{operation} because connection is #{state}.")
171
+
172
+ @state = state
173
+ @operation = operation
174
+ end
175
+ end
176
+
177
+ #
178
+ # Erro para quando nao for possivel estabelecer conexao com o provedor JMS.
179
+ #
180
+ class InitializationError < StandardError
181
+ attr_reader :configuration, :cause
182
+
183
+ def initialize(configuration, cause)
184
+ super("Could not open connection to JMS provider. Verify the config's config.")
185
+
186
+ @configuration = configuration
187
+ @cause = cause
188
+ end
189
+ end
63
190
  end
64
191
 
65
192
  module JNDI
data/lib/jsparrow.rb CHANGED
@@ -6,5 +6,6 @@ require 'jms.rb'
6
6
  # Bibliotecas do JSparrow
7
7
  require 'connection.rb'
8
8
  require 'client.rb'
9
+ require 'listener.rb'
9
10
  require 'messaging.rb'
10
11
  require 'error.rb'
data/lib/listener.rb ADDED
@@ -0,0 +1,146 @@
1
+ # Classes Java usadas nesse arquivo
2
+ import 'javax.naming.InitialContext'
3
+ import 'javax.jms.MessageListener'
4
+
5
+ module JSparrow
6
+ module Connection
7
+
8
+ #
9
+ # Ouvintes de mensagens.
10
+ #
11
+ # Sao como clientes JMS, mas apenas para recebimento de mensagens.
12
+ #
13
+ class Listener
14
+ include MessageListener
15
+
16
+ #
17
+ # Nome (configurado no setup da conexao) do destino JMS que sera escutado.
18
+ #
19
+ # Invariavelmente deve ser usado pelas subclasses, para informar o nome da queue
20
+ # ou topico que sera escutado.
21
+ #
22
+ # listen_to :queue => :registered_name_of_queue
23
+ # listen_to :topic => :registered_name_of_topic
24
+ #
25
+ def self.listen_to(destination)
26
+ configure(:listen_to_destination, destination)
27
+ end
28
+
29
+ #
30
+ # Criterios de selecao de mensagens, seguindo o padrao JMS.
31
+ #
32
+ # Invariavelmente as subclasses precisam usar esse metodo, se quiserem definir
33
+ # os criterios de recebimento que este listener levara em conta.
34
+ #
35
+ # receive_only_in_criteria :selector => "recipient = 'jsparrow-spec' and to_listener = 'TestQueueListener'"
36
+ #
37
+ def self.receive_only_in_criteria(criteria = {:selector => ''})
38
+ configure(:criteria_to_receiving, criteria)
39
+ end
40
+
41
+ def initialize(connection)
42
+ @connection = connection
43
+ end
44
+
45
+ def is_listening?
46
+ @connection.is_opened?
47
+ end
48
+
49
+ #
50
+ # Inicia a escuta de mensagens.
51
+ #
52
+ def start_listening
53
+ @connection.open
54
+
55
+ connection_factory, destination = lookup_resources
56
+
57
+ selector = criteria_to_receiving[:selector] if respond_to? :criteria_to_receiving
58
+
59
+ # Cria uma conexao para escuta de mensagens
60
+ @listening_connection = connection_factory.create_connection
61
+
62
+ # Cria uma sessao e um consumidor de qualquer tipo de mensagem
63
+ session = @listening_connection.create_session(false, Session::AUTO_ACKNOWLEDGE)
64
+ consumer = session.create_consumer(destination, selector)
65
+
66
+ # Registra-se como ouvinte
67
+ consumer.message_listener = self
68
+
69
+ # Inicia a escuta de mensagens
70
+ @listening_connection.start
71
+ end
72
+
73
+ #
74
+ # Finaliza a escuta de mensagens.
75
+ #
76
+ def stop_listening
77
+ @listening_connection.close
78
+
79
+ @connection.close
80
+ end
81
+
82
+ #
83
+ # Faz o enriquecimento do objeto mensagem e delega para o metodo on_receive_message
84
+ # que, implementado pelas subclasses, efetivamente trata a mensagem.
85
+ #
86
+ # Nao deve ser re-implementado por subclasses.
87
+ #
88
+ def on_message(received_message)
89
+ class << received_message
90
+ include Messaging::MessageType
91
+ end
92
+
93
+ on_receive_message(received_message)
94
+ end
95
+
96
+ #
97
+ # E executado todas as vezes que chega uma mensagem que atenda aos criterios
98
+ # definido para este listener (na variavel de instancia @criteria_for_receiving).
99
+ #
100
+ # Invariavelmente deve ser re-implementado nas subclasses.
101
+ #
102
+ def on_receive_message(received_message)
103
+ raise Error::AbstractMethodError.new(self.class.superclass, 'on_receive_message')
104
+ end
105
+
106
+ # --- Private methods --- #
107
+ private
108
+
109
+ def self.configure(attribute, value)
110
+ self.instance_eval do
111
+ send(:define_method, attribute) do
112
+ value
113
+ end
114
+ end
115
+ end
116
+
117
+ def lookup_resources
118
+ destination_type, destination_name = get_destination_info
119
+
120
+ jndi_name_of_connection_factory = get_jndi_name_of_connection_factory(destination_type, destination_name)
121
+ jndi_name_of_destination = get_jndi_name_of_destination(destination_type, destination_name)
122
+
123
+ lookuped_connection_factory = @connection.lookup_resource(jndi_name_of_connection_factory)
124
+ lookuped_destination = @connection.lookup_resource(jndi_name_of_destination)
125
+
126
+ return lookuped_connection_factory, lookuped_destination
127
+ end
128
+
129
+ def get_destination_info
130
+ return listen_to_destination.keys[0], listen_to_destination.values[0]
131
+ end
132
+
133
+ def get_jndi_name_of_connection_factory(destination_type, destination_name)
134
+ connection_factory_name = "#{destination_type}_connection_factory".to_sym
135
+
136
+ @connection.configuration.enabled_connection_factories[connection_factory_name]
137
+ end
138
+
139
+ def get_jndi_name_of_destination(destination_type, destination_name)
140
+ enabled_method_for_destinations = "enabled_#{destination_type}s"
141
+
142
+ @connection.configuration.send(enabled_method_for_destinations)[destination_name]
143
+ end
144
+ end
145
+ end
146
+ end
data/lib/messaging.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # Classes Java usadas nesse arquivo
2
2
  import 'javax.jms.Session'
3
- import 'javax.jms.MessageListener'
4
3
 
5
4
  module JSparrow
6
5
  module Messaging
@@ -80,22 +79,22 @@ module JSparrow
80
79
  # --- Private methods --- #
81
80
  private
82
81
 
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)
82
+ def send_message(&message_creator)
83
+ # Cria uma conexao, uma sessao e um emissor de qualquer tipo de mensagem
84
+ connection = @connection_factory.create_connection
85
+ session = connection.create_session(true, Session::AUTO_ACKNOWLEDGE)
86
+ producer = session.create_producer(@destination)
88
87
 
89
- # Obtem uma mensagem (TextMessage, ObjectMessage ou MapMessage) do criador especifico
90
- message = message_creator.call(session)
88
+ # Obtem uma mensagem (TextMessage, ObjectMessage ou MapMessage) do criador especifico
89
+ message = message_creator.call(session)
91
90
 
92
- # Envia a mensagem
93
- producer.send(message)
91
+ # Envia a mensagem
92
+ producer.send(message)
94
93
 
95
- # Commita a sessao e fecha a conexao
96
- session.commit
97
- connection.close
98
- end
94
+ # Commita a sessao e fecha a conexao
95
+ session.commit
96
+ connection.close
97
+ end
99
98
  end
100
99
 
101
100
  #
@@ -128,117 +127,22 @@ module JSparrow
128
127
  connection.close
129
128
  end
130
129
  end
131
-
132
- #
133
- # Ouvintes de mensagens.
130
+
134
131
  #
135
- # TODO: Completar a implementacao. Ainda nao esta legal. (Ja dei um tapinha,
136
- # acho que agora ta bem proximo do que deve ser.)
132
+ # Identifica o tipo de uma mensagem.
137
133
  #
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
134
+ module MessageType
135
+ def is_text_message?
136
+ respond_to? :get_text
163
137
  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
138
 
236
- def is_object_message?
237
- (respond_to? :get_object and !(respond_to? :get_long))
238
- end
139
+ def is_object_message?
140
+ (respond_to? :get_object and !(respond_to? :get_long))
141
+ end
239
142
 
240
- def is_map_message?
241
- respond_to? :get_long
143
+ def is_map_message?
144
+ respond_to? :get_long
145
+ end
242
146
  end
243
147
  end
244
148
  end
File without changes