actionservice 0.2.100 → 0.2.102

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.
@@ -1,5 +1,6 @@
1
1
  require 'xmlrpc/parser'
2
2
  require 'xmlrpc/utils'
3
+ require 'singleton'
3
4
 
4
5
  module ActionService
5
6
  module Protocol
@@ -10,86 +11,115 @@ module ActionService
10
11
  end
11
12
 
12
13
  class XmlRpcProtocol < AbstractProtocol
13
- include XMLRPC::ParserWriterChooseMixin
14
+ private
15
+ class Helper
16
+ include Singleton
17
+ include XMLRPC::ParserWriterChooseMixin
18
+
19
+ def get_parser
20
+ parser()
21
+ end
22
+
23
+ def get_create
24
+ create()
25
+ end
26
+ end
27
+
28
+ public
14
29
 
15
- def initialize(container_klass)
16
- @container_klass = container_klass
17
- @container_klass.write_inheritable_hash('default_system_exports', XmlRpcProtocol => method(:xmlrpc_default_system_handler))
30
+ def self.create_protocol_request(container_class, action_pack_request)
31
+ parser = Helper.instance.get_parser
32
+ service_name = action_pack_request.parameters['action']
33
+ methodname, params = parser.parseMethodCall(action_pack_request.raw_post)
34
+ protocol = XmlRpcProtocol.new(container_class)
35
+ content_type = action_pack_request.env['HTTP_CONTENT_TYPE']
36
+ content_type ||= 'text/xml'
37
+ request = ProtocolRequest.new(protocol,
38
+ action_pack_request.raw_post,
39
+ service_name.to_sym,
40
+ methodname,
41
+ content_type)
42
+ request.values = params
43
+ request
44
+ rescue
45
+ nil
18
46
  end
19
47
 
20
- def unmarshal_request(request_info, export_info, strict=true)
21
- expects = export_info[:expects]
22
- params = request_info.protocol_info[:xmlrpc][:params]
23
- if expects
24
- expects = array_types(expects)
25
- validate_types(request_info.public_method_name, expects, params, :in)
26
- params
48
+ def initialize(container_class)
49
+ super(container_class)
50
+ container_class.write_inheritable_hash('default_system_exports', XmlRpcProtocol => method(:xmlrpc_default_system_handler))
51
+ end
52
+
53
+ def unmarshal_request(protocol_request)
54
+ values = protocol_request.values
55
+ signature = protocol_request.signature
56
+ if signature
57
+ signature = array_types(signature)
58
+ protocol_request.check_parameter_types(values, signature)
59
+ values
27
60
  else
28
- strict ? [] : params
61
+ protocol_request.checked? ? [] : values
29
62
  end
30
63
  end
31
64
 
32
- def marshal_response(request_info, export_info, return_value, strict=true)
33
- returns = export_info[:returns]
34
- if returns
35
- returns = array_types(returns)
36
- validate_types(request_info.public_method_name, returns, [return_value], :out)
37
- raw_response = create().methodResponse(true, return_value)
65
+ def marshal_response(protocol_request, return_value)
66
+ create = Helper.instance.get_create
67
+ signature = protocol_request.return_signature
68
+ if signature
69
+ signature = array_types(signature)
70
+ protocol_request.check_parameter_types([return_value], signature)
71
+ return_value = fixup_values_for_return(return_value)
72
+ raw_response = create.methodResponse(true, return_value)
38
73
  else
39
74
  # XML-RPC doesn't have the concept of a void method, nor does it
40
75
  # support a nil return value, so return true if we would have returned
41
76
  # nil
42
- if strict
43
- raw_response = create().methodResponse(true, true)
77
+ if protocol_request.checked?
78
+ raw_response = create.methodResponse(true, true)
44
79
  else
45
80
  return_value = true if return_value.nil?
46
- raw_response = create().methodResponse(true, return_value)
81
+ raw_response = create.methodResponse(true, return_value)
47
82
  end
48
83
  end
49
- ServiceResponseInfo.new(raw_response, 'text/xml')
84
+ ProtocolResponse.new(self, raw_response, 'text/xml')
50
85
  end
51
86
 
52
87
  def marshal_exception(exception)
53
- raw_response = create().methodResponse(false, exception)
54
- ServiceResponseInfo.new(raw_response, 'text/xml')
55
- end
56
-
57
- def request_info
58
- @request_info
88
+ create = Helper.instance.get_create
89
+ raw_response = create.methodResponse(false, exception)
90
+ ProtocolResponse.new(self, raw_response, 'text/xml')
59
91
  end
60
92
 
61
- def request_supported?(request)
62
- begin
63
- service_name = request.parameters['action']
64
- methodname, params = parser().parseMethodCall(request.raw_post)
65
- @request_info = ServiceRequestInfo.new(service_name,
66
- methodname,
67
- request.raw_post,
68
- request.env['HTTP_CONTENT_TYPE'] || 'text/xml',
69
- :xmlrpc => { :params => params })
70
- true
71
- rescue
72
- false
73
- end
74
- end
75
-
76
93
  private
77
- def xmlrpc_default_system_handler(name, service_klass, *args)
94
+ def xmlrpc_default_system_handler(name, service_class, *args)
78
95
  case name
79
96
  when 'system.listMethods'
80
97
  methods = []
81
- service_klass.exports.each do |name, info|
82
- methods << service_klass.public_export_name(name)
98
+ service_class.exports.each do |name, info|
99
+ methods << service_class.public_export_name(name)
83
100
  end
84
101
  methods.sort
85
102
  else
86
- raise SystemExportNotHandledError
103
+ throw :try_default_export
87
104
  end
88
105
  end
89
106
 
90
107
  def array_types(signature)
91
108
  signature.map{|x| x.is_a?(Array) ? Array : x}
92
109
  end
110
+
111
+ def fixup_values_for_return(return_value)
112
+ if return_value.is_a?(Array)
113
+ (1..return_value.size).each do |i|
114
+ return_value[i-1] = fixup_values_for_return(return_value[i-1])
115
+ end
116
+ else
117
+ if return_value.is_a?(ActiveRecord::Base)
118
+ return_value = return_value.instance_variable_get('@attributes')
119
+ end
120
+ end
121
+ return_value
122
+ end
93
123
  end
94
124
 
95
125
  end
@@ -2,12 +2,23 @@ module ActionService
2
2
  module Router
3
3
  module ActionController
4
4
  def self.append_features(base)
5
+ base.add_export_definition_callback do |klass, export_name, export_info|
6
+ if klass.service_dispatching_mode == :direct && !klass.method_defined?(:api)
7
+ klass.class_eval <<-EOS
8
+ def api
9
+ process_action_service_request
10
+ end
11
+ EOS
12
+ end
13
+ end
5
14
  base.add_service_definition_callback do |klass, name, info|
6
- klass.class_eval <<-EOF
7
- def #{name}
8
- process_action_service_request
9
- end
10
- EOF
15
+ if klass.service_dispatching_mode == :delegated
16
+ klass.class_eval <<-EOS
17
+ def #{name}
18
+ process_action_service_request
19
+ end
20
+ EOS
21
+ end
11
22
  end
12
23
  base.send(:include, ActionService::Router::ActionController::InstanceMethods)
13
24
  end
@@ -15,54 +26,55 @@ module ActionService
15
26
  module InstanceMethods
16
27
  private
17
28
  def process_action_service_request
18
- protocol = nil
19
- request_info = nil
29
+ protocol_request = nil
20
30
  begin
21
- protocol = probe_request_protocol(self.request)
22
- request_info = protocol.request_info
23
- if request_info
24
- log_request request_info
25
- response_info = dispatch_service_invocation_request(protocol, request_info)
26
- log_response response_info
31
+ protocol_request = probe_request_protocol(self.request)
32
+ if protocol_request
33
+ log_request(protocol_request)
34
+ protocol_response = dispatch_service_request(protocol_request)
35
+ log_response(protocol_request)
27
36
  response_options = {
28
- :type => response_info.content_type,
37
+ :type => protocol_response.content_type,
29
38
  :disposition => 'inline'
30
39
  }
31
- send_data(response_info.raw_body, response_options)
40
+ send_data(protocol_response.raw_body, response_options)
32
41
  else
33
42
  logger.fatal "Invalid Action Service service or method requested"
34
- render_text '', "500 Invalid service/method"
43
+ render_text 'Internal protocol error', "500 Invalid service/method"
35
44
  end
36
45
  rescue Exception => e
37
46
  log_error e unless logger.nil?
38
- service_object = service_object(request_info.service_name)
47
+ service_object = service_object(protocol_request.service_name) rescue nil
39
48
  exc_response = nil
40
- if service_object.class.report_exceptions
41
- exc_response_info = protocol.marshal_exception(e) rescue nil
49
+ if service_object && service_object.class.report_exceptions
50
+ exc_response = protocol_request.protocol.marshal_exception(e) rescue nil
42
51
  end
43
- if exc_response_info
52
+ if exc_response
44
53
  response_options = {
45
- :type => exc_response_info.content_type,
54
+ :type => exc_response.content_type,
46
55
  :disposition => 'inline'
47
56
  }
48
- send_data(exc_response_info.raw_body, response_options)
57
+ send_data(exc_response.raw_body, response_options)
49
58
  else
50
- render_text '', "500 #{e.message}"
59
+ render_text 'Internal protocol error', "500 #{e.message}"
51
60
  end
52
61
  end
53
62
  end
54
63
 
55
- def log_request(request_info)
64
+ def log_request(protocol_request)
56
65
  unless logger.nil?
57
- logger.info "\nRaw Action Service Request:"
58
- logger.info request_info.raw_body
66
+ service_name = protocol_request.service_name
67
+ method_name = protocol_request.public_method_name
68
+ logger.info "\nProcessing Action Service Request: #{service_name}##{method_name}"
69
+ logger.info "Raw Request Body:"
70
+ logger.info protocol_request.raw_body
59
71
  end
60
72
  end
61
73
 
62
- def log_response(response_info)
74
+ def log_response(protocol_response)
63
75
  unless logger.nil?
64
- logger.info "\nRaw Action Service Response:"
65
- logger.info response_info.raw_body
76
+ logger.info "\nRaw Response Body:"
77
+ logger.info protocol_response.raw_body
66
78
  end
67
79
  end
68
80
  end
@@ -2,155 +2,190 @@ module ActionService
2
2
  module Router
3
3
  module Wsdl
4
4
  def self.append_features(base)
5
- base.extend(ClassMethods)
6
5
  base.send(:include, ActionService::Router::Wsdl::InstanceMethods)
7
6
  end
8
7
 
9
- module ClassMethods
8
+ module InstanceMethods
10
9
  XsdNs = 'http://www.w3.org/2001/XMLSchema'
11
10
  WsdlNs = 'http://schemas.xmlsoap.org/wsdl/'
12
11
  SoapNs = 'http://schemas.xmlsoap.org/wsdl/soap/'
13
12
  SoapEncodingNs = 'http://schemas.xmlsoap.org/soap/encoding/'
14
13
  SoapHttpTransport = 'http://schemas.xmlsoap.org/soap/http'
15
14
 
16
- def to_wsdl(container, uri, soap_action_base)
17
- wsdl = ""
18
-
19
- namespace = container.class.soap_mapper.custom_namespace
20
- wsdl_service_name = namespace.split(/:/)[1]
21
-
22
- mapper = ActionService::Protocol::Soap::SoapMapper.new(namespace)
23
- services = {}
24
- mapper.map_container_services(container) do |name, klass, exports|
25
- services[name] = [klass, exports]
15
+ def wsdl
16
+ case @request.method
17
+ when :get
18
+ begin
19
+ host_name = @request.env['HTTP_HOST']||@request.env['SERVER_NAME']
20
+ uri = "http://#{host_name}/#{controller_name}/"
21
+ soap_action_base = "/#{controller_name}"
22
+ xml = to_wsdl(self, uri, soap_action_base)
23
+ send_data(xml, :type => 'text/xml', :disposition => 'inline')
24
+ rescue Exception => e
25
+ log_error e unless logger.nil?
26
+ render_text('', "500 #{e.message}")
27
+ end
28
+ when :post
29
+ render_text('', "500 POST not supported")
26
30
  end
27
- custom_types = mapper.custom_types
28
-
29
-
30
- xm = Builder::XmlMarkup.new(:target => wsdl, :indent => 2)
31
- xm.instruct!
32
-
33
- xm.definitions('name' => wsdl_service_name,
34
- 'targetNamespace' => namespace,
35
- 'xmlns:typens' => namespace,
36
- 'xmlns:xsd' => XsdNs,
37
- 'xmlns:soap' => SoapNs,
38
- 'xmlns:soapenc' => SoapEncodingNs,
39
- 'xmlns:wsdl' => WsdlNs,
40
- 'xmlns' => WsdlNs) do
31
+ end
41
32
 
42
- # Custom type XSD generation
43
- if custom_types.size > 0
44
- xm.types do
45
- xm.xsd(:schema, 'xmlns' => XsdNs, 'targetNamespace' => namespace) do
46
- custom_types.each do |klass, mapping|
47
- case
48
- when mapping.is_a?(ActionService::Protocol::Soap::SoapArrayMapping)
49
- xm.xsd(:complexType, 'name' => mapping.type_name) do
50
- xm.xsd(:complexContent) do
51
- xm.xsd(:restriction, 'base' => 'soapenc:Array') do
52
- xm.xsd(:attribute, 'ref' => 'soapenc:arrayType',
53
- 'wsdl:arrayType' => mapping.element_mapping.qualified_type_name + '[]')
33
+ private
34
+ def to_wsdl(container, uri, soap_action_base)
35
+ wsdl = ""
36
+
37
+ service_dispatching_mode = container.service_dispatching_mode
38
+ mapper = container.class.soap_mapper
39
+ namespace = mapper.custom_namespace
40
+ wsdl_service_name = namespace.split(/:/)[1]
41
+
42
+ services = {}
43
+ mapper.map_container_services(container) do |name, klass, exports|
44
+ services[name] = [klass, exports]
45
+ end
46
+ custom_types = mapper.custom_types
47
+
48
+
49
+ xm = Builder::XmlMarkup.new(:target => wsdl, :indent => 2)
50
+ xm.instruct!
51
+
52
+ xm.definitions('name' => wsdl_service_name,
53
+ 'targetNamespace' => namespace,
54
+ 'xmlns:typens' => namespace,
55
+ 'xmlns:xsd' => XsdNs,
56
+ 'xmlns:soap' => SoapNs,
57
+ 'xmlns:soapenc' => SoapEncodingNs,
58
+ 'xmlns:wsdl' => WsdlNs,
59
+ 'xmlns' => WsdlNs) do
60
+
61
+ # Custom type XSD generation
62
+ if custom_types.size > 0
63
+ xm.types do
64
+ xm.xsd(:schema, 'xmlns' => XsdNs, 'targetNamespace' => namespace) do
65
+ custom_types.each do |klass, mapping|
66
+ case
67
+ when mapping.is_a?(ActionService::Protocol::Soap::SoapArrayMapping)
68
+ xm.xsd(:complexType, 'name' => mapping.type_name) do
69
+ xm.xsd(:complexContent) do
70
+ xm.xsd(:restriction, 'base' => 'soapenc:Array') do
71
+ xm.xsd(:attribute, 'ref' => 'soapenc:arrayType',
72
+ 'wsdl:arrayType' => mapping.element_mapping.qualified_type_name + '[]')
73
+ end
54
74
  end
55
75
  end
56
- end
57
- when mapping.is_a?(ActionService::Protocol::Soap::SoapMapping)
58
- xm.xsd(:complexType, 'name' => mapping.type_name) do
59
- xm.xsd(:all) do
60
- mapping.each_attribute do |name, type_name|
61
- xm.xsd(:element, 'name' => name, 'type' => type_name)
76
+ when mapping.is_a?(ActionService::Protocol::Soap::SoapMapping)
77
+ xm.xsd(:complexType, 'name' => mapping.type_name) do
78
+ xm.xsd(:all) do
79
+ mapping.each_attribute do |name, type_name|
80
+ xm.xsd(:element, 'name' => name, 'type' => type_name)
81
+ end
62
82
  end
63
83
  end
84
+ else
85
+ raise(WsdlError, "unsupported mapping type #{mapping.class.name}")
64
86
  end
65
- else
66
- raise(WsdlError, "unsupported mapping type #{mapping.class.name}")
67
87
  end
68
88
  end
69
89
  end
70
90
  end
71
- end
72
-
73
- services.each do |service_name, service_values|
74
- service_klass, service_exports = service_values
75
- # Parameter list message definitions
76
- service_exports.each do |export_name, export_signature|
77
- gen = lambda do |msg_name, direction|
78
- xm.message('name' => msg_name) do
79
- sym = nil
80
- if direction == :out
81
- if export_signature[:returns]
82
- xm.part('name' => 'return', 'type' => export_signature[:returns][0].qualified_type_name)
91
+
92
+ services.each do |service_name, service_values|
93
+ service_klass, service_exports = service_values
94
+ # Parameter list message definitions
95
+ service_exports.each do |export_name, export_signature|
96
+ gen = lambda do |msg_name, direction|
97
+ xm.message('name' => msg_name) do
98
+ sym = nil
99
+ if direction == :out
100
+ if export_signature[:returns]
101
+ xm.part('name' => 'return', 'type' => export_signature[:returns][0].qualified_type_name)
102
+ end
103
+ else
104
+ mapping_list = export_signature[:expects]
105
+ i = 1
106
+ mapping_list.each do |mapping|
107
+ if mapping.is_a?(Hash)
108
+ param_name = mapping.keys.shift
109
+ mapping = mapping.values.shift
110
+ else
111
+ param_name = "param#{i}"
112
+ end
113
+ xm.part('name' => param_name, 'type' => mapping.qualified_type_name)
114
+ i += 1
115
+ end if mapping_list
83
116
  end
84
- else
85
- mapping_list = export_signature[:expects]
86
- i = 1
87
- mapping_list.each do |mapping|
88
- xm.part('name' => "param#{i}", 'type' => mapping.qualified_type_name)
89
- i += 1
90
- end if mapping_list
91
117
  end
92
118
  end
93
- end
94
- public_name = service_klass.public_export_name(export_name)
95
- gen.call(public_name, :in)
96
- gen.call("#{public_name}Response", :out)
97
- end
98
-
99
- # Declare the port
100
- port_name = port_name_for(wsdl_service_name, service_name)
101
- xm.portType('name' => port_name) do
102
- service_exports.each do |export_name, export_signature|
103
119
  public_name = service_klass.public_export_name(export_name)
104
- xm.operation('name' => public_name) do
105
- xm.input('message' => "typens:#{public_name}")
106
- xm.output('message' => "typens:#{public_name}Response")
107
- end
120
+ gen.call(public_name, :in)
121
+ gen.call("#{public_name}Response", :out)
108
122
  end
109
- end
110
-
111
- # Bind the port to SOAP
112
- binding_name = binding_name_for(wsdl_service_name, service_name)
113
- xm.binding('name' => binding_name, 'type' => "typens:#{port_name}") do
114
- xm.soap(:binding, 'style' => 'rpc', 'transport' => SoapHttpTransport)
115
- service_exports.each do |export_name, export_signature|
116
- public_name = service_klass.public_export_name(export_name)
117
- xm.operation('name' => public_name) do
118
- soap_action = soap_action_base \
119
- + "/" + service_name.to_s \
120
- + "/" + public_name
121
- xm.soap(:operation, 'soapAction' => soap_action)
122
- xm.input do
123
- xm.soap(:body,
124
- 'use' => 'encoded',
125
- 'namespace' => namespace,
126
- 'encodingStyle' => SoapEncodingNs)
123
+
124
+ # Declare the port
125
+ port_name = port_name_for(wsdl_service_name, service_name)
126
+ xm.portType('name' => port_name) do
127
+ service_exports.each do |export_name, export_signature|
128
+ public_name = service_klass.public_export_name(export_name)
129
+ xm.operation('name' => public_name) do
130
+ xm.input('message' => "typens:#{public_name}")
131
+ xm.output('message' => "typens:#{public_name}Response")
127
132
  end
128
- xm.output do
129
- xm.soap(:body,
130
- 'use' => 'encoded',
131
- 'namespace' => namespace,
132
- 'encodingStyle' => SoapEncodingNs)
133
+ end
134
+ end
135
+
136
+ # Bind the port to SOAP
137
+ binding_name = binding_name_for(wsdl_service_name, service_name)
138
+ xm.binding('name' => binding_name, 'type' => "typens:#{port_name}") do
139
+ xm.soap(:binding, 'style' => 'rpc', 'transport' => SoapHttpTransport)
140
+ service_exports.each do |export_name, export_signature|
141
+ public_name = service_klass.public_export_name(export_name)
142
+ xm.operation('name' => public_name) do
143
+ case service_dispatching_mode
144
+ when :direct
145
+ soap_action = soap_action_base + "/api/" + public_name
146
+ when :delegated
147
+ soap_action = soap_action_base \
148
+ + "/" + service_name.to_s \
149
+ + "/" + public_name
150
+ end
151
+ xm.soap(:operation, 'soapAction' => soap_action)
152
+ xm.input do
153
+ xm.soap(:body,
154
+ 'use' => 'encoded',
155
+ 'namespace' => namespace,
156
+ 'encodingStyle' => SoapEncodingNs)
157
+ end
158
+ xm.output do
159
+ xm.soap(:body,
160
+ 'use' => 'encoded',
161
+ 'namespace' => namespace,
162
+ 'encodingStyle' => SoapEncodingNs)
163
+ end
133
164
  end
134
165
  end
135
166
  end
136
167
  end
137
- end
138
-
139
- # Define the service
140
- xm.service('name' => "#{wsdl_service_name}Service") do
141
- services.each do |service_name, service_values|
142
- service_klass, service_exports = service_values
143
- port_name = port_name_for(wsdl_service_name, service_name)
144
- binding_name = binding_name_for(wsdl_service_name, service_name)
145
- xm.port('name' => port_name, 'binding' => "typens:#{binding_name}") do
146
- xm.soap(:address, 'location' => "#{uri}#{service_name.to_s}")
168
+
169
+ # Define the service
170
+ xm.service('name' => "#{wsdl_service_name}Service") do
171
+ services.each do |service_name, service_values|
172
+ service_klass, service_exports = service_values
173
+ port_name = port_name_for(wsdl_service_name, service_name)
174
+ binding_name = binding_name_for(wsdl_service_name, service_name)
175
+ case service_dispatching_mode
176
+ when :direct
177
+ binding_target = 'api'
178
+ when :delegated
179
+ binding_target = service_name.to_s
180
+ end
181
+ xm.port('name' => port_name, 'binding' => "typens:#{binding_name}") do
182
+ xm.soap(:address, 'location' => "#{uri}#{binding_target}")
183
+ end
147
184
  end
148
185
  end
149
186
  end
150
187
  end
151
- end
152
188
 
153
- private
154
189
  def port_name_for(wsdl_service_name, service_name)
155
190
  "#{wsdl_service_name}#{Inflector.camelize(service_name.to_s)}Port"
156
191
  end
@@ -159,24 +194,6 @@ module ActionService
159
194
  "#{wsdl_service_name}#{Inflector.camelize(service_name.to_s)}Binding"
160
195
  end
161
196
  end
162
-
163
- module InstanceMethods
164
- def wsdl
165
- case @request.method
166
- when :get
167
- begin
168
- uri = "http://#{@request.env['HTTP_HOST']||@request.env['SERVER_NAME']}/#{controller_name}/"
169
- soap_action_base = "/#{controller_name}"
170
- xml = self.class.to_wsdl(self, uri, soap_action_base)
171
- send_data(xml, :type => 'text/xml', :disposition => 'inline')
172
- rescue Exception => e
173
- render_text('', "500 #{e.message}")
174
- end
175
- when :post
176
- render_text('', "500 POST not supported")
177
- end
178
- end
179
- end
180
197
  end
181
198
  end
182
199
  end
@@ -23,14 +23,17 @@
23
23
 
24
24
  begin
25
25
  require 'action_controller'
26
+ require 'active_record'
26
27
  rescue LoadError
27
28
  require 'rubygems'
28
29
  require_gem 'actionpack', '>= 1.4.0'
30
+ require_gem 'activerecord', '>= 1.6.0'
29
31
  end
30
32
 
31
33
  $:.unshift(File.dirname(__FILE__))
32
34
 
33
35
  require 'action_service/base'
36
+ require 'action_service/exporting'
34
37
  require 'action_service/invocation'
35
38
  require 'action_service/struct'
36
39
  require 'action_service/container'
@@ -38,10 +41,12 @@ require 'action_service/protocol'
38
41
  require 'action_service/router'
39
42
 
40
43
  ActionService::Base.class_eval do
44
+ include ActionService::Exporting
41
45
  include ActionService::Invocation
42
46
  end
43
47
 
44
48
  ActionController::Base.class_eval do
49
+ include ActionService::Exporting
45
50
  include ActionService::Container
46
51
  include ActionService::Protocol::Registry
47
52
  include ActionService::Protocol::Soap