activemessaging 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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