redstorm 0.6.6 → 0.7.0.beta1

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. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6 -1
  3. data/README.md +8 -7
  4. data/examples/dsl/exclamation_topology.rb +2 -4
  5. data/examples/dsl/exclamation_topology2.rb +4 -5
  6. data/examples/dsl/hello_world_topology.rb +7 -0
  7. data/examples/dsl/kafka_topology.rb +5 -1
  8. data/examples/dsl/redis_word_count_topology.rb +5 -9
  9. data/examples/dsl/ruby_version_topology.rb +2 -0
  10. data/examples/dsl/word_count_topology.rb +4 -5
  11. data/examples/trident/word_count_query.rb +33 -0
  12. data/examples/trident/word_count_topology.rb +153 -0
  13. data/ivy/storm_dependencies.xml +1 -1
  14. data/ivy/topology_dependencies.xml +3 -2
  15. data/lib/red_storm.rb +5 -2
  16. data/lib/red_storm/configurator.rb +12 -0
  17. data/lib/red_storm/dsl/batch_bolt.rb +34 -0
  18. data/lib/red_storm/dsl/batch_committer_bolt.rb +9 -0
  19. data/lib/red_storm/dsl/batch_spout.rb +53 -0
  20. data/lib/red_storm/dsl/bolt.rb +7 -2
  21. data/lib/red_storm/dsl/output_collector.rb +8 -0
  22. data/lib/red_storm/dsl/spout.rb +3 -1
  23. data/lib/red_storm/dsl/topology.rb +2 -2
  24. data/lib/red_storm/dsl/tuple.rb +2 -0
  25. data/lib/red_storm/topology_launcher.rb +14 -10
  26. data/lib/red_storm/version.rb +1 -1
  27. data/redstorm.gemspec +1 -0
  28. data/src/main/redstorm/storm/jruby/JRubyBatchBolt.java +53 -35
  29. data/src/main/redstorm/storm/jruby/JRubyBatchSpout.java +77 -42
  30. data/src/main/redstorm/storm/jruby/JRubyBolt.java +54 -34
  31. data/src/main/redstorm/storm/jruby/JRubySpout.java +62 -40
  32. data/src/main/redstorm/storm/jruby/JRubyTransactionalBolt.java +57 -35
  33. data/src/main/redstorm/storm/jruby/JRubyTransactionalCommitterBolt.java +6 -17
  34. data/src/main/redstorm/storm/jruby/JRubyTransactionalCommitterSpout.java +14 -26
  35. data/src/main/redstorm/storm/jruby/JRubyTransactionalSpout.java +60 -37
  36. data/src/main/redstorm/storm/jruby/JRubyTridentFunction.java +66 -0
  37. metadata +16 -23
  38. data/lib/red_storm/proxy/batch_bolt.rb +0 -63
  39. data/lib/red_storm/proxy/batch_committer_bolt.rb +0 -52
  40. data/lib/red_storm/proxy/batch_spout.rb +0 -59
  41. data/lib/red_storm/proxy/bolt.rb +0 -63
  42. data/lib/red_storm/proxy/proxy_function.rb +0 -40
  43. data/lib/red_storm/proxy/spout.rb +0 -87
  44. data/lib/red_storm/proxy/transactional_committer_spout.rb +0 -47
  45. data/lib/red_storm/proxy/transactional_spout.rb +0 -46
  46. data/src/main/redstorm/storm/jruby/JRubyProxyFunction.java +0 -51
@@ -0,0 +1,9 @@
1
+ module RedStorm
2
+ module DSL
3
+
4
+ class BatchCommitterBolt < BatchBolt
5
+
6
+ def self.java_proxy; "Java::RedstormStormJruby::JRubyBatchCommitterBolt"; end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ module RedStorm
2
+ module DSL
3
+
4
+ class BatchSpout < Spout
5
+
6
+ def self.java_proxy; "Java::RedstormStormJruby::JRubyBatchSpout"; end
7
+
8
+ def get_output_fields
9
+ Fields.new(self.class.fields)
10
+ end
11
+
12
+ def self.on_emit_batch(*args, &on_emit_batch_block)
13
+ options = args.last.is_a?(Hash) ? args.pop : {}
14
+ method_name = args.first
15
+
16
+ self.on_emit_batch_options.merge!(options)
17
+
18
+ # indirecting through a lambda defers the method lookup at invocation time
19
+ # and the performance penalty is negligible
20
+ body = block_given? ? on_emit_batch_block : lambda{|batch_id, collector| self.send((method_name || :on_emit_batch).to_sym)}
21
+ define_method(:on_emit_batch, body)
22
+ end
23
+
24
+ # Spout proxy interface
25
+
26
+ #
27
+ # note that in batch spout, ack is for the batch id and not the message id as in the base spout.
28
+ # TODO maybe rename msg_id to just id in the base spout
29
+ #
30
+
31
+ def emit_batch(batch_id, collector)
32
+ # TODO this is a TridentCollector, emit should just work by setting @collector
33
+ # report_error need to be hooked?
34
+ @collector = collector
35
+ on_emit_batch(batch_id, collector)
36
+ end
37
+
38
+ def open(config, context)
39
+ @context = context
40
+ @config = config
41
+
42
+ on_init
43
+ end
44
+
45
+ private
46
+
47
+ def self.on_emit_batch_options
48
+ @on_emit_batch_options ||= {}
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -3,6 +3,9 @@ require 'red_storm/configurator'
3
3
  require 'red_storm/environment'
4
4
  require 'pathname'
5
5
 
6
+ java_import 'backtype.storm.tuple.Fields'
7
+ java_import 'backtype.storm.tuple.Values'
8
+
6
9
  module RedStorm
7
10
  module DSL
8
11
 
@@ -11,6 +14,8 @@ module RedStorm
11
14
  class Bolt
12
15
  attr_reader :collector, :context, :config
13
16
 
17
+ def self.java_proxy; "Java::RedstormStormJruby::JRubyBolt"; end
18
+
14
19
  # DSL class methods
15
20
 
16
21
  def self.log
@@ -54,11 +59,11 @@ module RedStorm
54
59
  end
55
60
 
56
61
  def unanchored_emit(*values)
57
- @collector.emit(Values.new(*values))
62
+ @collector.emit_tuple(Values.new(*values))
58
63
  end
59
64
 
60
65
  def anchored_emit(tuple, *values)
61
- @collector.emit(tuple, Values.new(*values))
66
+ @collector.emit_anchor_tuple(tuple, Values.new(*values))
62
67
  end
63
68
 
64
69
  def ack(tuple)
@@ -0,0 +1,8 @@
1
+ require 'java'
2
+ java_import 'backtype.storm.task.OutputCollector'
3
+
4
+ # make alias methods to specific signatures to avoid selection overhead for heavily overloaded method
5
+ class OutputCollector
6
+ java_alias :emit_tuple, :emit, [java.lang.Class.for_name("java.util.List")]
7
+ java_alias :emit_anchor_tuple, :emit, [java.lang.Class.for_name("backtype.storm.tuple.Tuple"), java.lang.Class.for_name("java.util.List")]
8
+ end
@@ -11,6 +11,8 @@ module RedStorm
11
11
  class Spout
12
12
  attr_reader :config, :context, :collector
13
13
 
14
+ def self.java_proxy; "Java::RedstormStormJruby::JRubySpout"; end
15
+
14
16
  # DSL class methods
15
17
 
16
18
  def self.configure(&configure_block)
@@ -99,7 +101,7 @@ module RedStorm
99
101
  unreliable_emit(*values)
100
102
  end
101
103
  else
102
- sleep(0.1)
104
+ sleep(0.1) # see https://twitter.com/colinsurprenant/status/406445541904494592
103
105
  end
104
106
  end
105
107
  end
@@ -46,7 +46,7 @@ module RedStorm
46
46
  elsif is_java?
47
47
  @clazz.new(*constructor_args)
48
48
  else
49
- JRubySpout.new(@clazz.base_class_path, @clazz.name, @output_fields)
49
+ Object.module_eval(@clazz.java_proxy).new(@clazz.base_class_path, @clazz.name, @output_fields)
50
50
  end
51
51
  end
52
52
  end
@@ -95,7 +95,7 @@ module RedStorm
95
95
  elsif is_java?
96
96
  @clazz.new(*constructor_args)
97
97
  else
98
- JRubyBolt.new(@clazz.base_class_path, @clazz.name, @output_fields)
98
+ Object.module_eval(@clazz.java_proxy).new(@clazz.base_class_path, @clazz.name, @output_fields)
99
99
  end
100
100
  end
101
101
  end
@@ -23,6 +23,8 @@ class TupleImpl
23
23
  end
24
24
  alias_method :[], :value
25
25
 
26
+ alias_method :values, :getValues # wire directly to avoid method missing indirection
27
+
26
28
  def field_index(field)
27
29
  fieldIndex(field.to_s)
28
30
  end
@@ -2,8 +2,11 @@ require 'java'
2
2
 
3
3
  # This hack get rif of the "Use RbConfig instead of obsolete and deprecated Config"
4
4
  # deprecation warning that is triggered by "java_import 'backtype.storm.Config'".
5
- Object.send :remove_const, :Config
6
- Config = RbConfig
5
+ begin
6
+ Object.send :remove_const, :Config
7
+ Config = RbConfig
8
+ rescue NameError
9
+ end
7
10
 
8
11
  # see https://github.com/colinsurprenant/redstorm/issues/7
9
12
  module Backtype
@@ -20,14 +23,15 @@ java_import 'backtype.storm.tuple.Fields'
20
23
  java_import 'backtype.storm.tuple.Tuple'
21
24
  java_import 'backtype.storm.tuple.Values'
22
25
 
23
- java_import 'redstorm.storm.jruby.JRubyBolt'
24
- java_import 'redstorm.storm.jruby.JRubySpout'
25
- java_import 'redstorm.storm.jruby.JRubyBatchBolt'
26
- java_import 'redstorm.storm.jruby.JRubyBatchCommitterBolt'
27
- java_import 'redstorm.storm.jruby.JRubyBatchSpout'
28
- java_import 'redstorm.storm.jruby.JRubyTransactionalSpout'
29
- java_import 'redstorm.storm.jruby.JRubyTransactionalBolt'
30
- java_import 'redstorm.storm.jruby.JRubyTransactionalCommitterBolt'
26
+ # java_import 'redstorm.storm.jruby.JRubyBolt'
27
+ # java_import 'redstorm.storm.jruby.JRubySpout'
28
+ # java_import 'redstorm.storm.jruby.JRubyBatchBolt'
29
+ # java_import 'redstorm.storm.jruby.JRubyBatchCommitterBolt'
30
+ # java_import 'redstorm.storm.jruby.JRubyBatchSpout'
31
+ # java_import 'redstorm.storm.jruby.JRubyTransactionalSpout'
32
+ # java_import 'redstorm.storm.jruby.JRubyTransactionalBolt'
33
+ # java_import 'redstorm.storm.jruby.JRubyTransactionalCommitterBolt'
34
+ # java_import 'redstorm.storm.jruby.JRubyProxyFunction'
31
35
 
32
36
  java_package 'redstorm'
33
37
 
@@ -1,3 +1,3 @@
1
1
  module RedStorm
2
- VERSION = '0.6.6'
2
+ VERSION = '0.7.0.beta1'
3
3
  end
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = 'https://github.com/colinsurprenant/redstorm'
12
12
  s.summary = 'JRuby on Storm'
13
13
  s.description = 'JRuby integration & DSL for the Storm distributed realtime computation system'
14
+ s.license = "Apache 2.0"
14
15
 
15
16
  s.rubyforge_project = 'redstorm'
16
17
 
@@ -10,81 +10,99 @@ import backtype.storm.tuple.Tuple;
10
10
  import backtype.storm.tuple.Fields;
11
11
  import java.util.Map;
12
12
 
13
+ import org.jruby.Ruby;
14
+ import org.jruby.RubyObject;
15
+ import org.jruby.runtime.Helpers;
16
+ import org.jruby.runtime.builtin.IRubyObject;
17
+ import org.jruby.javasupport.JavaUtil;
18
+ import org.jruby.RubyModule;
19
+ import org.jruby.exceptions.RaiseException;
20
+
13
21
  /**
14
- * the JRubyBolt class is a simple proxy class to the actual bolt implementation in JRuby.
15
- * this proxy is required to bypass the serialization/deserialization process when dispatching
16
- * the bolts to the workers. JRuby does not yet support serialization from Java
17
- * (Java serialization call on a JRuby class).
22
+ * the JRubyBolt class is a proxy class to the actual bolt implementation in JRuby.
23
+ * this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
24
+ * JRuby classes do not support Java serialization.
18
25
  *
19
- * Note that the JRuby bolt proxy class is instanciated in the prepare method which is called after
20
- * deserialization at the worker and in the declareOutputFields method which is called once before
21
- * serialization at topology creation.
26
+ * Note that the JRuby bolt class is instanciated in the prepare method which is called after
27
+ * deserialization at the worker and in the declareOutputFields & getComponentConfiguration
28
+ * methods which are called once before serialization at topology creation.
22
29
  */
23
30
  public class JRubyBatchBolt extends BaseBatchBolt {
24
- IBatchBolt _proxyBolt;
25
- String _realBoltClassName;
26
- String _baseClassPath;
27
- String[] _fields;
31
+ private final String _realBoltClassName;
32
+ private final String[] _fields;
33
+ private final String _bootstrap;
34
+
35
+ // transient to avoid serialization
36
+ private transient IRubyObject _ruby_bolt;
37
+ private transient Ruby __ruby__;
28
38
 
29
39
  /**
30
40
  * create a new JRubyBolt
31
- *
32
- * @param baseClassPath the topology/project base JRuby class file path
41
+ *
42
+ * @param baseClassPath the topology/project base JRuby class file path
33
43
  * @param realBoltClassName the fully qualified JRuby bolt implementation class name
44
+ * @param fields the output fields names
34
45
  */
35
46
  public JRubyBatchBolt(String baseClassPath, String realBoltClassName, String[] fields) {
36
- _baseClassPath = baseClassPath;
37
47
  _realBoltClassName = realBoltClassName;
38
48
  _fields = fields;
49
+ _bootstrap = "require '" + baseClassPath + "'";
39
50
  }
40
51
 
41
52
  @Override
42
- public void prepare(final Map stormConf, final TopologyContext context, final BatchOutputCollector collector, final Object id) {
43
- // create instance of the jruby class here, after deserialization in the workers.
44
- _proxyBolt = newProxyBolt(_baseClassPath, _realBoltClassName);
45
- _proxyBolt.prepare(stormConf, context, collector, id);
53
+ public void prepare(final Map conf, final TopologyContext context, final BatchOutputCollector collector, final Object id) {
54
+ _ruby_bolt = initialize_ruby_bolt();
55
+ IRubyObject ruby_conf = JavaUtil.convertJavaToRuby(__ruby__, conf);
56
+ IRubyObject ruby_context = JavaUtil.convertJavaToRuby(__ruby__, context);
57
+ IRubyObject ruby_collector = JavaUtil.convertJavaToRuby(__ruby__, collector);
58
+ IRubyObject ruby_id = JavaUtil.convertJavaToRuby(__ruby__, id);
59
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "prepare", ruby_conf, ruby_context, ruby_collector, ruby_id);
46
60
  }
47
61
 
48
62
  @Override
49
63
  public void execute(Tuple input) {
50
- _proxyBolt.execute(input);
64
+ IRubyObject ruby_input = JavaUtil.convertJavaToRuby(__ruby__, input);
65
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "execute", ruby_input);
51
66
  }
52
67
 
53
68
  @Override
54
69
  public void finishBatch() {
55
- _proxyBolt.finishBatch();
70
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_bolt, "finish_batch");
56
71
  }
57
72
 
58
73
  @Override
59
74
  public void declareOutputFields(OutputFieldsDeclarer declarer) {
60
- // declareOutputFields is executed in the topology creation time, before serialisation.
61
- // do not set the _proxyBolt instance variable here to avoid JRuby serialization
62
- // issues. Just create tmp bolt instance to call declareOutputFields.
63
75
  if (_fields.length > 0) {
64
76
  declarer.declare(new Fields(_fields));
65
77
  } else {
66
- IBatchBolt bolt = newProxyBolt(_baseClassPath, _realBoltClassName);
67
- bolt.declareOutputFields(declarer);
78
+ IRubyObject ruby_bolt = initialize_ruby_bolt();
79
+ IRubyObject ruby_declarer = JavaUtil.convertJavaToRuby(__ruby__, declarer);
80
+ Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "declare_output_fields", ruby_declarer);
68
81
  }
69
82
  }
70
83
 
71
84
  @Override
72
85
  public Map<String, Object> getComponentConfiguration() {
73
86
  // getComponentConfiguration is executed in the topology creation time, before serialisation.
74
- // do not set the _proxyBolt instance variable here to avoid JRuby serialization
75
- // issues. Just create tmp bolt instance to call declareOutputFields.
76
- IBatchBolt bolt = newProxyBolt(_baseClassPath, _realBoltClassName);
77
- return bolt.getComponentConfiguration();
87
+ // just create tmp bolt instance to call getComponentConfiguration.
88
+
89
+ IRubyObject ruby_bolt = initialize_ruby_bolt();
90
+ IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_bolt, "get_component_configuration");
91
+ return (Map)ruby_result.toJava(Map.class);
78
92
  }
79
-
80
93
 
81
- private static IBatchBolt newProxyBolt(String baseClassPath, String realBoltClassName) {
94
+ private IRubyObject initialize_ruby_bolt() {
95
+ __ruby__ = Ruby.getGlobalRuntime();
96
+
97
+ RubyModule ruby_class;
82
98
  try {
83
- redstorm.proxy.BatchBolt proxy = new redstorm.proxy.BatchBolt(baseClassPath, realBoltClassName);
84
- return proxy;
99
+ ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
85
100
  }
86
- catch (Exception e) {
87
- throw new RuntimeException(e);
101
+ catch (RaiseException e) {
102
+ // after deserialization we need to recreate ruby environment
103
+ __ruby__.evalScriptlet(_bootstrap);
104
+ ruby_class = __ruby__.getClassFromPath(_realBoltClassName);
88
105
  }
106
+ return Helpers.invoke(__ruby__.getCurrentContext(), ruby_class, "new");
89
107
  }
90
108
  }
@@ -6,83 +6,118 @@ import storm.trident.operation.TridentCollector;
6
6
  import storm.trident.spout.IBatchSpout;
7
7
  import java.util.Map;
8
8
 
9
+ import org.jruby.Ruby;
10
+ import org.jruby.RubyObject;
11
+ import org.jruby.runtime.Helpers;
12
+ import org.jruby.runtime.builtin.IRubyObject;
13
+ import org.jruby.javasupport.JavaUtil;
14
+ import org.jruby.RubyModule;
15
+ import org.jruby.exceptions.RaiseException;
16
+
9
17
  /**
10
- * the JRubySpout class is a simple proxy class to the actual spout implementation in JRuby.
11
- * this proxy is required to bypass the serialization/deserialization process when dispatching
12
- * the spout to the workers. JRuby does not yet support serialization from Java
13
- * (Java serialization call on a JRuby class).
18
+ * the JRubySpout class is a proxy class to the actual spout implementation in JRuby.
19
+ * this proxy is required to bypass the serialization/deserialization issues of JRuby objects.
20
+ * JRuby classes do not support Java serialization.
14
21
  *
15
- * Note that the JRuby spout proxy class is instanciated in the open method which is called after
16
- * deserialization at the worker and in both the declareOutputFields and isDistributed methods which
17
- * are called once before serialization at topology creation.
22
+ * Note that the JRuby spout class is instanciated in the open method which is called after
23
+ * deserialization at the worker and in the declareOutputFields & getComponentConfiguration
24
+ * methods which are called once before serialization at topology creation.
18
25
  */
19
26
  public class JRubyBatchSpout implements IBatchSpout {
20
- IBatchSpout _proxySpout;
21
- String _realSpoutClassName;
22
- String _baseClassPath;
23
-
27
+ private final String _realSpoutClassName;
28
+ private final String[] _fields;
29
+ private final String _bootstrap;
30
+
31
+ // transient to avoid serialization
32
+ private transient IRubyObject _ruby_spout;
33
+ private transient Ruby __ruby__;
34
+
24
35
  /**
25
- * create a new JRubySpout
26
- *
27
- * @param baseClassPath the topology/project base JRuby class file path
36
+ * create a new JRubyBatchSpout
37
+ *
38
+ * @param baseClassPath the topology/project base JRuby class file path
28
39
  * @param realSpoutClassName the fully qualified JRuby spout implementation class name
40
+ * @param fields the output fields names
29
41
  */
30
42
  public JRubyBatchSpout(String baseClassPath, String realSpoutClassName) {
31
- _baseClassPath = baseClassPath;
32
43
  _realSpoutClassName = realSpoutClassName;
44
+ _fields = null;
45
+ _bootstrap = "require '" + baseClassPath + "'";
46
+ }
47
+
48
+ /* constructor for compatibility with JRubySpout signature */
49
+ public JRubyBatchSpout(String baseClassPath, String realSpoutClassName, String[] fields) {
50
+ _realSpoutClassName = realSpoutClassName;
51
+ _fields = fields;
52
+ _bootstrap = "require '" + baseClassPath + "'";
33
53
  }
34
54
 
35
55
  @Override
36
56
  public void open(final Map conf, final TopologyContext context) {
37
- // create instance of the jruby proxy class here, after deserialization in the workers.
38
- _proxySpout = newProxySpout(_baseClassPath, _realSpoutClassName);
39
- _proxySpout.open(conf, context);
57
+ // // create instance of the jruby proxy class here, after deserialization in the workers.
58
+ // _proxySpout = newProxySpout(_baseClassPath, _realSpoutClassName);
59
+ // _proxySpout.open(conf, context);
60
+
61
+
62
+ _ruby_spout = initialize_ruby_spout();
63
+ IRubyObject ruby_conf = JavaUtil.convertJavaToRuby(__ruby__, conf);
64
+ IRubyObject ruby_context = JavaUtil.convertJavaToRuby(__ruby__, context);
65
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "open", ruby_conf, ruby_context);
40
66
  }
41
67
 
42
68
  @Override
43
69
  public void emitBatch(long batchId, TridentCollector collector) {
44
- _proxySpout.emitBatch(batchId, collector);
45
- }
70
+ // _proxySpout.emitBatch(batchId, collector);
71
+
72
+ IRubyObject ruby_batch_id = JavaUtil.convertJavaToRuby(__ruby__, batchId);
73
+ IRubyObject ruby_collector = JavaUtil.convertJavaToRuby(__ruby__, collector);
74
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "emit_batch", ruby_batch_id, ruby_collector);
75
+ }
46
76
 
47
77
  @Override
48
78
  public void close() {
49
- _proxySpout.close();
79
+ // _proxySpout.close();
80
+
81
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "close");
50
82
  }
51
83
 
52
84
  @Override
53
85
  public void ack(long batchId) {
54
- _proxySpout.ack(batchId);
86
+ // _proxySpout.ack(batchId);
87
+
88
+ IRubyObject ruby_batch_id = JavaUtil.convertJavaToRuby(__ruby__, batchId);
89
+ Helpers.invoke(__ruby__.getCurrentContext(), _ruby_spout, "ack", ruby_batch_id);
55
90
  }
56
91
 
57
92
  @Override
58
93
  public Fields getOutputFields() {
59
- if (_proxySpout == null) {
60
- // getOutputFields is executed in the topology creation time before serialisation.
61
- // do not set the _proxySpout instance variable here to avoid JRuby serialization
62
- // issues. Just create tmp spout instance to call getOutputFields.
63
- IBatchSpout spout = newProxySpout(_baseClassPath, _realSpoutClassName);
64
- return spout.getOutputFields();
65
- } else {
66
- return _proxySpout.getOutputFields();
67
- }
94
+ IRubyObject ruby_spout = initialize_ruby_spout();
95
+ IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_spout, "get_output_fields");
96
+ return (Fields)ruby_result.toJava(Fields.class);
68
97
  }
69
98
 
70
99
  @Override
71
100
  public Map<String, Object> getComponentConfiguration() {
72
- // getComponentConfiguration is executed in the topology creation time before serialisation.
73
- // do not set the _proxySpout instance variable here to avoid JRuby serialization
74
- // issues. Just create tmp spout instance to call declareOutputFields.
75
- IBatchSpout spout = newProxySpout(_baseClassPath, _realSpoutClassName);
76
- return spout.getComponentConfiguration();
101
+ // getComponentConfiguration is executed in the topology creation time, before serialisation.
102
+ // just create tmp spout instance to call getComponentConfiguration.
103
+
104
+ IRubyObject ruby_spout = initialize_ruby_spout();
105
+ IRubyObject ruby_result = Helpers.invoke(__ruby__.getCurrentContext(), ruby_spout, "get_component_configuration");
106
+ return (Map)ruby_result.toJava(Map.class);
77
107
  }
78
-
79
- private static IBatchSpout newProxySpout(String baseClassPath, String realSpoutClassName) {
108
+
109
+ private IRubyObject initialize_ruby_spout() {
110
+ __ruby__ = Ruby.getGlobalRuntime();
111
+
112
+ RubyModule ruby_class;
80
113
  try {
81
- redstorm.proxy.BatchSpout proxy = new redstorm.proxy.BatchSpout(baseClassPath, realSpoutClassName);
82
- return proxy;
114
+ ruby_class = __ruby__.getClassFromPath(_realSpoutClassName);
83
115
  }
84
- catch (Exception e) {
85
- throw new RuntimeException(e);
116
+ catch (RaiseException e) {
117
+ // after deserialization we need to recreate ruby environment
118
+ __ruby__.evalScriptlet(_bootstrap);
119
+ ruby_class = __ruby__.getClassFromPath(_realSpoutClassName);
86
120
  }
121
+ return Helpers.invoke(__ruby__.getCurrentContext(), ruby_class, "new");
87
122
  }
88
123
  }