activemessaging 0.6.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.
Files changed (46) hide show
  1. data/Rakefile +50 -0
  2. data/generators/a13g_test_harness/a13g_test_harness_generator.rb +19 -0
  3. data/generators/a13g_test_harness/templates/active_messaging_test.rhtml +13 -0
  4. data/generators/a13g_test_harness/templates/active_messaging_test_controller.rb +29 -0
  5. data/generators/a13g_test_harness/templates/index.rhtml +17 -0
  6. data/generators/filter/USAGE +0 -0
  7. data/generators/filter/filter_generator.rb +19 -0
  8. data/generators/filter/templates/filter.rb +12 -0
  9. data/generators/filter/templates/filter_test.rb +28 -0
  10. data/generators/processor/USAGE +8 -0
  11. data/generators/processor/processor_generator.rb +31 -0
  12. data/generators/processor/templates/application.rb +18 -0
  13. data/generators/processor/templates/broker.yml +79 -0
  14. data/generators/processor/templates/jruby_poller +117 -0
  15. data/generators/processor/templates/messaging.rb +12 -0
  16. data/generators/processor/templates/poller +23 -0
  17. data/generators/processor/templates/poller.rb +23 -0
  18. data/generators/processor/templates/processor.rb +8 -0
  19. data/generators/processor/templates/processor_test.rb +20 -0
  20. data/generators/tracer/USAGE +8 -0
  21. data/generators/tracer/templates/controller.rb +14 -0
  22. data/generators/tracer/templates/helper.rb +2 -0
  23. data/generators/tracer/templates/index.rhtml +4 -0
  24. data/generators/tracer/templates/layout.rhtml +16 -0
  25. data/generators/tracer/templates/trace_processor.rb +100 -0
  26. data/generators/tracer/tracer_generator.rb +25 -0
  27. data/lib/activemessaging.rb +133 -0
  28. data/lib/activemessaging/adapter.rb +21 -0
  29. data/lib/activemessaging/adapters/asqs.rb +412 -0
  30. data/lib/activemessaging/adapters/base.rb +82 -0
  31. data/lib/activemessaging/adapters/jms.rb +237 -0
  32. data/lib/activemessaging/adapters/reliable_msg.rb +190 -0
  33. data/lib/activemessaging/adapters/stomp.rb +99 -0
  34. data/lib/activemessaging/adapters/test.rb +155 -0
  35. data/lib/activemessaging/adapters/wmq.rb +202 -0
  36. data/lib/activemessaging/filter.rb +29 -0
  37. data/lib/activemessaging/gateway.rb +422 -0
  38. data/lib/activemessaging/message_sender.rb +30 -0
  39. data/lib/activemessaging/named_base.rb +54 -0
  40. data/lib/activemessaging/processor.rb +45 -0
  41. data/lib/activemessaging/support.rb +17 -0
  42. data/lib/activemessaging/test_helper.rb +194 -0
  43. data/lib/activemessaging/trace_filter.rb +34 -0
  44. data/messaging.rb.example +5 -0
  45. data/tasks/start_consumers.rake +8 -0
  46. metadata +123 -0
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/rdoc'
4
+ require 'rake/gempackagetask'
5
+
6
+ desc 'Default: run unit tests.'
7
+ task :default => :test
8
+
9
+ desc 'Test the ActiveMessaging plugin.'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'lib'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the ActiveMessaging plugin.'
17
+ task :rdoc do
18
+ rm_rf 'doc'
19
+ RDoc::RDoc.new.document(%w(--line-numbers --inline-source --title ActiveMessaging README lib))
20
+ end
21
+
22
+ gem_spec = Gem::Specification.new do |s|
23
+ s.name = %q{activemessaging}
24
+ s.version = "0.6.0"
25
+
26
+ s.specification_version = 2 if s.respond_to? :specification_version=
27
+
28
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
29
+ s.authors = ["jon.tirsen", "kookster", "olle.jonsson", "sylvain.perez", "anti.god.botherer", 'uwe.kubosch']
30
+ s.date = %q{2008-08-15}
31
+ s.description = %q{ActiveMessaging is an attempt to bring the simplicity and elegance of rails development to the world of messaging. Messaging, (or event-driven architecture) is widely used for enterprise integration, with frameworks such as Java's JMS, and products such as ActiveMQ, Tibco, IBM MQSeries, etc.}
32
+ s.email = %q{activemessaging-discuss@googlegroups.com}
33
+ s.files = FileList['generators/**/*', 'lib/**/*', 'tasks/**/*', 'Rakefile', 'messaging.rb.example'].to_a
34
+ s.homepage = %q{http://code.google.com/p/activemessaging/}
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.2.0}
37
+ s.summary = %q{ActiveMessaging is an attempt to bring the simplicity and elegance of rails development to the world of messaging. Messaging, (or event-driven architecture) is widely used for enterprise integration, with frameworks such as Java's JMS, and products such as ActiveMQ, Tibco, IBM MQSeries, etc.}
38
+ #s.test_files = ["test"]
39
+ #s.autorequire = 'activemessaging'
40
+ s.has_rdoc = true
41
+
42
+ s.add_dependency(%q<activesupport>, [">= 1.0.0"])
43
+ s.add_dependency(%q<rubigen>, [">= 1.5.2"])
44
+ #s.add_dependency(%q<common-pool-cliffmoon>, [">= 0.0.3"])
45
+ end
46
+
47
+ desc 'Generate ActiveMessaging gem.'
48
+ Rake::GemPackageTask.new(gem_spec) do |pkg|
49
+ end
50
+
@@ -0,0 +1,19 @@
1
+ class A13gTestHarnessGenerator < RubiGen::Base
2
+ def manifest
3
+ record do |m|
4
+
5
+ controller_path = 'app/controllers'
6
+ m.directory controller_path
7
+ m.file 'active_messaging_test_controller.rb', File.join(controller_path, 'active_messaging_test_controller.rb')
8
+
9
+ view_path = 'app/views/active_messaging_test'
10
+ m.directory view_path
11
+ m.file 'index.rhtml', File.join(view_path, 'index.rhtml')
12
+
13
+ view_path = 'app/views/layouts'
14
+ m.directory view_path
15
+ m.file 'active_messaging_test.rhtml', File.join(view_path, 'active_messaging_test.rhtml')
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>ActiveMessaging Test Harness: <%= controller.action_name %></title>
4
+ <%= stylesheet_link_tag 'scaffold' %>
5
+ </head>
6
+ <body>
7
+
8
+ <p style="color: green"><%= flash[:notice] %></p>
9
+
10
+ <%= yield %>
11
+
12
+ </body>
13
+ </html>
@@ -0,0 +1,29 @@
1
+ class ActiveMessagingTestController < ApplicationController
2
+
3
+ include ActiveMessaging::MessageSender
4
+
5
+ def index
6
+ @destinations = ActiveMessaging::Gateway.named_destinations.values
7
+
8
+ if request.post?
9
+ @message = params[:message]
10
+
11
+ if params[:destination].nil? || params[:destination].empty?
12
+ flash[:notice] = "Please specify a destination."
13
+ return
14
+ else
15
+ @destination = params[:destination].intern
16
+ end
17
+
18
+ if @message.nil? || @message.empty?
19
+ flash[:notice] = "Please specify a message."
20
+ return
21
+ end
22
+
23
+ puts "#{@destination} : #{@message}"
24
+ publish @destination, @message
25
+ flash[:notice] = "'#{@message}' sent to #{@destination}"
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,17 @@
1
+ <h1>ActiveMessaging Test Harness</h1>
2
+
3
+ <% form_tag :action => 'index' do |f| %>
4
+ <p>
5
+ <label for="destination">Destination:</label><br/>
6
+ (broker: name => 'destination')<br/>
7
+ <select name="destination">
8
+ <option value=""></option>
9
+ <%= options_from_collection_for_select @destinations, 'name', 'to_s', @destination %>
10
+ </select>
11
+ </p>
12
+ <p>
13
+ <label for="message">Message:</label><br/>
14
+ <%= text_area_tag :message, @message, :size=>'50x10' %>
15
+ </p>
16
+ <%= submit_tag "submit" %>
17
+ <% end -%>
File without changes
@@ -0,0 +1,19 @@
1
+ class FilterGenerator < RubiGen::Base
2
+ def manifest
3
+ record do |m|
4
+ path = 'app/processors'
5
+ test_path = 'test/functional'
6
+
7
+ # Check for class naming collisions
8
+ m.class_collisions class_path, "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
9
+
10
+ # filter and test directories
11
+ m.directory File.join(path, class_path)
12
+ m.directory File.join(test_path, class_path)
13
+
14
+ # filter and test templates
15
+ m.template 'filter.rb', File.join(path, class_path, "#{file_name}_filter.rb")
16
+ m.template 'filter_test.rb', File.join(test_path, class_path, "#{file_name}_filter_test.rb")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ class <%= class_name %>Filter < ActiveMessaging::Filter
2
+
3
+ attr_accessor :options
4
+
5
+ def initialize(options={})
6
+ @options = options
7
+ end
8
+
9
+ def process(message, routing)
10
+ logger.debug "<%= class_name %>Filter filtering message: #{message.inspect} with routing: #{routing.inspect}"
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require File.dirname(__FILE__) + '/../../vendor/plugins/activemessaging/lib/activemessaging/test_helper'
3
+
4
+ class <%= class_name %>FilterTest < Test::Unit::TestCase
5
+ include ActiveMessaging::TestHelper
6
+
7
+ def setup
8
+ # if you want to write code to tests against the filter directly
9
+ load File.dirname(__FILE__) + "/../../app/processors/<%= file_name %>_filter.rb"
10
+ @options = {:direction=>:incoming, :only=>:<%= file_name %>_test}
11
+ @filter = <%= class_name %>Filter.new(@options)
12
+ @destination = ActiveMessaging::Gateway.destination :<%= file_name %>_test, '/queue/<%= file_name %>.test.queue'
13
+ end
14
+
15
+ def teardown
16
+ ActiveMessaging::Gateway.reset
17
+ @filter = nil
18
+ @destination = nil
19
+ @options = nil
20
+ end
21
+
22
+ def test_<%= file_name %>_filter
23
+ @message = ActiveMessaging::TestMessage.new(@destination.value, {'message-id'=>'test-message-id-header'}, 'message body')
24
+ @routing = {:direction=>:incoming, :destination=>@destination}
25
+ @filter.process(@message, @routing)
26
+ end
27
+
28
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates a stub ActiveMessaging Processor and associated test.
3
+
4
+ Examples:
5
+ ./script/generate processor HelloWorld
6
+ will create:
7
+ /app/processors/hello_world_processor.rb
8
+ /test/functional/hello_world_processor_test.rb
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../../lib/activemessaging/named_base'
2
+
3
+ class ProcessorGenerator < NamedBase
4
+ def manifest
5
+ record do |m|
6
+ path = 'app/processors'
7
+ test_path = 'test/functional'
8
+
9
+ # Check for class naming collisions.
10
+ m.class_collisions class_path, "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
11
+
12
+ # processor and test directories
13
+ m.directory File.join(path, class_path)
14
+ m.directory File.join(test_path, class_path)
15
+
16
+ # processor and test templates
17
+ m.template 'processor.rb', File.join(path, class_path, "#{file_name}_processor.rb")
18
+ m.template 'processor_test.rb', File.join(test_path, class_path, "#{file_name}_processor_test.rb")
19
+
20
+ m.template 'messaging.rb', File.join('config', "messaging.rb")
21
+ m.file 'broker.yml', File.join('config', "broker.yml")
22
+ m.file 'application.rb', File.join(path, "application.rb")
23
+ m.file 'poller.rb', File.join('lib', "poller.rb")
24
+ if defined?(JRUBY_VERSION)
25
+ m.file 'jruby_poller', File.join('script', "jruby_poller"), { :chmod => 0755 }
26
+ else
27
+ m.file 'poller', File.join('script', "poller"), { :chmod => 0755 }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ class ApplicationProcessor < ActiveMessaging::Processor
2
+
3
+ # Default on_error implementation - logs standard errors but keeps processing. Other exceptions are raised.
4
+ # Have on_error throw ActiveMessaging::AbortMessageException when you want a message to be aborted/rolled back,
5
+ # meaning that it can and should be retried (idempotency matters here).
6
+ # Retry logic varies by broker - see individual adapter code and docs for how it will be treated
7
+ def on_error(err)
8
+ if (err.kind_of?(StandardError))
9
+ logger.error "ApplicationProcessor::on_error: #{err.class.name} rescued:\n" + \
10
+ err.message + "\n" + \
11
+ "\t" + err.backtrace.join("\n\t")
12
+ else
13
+ logger.error "ApplicationProcessor::on_error: #{err.class.name} raised: " + err.message
14
+ raise err
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,79 @@
1
+ #
2
+ # broker.yml
3
+ #
4
+ # Simple yaml file for the env specific configuration of the broker connections.
5
+ # See the wiki for more information: http://code.google.com/p/activemessaging/wiki/Configuration
6
+ #
7
+ development:
8
+ ############################
9
+ # Stomp Adapter Properties #
10
+ ############################
11
+ adapter: stomp
12
+
13
+ # properties below are all defaults for this adapter
14
+ # login: ""
15
+ # passcode: ""
16
+ # host: localhost
17
+ # port: 61613
18
+ # reliable: true
19
+ # reconnectDelay: 5
20
+
21
+ # NEW! enable stomp retry logic
22
+ # will resend errored out messages to be retried when on_error throws ActiveMessaging::AbortMessageException
23
+ #
24
+ # Max number of times to retry an aborted message, for 0, will not retry (default)
25
+ # retryMax: 0
26
+ #
27
+ # If error still occurs after retryMax, send message to specified dead letter queue
28
+ # deadLetterQueue: '/queue/activemessaging/deadletter'
29
+
30
+
31
+ ###################################
32
+ # Websphere MQ Adapter Properties #
33
+ ###################################
34
+ # adapter: wmq
35
+ # q_mgr_name: ""
36
+ # poll_interval: .1
37
+
38
+
39
+ #################################
40
+ # Amazon SQS Adapter Properties #
41
+ #################################
42
+ # adapter: asqs
43
+ # access_key_id: XXXXXXXXXXXXXXXXXXXX
44
+ # secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
45
+
46
+ ## properties below are all defaults for this adapter
47
+ # host: queue.amazonaws.com
48
+ # port: 80
49
+ # reliable: true
50
+ # reconnectDelay: 5
51
+ # aws_version: 2006-04-01
52
+ # content_type: text/plain
53
+ # poll_interval: 1
54
+ # cache_queue_list: true
55
+
56
+
57
+ ########################################
58
+ # ReliableMessaging Adapter Properties #
59
+ ########################################
60
+ # adapter: reliable_msg
61
+
62
+ ## properties below are all defaults for this adapter
63
+ # poll_interval: 1
64
+ # reliable: true
65
+
66
+ test:
67
+ adapter: test
68
+ reliable: false
69
+
70
+ production:
71
+ adapter: stomp
72
+ reliable: true
73
+ # properties below are all defaults for this adapter
74
+ # login: ""
75
+ # passcode: ""
76
+ # host: localhost
77
+ # port: 61613
78
+ # reliable: true
79
+ # reconnectDelay: 5
@@ -0,0 +1,117 @@
1
+ #!/bin/sh
2
+
3
+ JRUBY_CMD=`which jruby`
4
+ RAILS_ROOT="$(dirname $0)/.."
5
+ POLLER_RB="$RAILS_ROOT/vendor/plugins/activemessaging/poller.rb"
6
+ OUT="$RAILS_ROOT/tmp/poller.output"
7
+ PID_FILE="$RAILS_ROOT/tmp/poller0.pid"
8
+
9
+ if [ -z "$JRUBY_CMD" ] ; then
10
+ echo "Could not find jruby on your path."
11
+ exit 1
12
+ fi
13
+
14
+ if [ ! -f $POLLER_RB ] ; then
15
+ echo "Could not find the poller file at: $POLLER_RB"
16
+ exit 1
17
+ fi
18
+
19
+ function start() {
20
+ if [[ -s $PID_FILE && -n "$(ps -A | grep "^[ \t]*$(< $PID_FILE)")" ]] ; then
21
+ PID=$(< $PID_FILE)
22
+ echo "Poller already running with pid $PID."
23
+ exit 1
24
+ fi
25
+ $JRUBY_CMD $POLLER_RB "$@" >> $OUT 2>&1 &
26
+ PID=$!
27
+ echo $PID > $PID_FILE
28
+ echo "Poller started with pid=$PID"
29
+ }
30
+
31
+ function stop() {
32
+ if [[ -z "$(ps -A | grep "^[ \t]*$(< $PID_FILE)")" ]] ; then
33
+ echo "Poller is not currently running."
34
+ exit 1
35
+ fi
36
+ if [ -z "$FORCE" ] ; then
37
+ echo "Sending TERM signal to poller."
38
+ kill -TERM $(< $PID_FILE)
39
+ else
40
+ echo "Sending KILL signal to poller."
41
+ kill -KILL $(< $PID_FILE)
42
+ fi
43
+ rm $PID_FILE
44
+ }
45
+
46
+ function restart() {
47
+ stop
48
+ start
49
+ }
50
+
51
+ function run() {
52
+ exec $JRUBY_CMD $POLLER_RB "$@"
53
+ }
54
+
55
+ function zap() {
56
+ echo "Resetting to stopped state."
57
+ [ -f $PID_FILE ] && rm $PID_FILE
58
+ }
59
+
60
+ function usage() {
61
+ cat <<EOF
62
+ Usage: poller <command> <options> -- <application options>
63
+
64
+ * where <command> is one of:
65
+ start start an instance of the application
66
+ stop stop all instances of the application
67
+ restart stop all instances and restart them afterwards
68
+ run start the application and stay on top
69
+ zap set the application to a stopped state
70
+
71
+ * and where <options> may contain several of the following:
72
+
73
+ -t, --ontop Stay on top (does not daemonize)
74
+ -f, --force Force operation
75
+ EOF
76
+
77
+ }
78
+
79
+ CMD=$1
80
+ shift
81
+
82
+ for i in "1" "2" ; do
83
+ case "$1" in
84
+ "-f"|"--force")
85
+ FORCE="true"
86
+ shift
87
+ ;;
88
+ "-t"|"--ontop")
89
+ ONTOP="true"
90
+ shift
91
+ ;;
92
+ esac
93
+ done
94
+
95
+ [ "$1" == "--" ] && shift
96
+
97
+ case "$CMD" in
98
+ "start")
99
+ start
100
+ ;;
101
+ "stop")
102
+ stop
103
+ ;;
104
+ "run")
105
+ run
106
+ ;;
107
+ "restart")
108
+ restart
109
+ ;;
110
+ "zap")
111
+ zap
112
+ ;;
113
+ "usage"|*)
114
+ usage
115
+ exit 1
116
+ ;;
117
+ esac