rename service* to web_service*.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@668 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Leon Breedt 2005-02-18 21:22:52 +00:00
parent 5dcbe933df
commit fdecb6843b
31 changed files with 279 additions and 294 deletions

View File

@ -1,5 +1,8 @@
UNRELEASED
* lib/*,test/*,examples/*: prefix all generic "service"
type names with web_. update all using code as well as
the RDoc.
* lib/action_service/router/wsdl.rb: ensure that #wsdl is
defined in the final container class, or the new ActionPack
filtering will exclude it

View File

@ -60,7 +60,7 @@ ActionService::API::Base +inflect_names+ option.
==== API usage example
class PersonController < ActionController::Base
service_api PersonAPI
web_service_api PersonAPI
def add
end
@ -93,7 +93,7 @@ overridden.</em>
==== Direct dispatching example
class PersonController < ApplicationController
service_api PersonAPI
web_service_api PersonAPI
def add
end
@ -113,23 +113,23 @@ For this example, protocol requests for +Add+ and +Remove+ methods sent to
=== Delegated dispatching
This mode can be turned on by setting the +service_dispatching_mode+ option
This mode can be turned on by setting the +web_service_dispatching_mode+ option
in a controller.
In this mode, the controller contains one or more service API objects (objects
that implement an ActionService::API::Base definition). These API
In this mode, the controller contains one or more web service objects (objects
that implement an ActionService::API::Base definition). These web service
objects are each mapped onto one controller action only.
==== Delegated dispatching example
class ApiController < ApplicationController
service_dispatching_mode :delegated
web_service_dispatching_mode :delegated
service :person, PersonService.new
web_service :person, PersonService.new
end
class PersonService < ActionService::Base
service_api PersonAPI
web_service_api PersonAPI
def add
end
@ -146,10 +146,10 @@ objects are each mapped onto one controller action only.
For this example, all protocol requests for +PersonService+ are
sent to the <tt>/api/person</tt> action.
The <tt>/api/person</tt> action is generated when the +service+
The <tt>/api/person</tt> action is generated when the +web_service+
method is called. <em>This action must not be overridden.</em>
Other controller actions (actions that aren't the target of a +service+ call)
Other controller actions (actions that aren't the target of a +web_service+ call)
are ignored for ActionService purposes, and can do normal action tasks.
@ -166,21 +166,18 @@ applications that both use Action Service. It may work with other servers, but
that is not its intended use, and interoperability can't be guaranteed, especially
not for .NET web services.
Web services protocol specifications are complex, and Action Service can only
be guaranteed to work with a subset.
Web services protocol specifications are complex, and Action Service client
support can only be guaranteed to work with a subset.
If you have the need for clients for a complex service not running on Action
Service, it is recommended that you use +wsdl2ruby+ and generate the client
stub classes.
==== Factory created client example
class BlogManagerController < ApplicationController
client_api :blogger, :xmlrpc, 'http://url/to/blog/api/RPC2', :handler_name => 'blogger'
web_client_api :blogger, :xmlrpc, 'http://url/to/blog/api/RPC2', :handler_name => 'blogger'
end
class SearchingController < ApplicationController
client_api :google, :soap, 'http://url/to/blog/api/beta', :service_name => 'GoogleSearch'
web_client_api :google, :soap, 'http://url/to/blog/api/beta', :service_name => 'GoogleSearch'
end
See ActionService::API::ActionController::ClassMethods for more details.

View File

@ -1,3 +1,7 @@
= 0.4.0 Tasks
- add ActiveRecord-like logging that includes timing information
- rename project to 'actionwebservice', Action Web Service
= Post-0.4.0 Tasks
- relax type-checking for XML-RPC, and perform casts between base types if there
are mismatches (i.e. String received when Integer expected, or vice-versa)
@ -9,14 +13,14 @@
@request = controller.request
end
service :mt {MTService.new(@request)}
service :blogger {BloggerService.new(@request)}
service :metaWeblog {MetaWeblogService.new(@request)}
web_service :mt {MTService.new(@request)}
web_service :blogger {BloggerService.new(@request)}
web_service :metaWeblog {MetaWeblogService.new(@request)}
end
class ApiController < ApplicationController
service_dispatching_mode :delegated
service :xmlrpc { BloggingServices.new(@request) }
web_service_dispatching_mode :delegated
web_service :xmlrpc { BloggingServices.new(@request) }
end
= Low priority tasks

View File

@ -1,6 +1,5 @@
= Google Service example
This example shows how one would implement an API like Google
Search that uses lots of structured types.
@ -9,26 +8,19 @@ modes.
There is also an example for API definition file autoloading.
= Running
1. Ensure you have the 'actionservice' Gem installed. You can generate it using
this command:
= Running the examples
$ rake package
1. Add the files to an Action Web Service enabled Rails project.
2. Edit config/environment.rb, and add the following line after the rest of the
require_gem statements:
require_gem 'actionservice'
3. "Direct" example:
"Direct" example:
* Copy direct/search_controller.rb to "app/controllers"
in a Rails project.
* Copy direct/google_search_api.rb to "app/apis"
in a Rails project
"Delegated" example:
"Delegated" example:
* Copy delegated/search_controller.rb to "app/controllers"
in a Rails project.
@ -44,7 +36,7 @@ There is also an example for API definition file autoloading.
in a Rails project.
4. Go to the WSDL url in a browser, and check that it looks correct.
2. Go to the WSDL url in a browser, and check that it looks correct.
"Direct" and "Delegated" examples:
http://url_to_project/search/wsdl
@ -60,7 +52,7 @@ There is also an example for API definition file autoloading.
explain extreme similarities :)
5. Test that it works with .NET (Mono in this example):
3. Test that it works with .NET (Mono in this example):
$ wget WSDL_URL
$ mv wsdl GoogleSearch.wsdl
@ -144,8 +136,8 @@ There is also an example for API definition file autoloading.
If you don't like this behaviour, you can do:
class MyController < ActionController::Base
service_exception_reporting false
web_service_exception_reporting false
end
6. Crack open a beer. Publishing APIs for working with the same model as
4. Crack open a beer. Publishing APIs for working with the same model as
your Rails web app should be easy from now on :)

View File

@ -1,5 +1,3 @@
require 'action_service'
class DirectoryCategory < ActionService::Struct
member :fullViewableName, :string
member :specialEncoding, :string
@ -52,7 +50,7 @@ class GoogleSearchAPI < ActionService::API::Base
end
class GoogleSearchService < ActionService::Base
service_api GoogleSearchAPI
web_service_api GoogleSearchAPI
def doGetCachedPage(key, url)
"<html><body>i am a cached page</body></html>"

View File

@ -2,6 +2,6 @@ require 'google_search_service'
class SearchController < ApplicationController
wsdl_service_name 'GoogleSearch'
service_dispatching_mode :delegated
service :beta3, GoogleSearchService.new
web_service_dispatching_mode :delegated
web_service :beta3, GoogleSearchService.new
end

View File

@ -0,0 +1,50 @@
class DirectoryCategory < ActionService::Struct
member :fullViewableName, :string
member :specialEncoding, :string
end
class ResultElement < ActionService::Struct
member :summary, :string
member :URL, :string
member :snippet, :string
member :title, :string
member :cachedSize, :string
member :relatedInformationPresent, :bool
member :hostName, :string
member :directoryCategory, DirectoryCategory
member :directoryTitle, :string
end
class GoogleSearchResult < ActionService::Struct
member :documentFiltering, :bool
member :searchComments, :string
member :estimatedTotalResultsCount, :int
member :estimateIsExact, :bool
member :resultElements, [ResultElement]
member :searchQuery, :string
member :startIndex, :int
member :endIndex, :int
member :searchTips, :string
member :directoryCategories, [DirectoryCategory]
member :searchTime, :float
end
class GoogleSearchAPI < ActionService::API::Base
inflect_names false
api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}]
api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}]
api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [
{:key=>:string},
{:q=>:string},
{:start=>:int},
{:maxResults=>:int},
{:filter=>:bool},
{:restrict=>:string},
{:safeSearch=>:bool},
{:lr=>:string},
{:ie=>:string},
{:oe=>:string}
]
end

View File

@ -1,56 +1,5 @@
class DirectoryCategory < ActionService::Struct
member :fullViewableName, :string
member :specialEncoding, :string
end
class ResultElement < ActionService::Struct
member :summary, :string
member :URL, :string
member :snippet, :string
member :title, :string
member :cachedSize, :string
member :relatedInformationPresent, :bool
member :hostName, :string
member :directoryCategory, DirectoryCategory
member :directoryTitle, :string
end
class GoogleSearchResult < ActionService::Struct
member :documentFiltering, :bool
member :searchComments, :string
member :estimatedTotalResultsCount, :int
member :estimateIsExact, :bool
member :resultElements, [ResultElement]
member :searchQuery, :string
member :startIndex, :int
member :endIndex, :int
member :searchTips, :string
member :directoryCategories, [DirectoryCategory]
member :searchTime, :float
end
class GoogleSearchAPI < ActionService::API::Base
inflect_names false
api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}]
api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}]
api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [
{:key=>:string},
{:q=>:string},
{:start=>:int},
{:maxResults=>:int},
{:filter=>:bool},
{:restrict=>:string},
{:safeSearch=>:bool},
{:lr=>:string},
{:ie=>:string},
{:oe=>:string}
]
end
class SearchController < ApplicationController
service_api GoogleSearchAPI
web_service_api :google_search
wsdl_service_name 'GoogleSearch'
def doGetCachedPage

View File

@ -1,3 +1,6 @@
# point your client at http://project_url/blog/api to test
# this
# structures as defined by the metaWeblog/blogger
# specifications.
module Blog
@ -73,7 +76,7 @@ class MetaWeblogAPI < ActionService::API::Base
end
class BlogController < ApplicationController
service_api MetaWeblogAPI
web_service_api MetaWeblogAPI
def initialize
@postid = 0
@ -99,23 +102,26 @@ class BlogController < ApplicationController
def getUsersBlogs
$stderr.puts "Returning user %s's blogs" % @params['username']
blog = Blog::Blog.new
blog.url = 'http://blog.xeraph.org'
blog.blogid = 'sttm'
blog.blogName = 'slave to the machine'
blog = Blog::Blog.new(
:url =>'http://blog.xeraph.org',
:blogid => 'sttm',
:blogName => 'slave to the machine'
)
[blog]
end
def getRecentPosts
$stderr.puts "Returning recent posts (%d requested)" % @params['numberOfPosts']
post1 = Blog::Post.new
post1.title = 'first post!'
post1.link = 'http://blog.xeraph.org/testOne.html'
post1.description = 'this is the first post'
post2 = Blog::Post.new
post2.title = 'second post!'
post2.link = 'http://blog.xeraph.org/testTwo.html'
post2.description = 'this is the second post'
post1 = Blog::Post.new(
:title => 'first post!',
:link => 'http://blog.xeraph.org/testOne.html',
:description => 'this is the first post'
)
post2 = Blog::Post.new(
:title => 'second post!',
:link => 'http://blog.xeraph.org/testTwo.html',
:description => 'this is the second post'
)
[post1, post2]
end
end

View File

@ -11,12 +11,6 @@ module ActionService # :nodoc:
module ClassMethods
# Attaches ActionService API +definition+ to the calling class.
#
# If +definition+ is not an ActionService::API::Base derivative class
# object, it may be a symbol or a string, in which case a file named
# <tt>definition_api.rb</tt> will be expected to exist in the load path,
# containing an API definition class named <tt>DefinitionAPI</tt> or
# <tt>DefinitionApi</tt>.
#
# Action Controllers can have a default associated API, removing the need
# to call this method if you follow the Action Service naming conventions.
#
@ -28,7 +22,7 @@ module ActionService # :nodoc:
# ==== Service class example
#
# class MyService < ActionService::Base
# service_api MyAPI
# web_service_api MyAPI
# end
#
# class MyAPI < ActionService::API::Base
@ -38,50 +32,50 @@ module ActionService # :nodoc:
# ==== Controller class example
#
# class MyController < ActionController::Base
# service_api MyAPI
# web_service_api MyAPI
# end
#
# class MyAPI < ActionService::API::Base
# ...
# end
def service_api(definition=nil)
def web_service_api(definition=nil)
if definition.nil?
read_inheritable_attribute("service_api")
read_inheritable_attribute("web_service_api")
else
if definition.is_a?(Symbol)
raise(APIError, "symbols can only be used for #service_api inside of a controller")
raise(APIError, "symbols can only be used for #web_service_api inside of a controller")
end
unless definition.respond_to?(:ancestors) && definition.ancestors.include?(Base)
raise(APIError, "#{definition.to_s} is not a valid API definition")
end
write_inheritable_attribute("service_api", definition)
call_service_api_callbacks(self, definition)
write_inheritable_attribute("web_service_api", definition)
call_web_service_api_callbacks(self, definition)
end
end
def add_service_api_callback(&block) # :nodoc:
write_inheritable_array("service_api_callbacks", [block])
def add_web_service_api_callback(&block) # :nodoc:
write_inheritable_array("web_service_api_callbacks", [block])
end
private
def call_service_api_callbacks(container_class, definition)
(read_inheritable_attribute("service_api_callbacks") || []).each do |block|
def call_web_service_api_callbacks(container_class, definition)
(read_inheritable_attribute("web_service_api_callbacks") || []).each do |block|
block.call(container_class, definition)
end
end
end
# A service API class specifies the methods that will be available for
# A web service API class specifies the methods that will be available for
# invocation for an API. It also contains metadata such as the method type
# signature hints.
#
# It is not intended to be instantiated.
#
# It is attached to service implementation classes like ActionService::Base
# and ActionController::Base derivatives with ClassMethods#service_api.
# It is attached to web service implementation classes like
# ActionService::Base and ActionController::Base derivatives by using
# ClassMethods#web_service_api.
class Base
# Whether to transform API method names into camel-cased
# names
# Whether to transform the public API method names into camel-cased names
class_inheritable_option :inflect_names, true
# If present, the name of a method to call when the remote caller
@ -96,13 +90,13 @@ module ActionService # :nodoc:
include ActionService::Signature
# API methods have a +name+, which must be the Ruby method name to use when
# performing the invocation on the service object.
# performing the invocation on the web service object.
#
# The type signature hints for the method input parameters and return value
# can by specified in +options+.
# The signatures for the method input parameters and return value can
# by specified in +options+.
#
# A signature hint is an array of one or more parameter type specifiers.
# A type specifier can be one of the following:
# A signature is an array of one or more parameter specifiers.
# A parameter specifier can be one of the following:
#
# * A symbol or string of representing one of the Action Service base types.
# See ActionService::Signature for a canonical list of the base types.
@ -113,15 +107,15 @@ module ActionService # :nodoc:
# * A Hash containing as key the name of the parameter, and as value
# one of the three preceding items
#
# If no method input parameter or method return value hints are given,
# the method is assumed to take no parameters and return no values of
# If no method input parameter or method return value signatures are given,
# the method is assumed to take no parameters and/or return no values of
# interest, and any values that are received by the server will be
# discarded and ignored.
#
# Valid options:
# [<tt>:expects</tt>] Signature hint for the method input parameters
# [<tt>:returns</tt>] Signature hint for the method return value
# [<tt>:expects_and_returns</tt>] Signature hint for both input parameters and return value
# [<tt>:expects</tt>] Signature for the method input parameters
# [<tt>:returns</tt>] Signature for the method return value
# [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value
def api_method(name, options={})
validate_options([:expects, :returns, :expects_and_returns], options.keys)
if options[:expects_and_returns]
@ -133,7 +127,7 @@ module ActionService # :nodoc:
end
expects = canonical_signature(expects) if expects
returns = canonical_signature(returns) if returns
if expects && Object.const_defined?('ActiveRecord')
if expects
expects.each do |param|
klass = signature_parameter_class(param)
klass = klass[0] if klass.is_a?(Array)

View File

@ -5,40 +5,35 @@ module ActionService # :nodoc:
base.class_eval do
class << self
alias_method :inherited_without_api, :inherited
alias_method :service_api_without_require, :service_api
alias_method :web_service_api_without_require, :web_service_api
end
end
base.extend(ClassMethods)
end
module ClassMethods
# Creates a _protected_ factory method with the given
# +name+. This method will create a +protocol+ client connected
# to the given endpoint URL.
# Creates a client for accessing remote web services, using the
# given +protocol+ to communicate with the +endpoint_uri+.
#
# ==== Example
#
# class MyController < ActionController::Base
# client_api :blogger, :xmlrpc, "http://blogger.com/myblog/api/RPC2", :handler_name => 'blogger'
# web_client_api :blogger, :xmlrpc, "http://blogger.com/myblog/api/RPC2", :handler_name => 'blogger'
# end
#
# In this example, a protected method named <tt>blogger</tt> will
# now exist on the controller, and calling it will return the
# XML-RPC client object for working with that remote service.
#
# The same rules as ActionService::API::Base#service_api are
# used to retrieve the API definition with the given +name+.
#
# +options+ is the set of protocol client specific options,
# see the protocol client class for details.
# see a protocol client class for details.
#
# If your API definition does not exist on the load path
# with the correct rules for it to be found, you can
# pass through the API definition class in +options+, using
# a key of <tt>:api</tt>
def client_api(name, protocol, endpoint_uri, options={})
# If your API definition does not exist on the load path with the
# correct rules for it to be found using +name+, you can pass through
# the API definition class in +options+, using a key of <tt>:api</tt>
def web_client_api(name, protocol, endpoint_uri, options={})
unless method_defined?(name)
api_klass = options.delete(:api) || require_api(name)
api_klass = options.delete(:api) || require_web_service_api(name)
class_eval do
define_method(name) do
probe_protocol_client(api_klass, protocol, endpoint_uri, options)
@ -48,18 +43,18 @@ module ActionService # :nodoc:
end
end
def service_api(definition=nil) # :nodoc:
return service_api_without_require if definition.nil?
def web_service_api(definition=nil) # :nodoc:
return web_service_api_without_require if definition.nil?
case definition
when String, Symbol
klass = require_api(definition)
klass = require_web_service_api(definition)
else
klass = definition
end
service_api_without_require(klass)
web_service_api_without_require(klass)
end
def require_api(name) # :nodoc:
def require_web_service_api(name) # :nodoc:
case name
when String, Symbol
file_name = name.to_s.underscore + "_api"
@ -88,7 +83,7 @@ module ActionService # :nodoc:
private
def inherited(child)
inherited_without_api(child)
child.service_api(child.controller_path)
child.web_service_api(child.controller_path)
rescue Exception => e
end
end

View File

@ -12,7 +12,7 @@ module ActionService # :nodoc:
# ==== Example
#
# class PersonService < ActionService::Base
# service_api PersonAPI
# web_service_api PersonAPI
#
# def find_person(criteria)
# Person.find_all [...]
@ -36,6 +36,6 @@ module ActionService # :nodoc:
class Base
# Whether to report exceptions back to the caller in the protocol's exception
# format
class_inheritable_option :service_exception_reporting, true
class_inheritable_option :web_service_exception_reporting, true
end
end

View File

@ -5,40 +5,40 @@ module ActionService # :nodoc:
def self.append_features(base) # :nodoc:
super
base.class_inheritable_option(:service_dispatching_mode, :direct)
base.class_inheritable_option(:service_exception_reporting, true)
base.class_inheritable_option(:web_service_dispatching_mode, :direct)
base.class_inheritable_option(:web_service_exception_reporting, true)
base.extend(ClassMethods)
base.send(:include, ActionService::Container::InstanceMethods)
end
module ClassMethods
# Declares a service that will provides access to the API of the given
# service +object+. +object+ must be an ActionService::Base derivative.
# Declares a web service that will provides access to the API of the given
# +object+. +object+ must be an ActionService::Base derivative.
#
# Service object creation can either be _immediate_, where the object
# Web service object creation can either be _immediate_, where the object
# instance is given at class definition time, or _deferred_, where
# object instantiation is delayed until request time.
#
# ==== Immediate service object example
# ==== Immediate web service object example
#
# class ApiController < ApplicationController
# service_dispatching_mode :delegated
# web_service_dispatching_mode :delegated
#
# service :person, PersonService.new
# web_service :person, PersonService.new
# end
#
# For deferred instantiation, a block should be given instead of an
# object instance. This block will be executed in controller instance
# context, so it can rely on controller instance variables being present.
#
# ==== Deferred service object example
# ==== Deferred web service object example
#
# class ApiController < ApplicationController
# service_dispatching_mode :delegated
# web_service_dispatching_mode :delegated
#
# service(:person) { PersonService.new(@request.env) }
# web_service(:person) { PersonService.new(@request.env) }
# end
def service(name, object=nil, &block)
def web_service(name, object=nil, &block)
if (object && block_given?) || (object.nil? && block.nil?)
raise(ContainerError, "either service, or a block must be given")
end
@ -48,56 +48,56 @@ module ActionService # :nodoc:
else
info = { name => { :object => object } }
end
write_inheritable_hash("action_services", info)
call_service_definition_callbacks(self, name, info)
write_inheritable_hash("web_services", info)
call_web_service_definition_callbacks(self, name, info)
end
# Whether this service contains a service with the given +name+
def has_service?(name)
services.has_key?(name.to_sym)
def has_web_service?(name)
web_services.has_key?(name.to_sym)
end
def services # :nodoc:
read_inheritable_attribute("action_services") || {}
def web_services # :nodoc:
read_inheritable_attribute("web_services") || {}
end
def add_service_definition_callback(&block) # :nodoc:
write_inheritable_array("service_definition_callbacks", [block])
def add_web_service_definition_callback(&block) # :nodoc:
write_inheritable_array("web_service_definition_callbacks", [block])
end
private
def call_service_definition_callbacks(container_class, service_name, service_info)
(read_inheritable_attribute("service_definition_callbacks") || []).each do |block|
block.call(container_class, service_name, service_info)
def call_web_service_definition_callbacks(container_class, web_service_name, service_info)
(read_inheritable_attribute("web_service_definition_callbacks") || []).each do |block|
block.call(container_class, web_service_name, service_info)
end
end
end
module InstanceMethods # :nodoc:
def service_object(service_name)
info = self.class.services[service_name.to_sym]
def web_service_object(web_service_name)
info = self.class.web_services[web_service_name.to_sym]
unless info
raise(ContainerError, "no such service '#{service_name}'")
raise(ContainerError, "no such web service '#{web_service_name}'")
end
service = info[:block]
service ? instance_eval(&service) : info[:object]
end
private
def dispatch_service_request(protocol_request)
case service_dispatching_mode
def dispatch_web_service_request(protocol_request)
case web_service_dispatching_mode
when :direct
dispatch_direct_service_request(protocol_request)
dispatch_direct_web_service_request(protocol_request)
when :delegated
dispatch_delegated_service_request(protocol_request)
dispatch_delegated_web_service_request(protocol_request)
else
raise(ContainerError, "unsupported dispatching mode '#{service_dispatching_mode}'")
raise(ContainerError, "unsupported dispatching mode :#{web_service_dispatching_mode}")
end
end
def dispatch_direct_service_request(protocol_request)
def dispatch_direct_web_service_request(protocol_request)
public_method_name = protocol_request.public_method_name
api = self.class.service_api
api = self.class.web_service_api
method_name = api.api_method_name(public_method_name)
block = nil
expects = nil
@ -164,10 +164,10 @@ module ActionService # :nodoc:
protocol_request.marshal(result)
end
def dispatch_delegated_service_request(protocol_request)
service_name = protocol_request.service_name
service = service_object(service_name)
api = service.class.service_api
def dispatch_delegated_web_service_request(protocol_request)
web_service_name = protocol_request.web_service_name
service = web_service_object(web_service_name)
api = service.class.web_service_api
public_method_name = protocol_request.public_method_name
method_name = api.api_method_name(public_method_name)
@ -197,7 +197,7 @@ module ActionService # :nodoc:
invocation.params = protocol_request.unmarshal
invocation.method_name = method_name.to_sym
else
raise(ContainerError, "no such method /#{service_name}##{public_method_name}")
raise(ContainerError, "no such method /#{web_service_name}##{public_method_name}")
end
end
end
@ -221,7 +221,7 @@ module ActionService # :nodoc:
invocation.method_name = method_name.to_sym
invocation.type = ActionService::Invocation::UnpublishedConcreteInvocation
else
raise(ContainerError, "no such method /#{service_name}##{public_method_name}")
raise(ContainerError, "no such method /#{web_service_name}##{public_method_name}")
end
result = perform_invoke.call
end

View File

@ -17,7 +17,7 @@ module ActionService # :nodoc:
# and after method invocations on ActionService::Base objects.
#
# When running in _Direct_ dispatching mode, ActionController filters
# should be used for this functionality.
# should be used for this functionality instead.
#
# The semantics of invocation interceptors are the same as ActionController
# filters, and accept the same parameters and options.
@ -147,8 +147,8 @@ module ActionService # :nodoc:
def perform_invocation(invocation)
if invocation.concrete?
unless self.respond_to?(invocation.method_name) && \
self.class.service_api.has_api_method?(invocation.method_name)
raise InvocationError, "no such service method '#{invocation.method_name}'"
self.class.web_service_api.has_api_method?(invocation.method_name)
raise InvocationError, "no such web service method '#{invocation.method_name}' on service object"
end
end
params = invocation.params

View File

@ -89,15 +89,15 @@ module ActionService # :nodoc:
attr :protocol
attr :raw_body
attr_accessor :service_name
attr_accessor :web_service_name
attr_accessor :public_method_name
attr_accessor :content_type
def initialize(protocol, raw_body, service_name, public_method_name, content_type, options={})
def initialize(protocol, raw_body, web_service_name, public_method_name, content_type, options={})
super(options)
@protocol = protocol
@raw_body = raw_body
@service_name = service_name
@web_service_name = web_service_name
@public_method_name = public_method_name
@content_type = content_type
end

View File

@ -297,34 +297,34 @@ module ActionService # :nodoc:
alias :map :lookup
def map_container_services(container, &block)
dispatching_mode = container.service_dispatching_mode
services = nil
dispatching_mode = container.web_service_dispatching_mode
web_services = nil
case dispatching_mode
when :direct
api = container.class.service_api
api = container.class.web_service_api
if container.respond_to?(:controller_class_name)
service_name = container.controller_class_name.sub(/Controller$/, '').underscore
web_service_name = container.controller_class_name.sub(/Controller$/, '').underscore
else
service_name = container.class.name.demodulize.underscore
web_service_name = container.class.name.demodulize.underscore
end
services = { service_name => api }
web_services = { web_service_name => api }
when :delegated
services = {}
container.class.services.each do |service_name, service_info|
web_services = {}
container.class.web_services.each do |web_service_name, web_service_info|
begin
object = container.service_object(service_name)
object = container.web_service_object(web_service_name)
rescue Exception => e
raise(ProtocolError, "failed to retrieve service object for mapping: #{e.message}")
raise(ProtocolError, "failed to retrieve web service object for web service '#{web_service_name}': #{e.message}")
end
services[service_name] = object.class.service_api
web_services[web_service_name] = object.class.web_service_api
end
end
services.each do |service_name, api|
web_services.each do |web_service_name, api|
if api.nil?
raise(ProtocolError, "no service API set while in :#{dispatching_mode} mode")
raise(ProtocolError, "no web service API set while in :#{dispatching_mode} mode")
end
map_api(api) do |api_methods|
yield service_name, api, api_methods if block_given?
yield web_service_name, api, api_methods if block_given?
end
end
end

View File

@ -28,9 +28,6 @@ module ActionService # :nodoc:
end
class XmlRpcProtocol < AbstractProtocol # :nodoc:
public
def self.create_protocol_request(container_class, action_pack_request)
helper = XMLRPC::XmlRpcHelper.instance
service_name = action_pack_request.parameters['action']
@ -160,7 +157,7 @@ module ActionService # :nodoc:
case name
when 'system.listMethods'
methods = []
api = service_class.service_api
api = service_class.web_service_api
api.api_methods.each do |name, info|
methods << api.public_api_method_name(name)
end
@ -181,7 +178,6 @@ module ActionService # :nodoc:
end
end
end
end
end
end

View File

@ -2,8 +2,8 @@ module ActionService # :nodoc:
module Router # :nodoc:
module ActionController # :nodoc:
def self.append_features(base) # :nodoc:
base.add_service_api_callback do |container_class, api|
if container_class.service_dispatching_mode == :direct && !container_class.method_defined?(:api)
base.add_web_service_api_callback do |container_class, api|
if container_class.web_service_dispatching_mode == :direct
container_class.class_eval <<-EOS
def api
process_action_service_request
@ -11,8 +11,8 @@ module ActionService # :nodoc:
EOS
end
end
base.add_service_definition_callback do |klass, name, info|
if klass.service_dispatching_mode == :delegated
base.add_web_service_definition_callback do |klass, name, info|
if klass.web_service_dispatching_mode == :delegated
klass.class_eval <<-EOS
def #{name}
process_action_service_request
@ -31,13 +31,15 @@ module ActionService # :nodoc:
begin
protocol_request = probe_request_protocol(self.request)
rescue Exception => e
logger.error "Invalid request: #{e.message}"
logger.error self.request.raw_post
unless logger.nil?
logger.error "Invalid request: #{e.message}"
logger.error self.request.raw_post
end
raise
end
if protocol_request
log_request(protocol_request)
protocol_response = dispatch_service_request(protocol_request)
protocol_response = dispatch_web_service_request(protocol_request)
log_response(protocol_response)
response_options = {
:type => protocol_response.content_type,
@ -45,20 +47,20 @@ module ActionService # :nodoc:
}
send_data(protocol_response.raw_body, response_options)
else
logger.fatal "Invalid Action Service service or method requested"
logger.fatal "Invalid Action Service service or method requested" unless logger.nil?
render_text 'Internal protocol error', "500 Invalid service/method"
end
rescue Exception => e
log_error e unless logger.nil?
exc_response = nil
case service_dispatching_mode
case web_service_dispatching_mode
when :direct
if self.class.service_exception_reporting
if self.class.web_service_exception_reporting
exc_response = protocol_request.protocol.marshal_exception(e)
end
when :delegated
service_object = service_object(protocol_request.service_name) rescue nil
if service_object && service_object.class.service_exception_reporting
web_service = web_service_object(protocol_request.service_name) rescue nil
if web_service && web_service.class.web_service_exception_reporting
exc_response = protocol_request.protocol.marshal_exception(e) rescue nil
end
end
@ -77,9 +79,9 @@ module ActionService # :nodoc:
def log_request(protocol_request)
unless logger.nil?
service_name = protocol_request.service_name
web_service_name = protocol_request.web_service_name
method_name = protocol_request.public_method_name
logger.info "\nProcessing Action Service Request: #{service_name}##{method_name}"
logger.info "\nProcessing Action Service Request: #{web_service_name}##{method_name}"
logger.info "Raw Request Body:"
logger.info protocol_request.raw_body
end

View File

@ -46,7 +46,7 @@ module ActionService # :nodoc:
def to_wsdl(container, uri, soap_action_base)
wsdl = ""
service_dispatching_mode = container.service_dispatching_mode
web_service_dispatching_mode = container.web_service_dispatching_mode
mapper = container.class.soap_mapper
namespace = mapper.custom_namespace
wsdl_service_name = namespace.split(/:/)[1]
@ -152,7 +152,7 @@ module ActionService # :nodoc:
api_methods.each do |method_name, method_signature|
public_name = service_api.public_api_method_name(method_name)
xm.operation('name' => public_name) do
case service_dispatching_mode
case web_service_dispatching_mode
when :direct
soap_action = soap_action_base + "/api/" + public_name
when :delegated
@ -183,7 +183,7 @@ module ActionService # :nodoc:
services.each do |service_name, service_values|
port_name = port_name_for(wsdl_service_name, service_name)
binding_name = binding_name_for(wsdl_service_name, service_name)
case service_dispatching_mode
case web_service_dispatching_mode
when :direct
binding_target = 'api'
when :delegated

View File

@ -14,16 +14,15 @@ module ActionService
# member :lastname, :string
# member :email, :string
# end
# person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe')
#
# Active Record model classes are already implicitly supported for method
# return signatures. A structure containing its columns as members will be
# automatically generated if its present in a signature.
#
# The structure
class Struct
# If a Hash is given as argument to an ActionService::Struct constructor,
# containing as key the member name, and its associated initial value
# it can contain initial values for the structure member.
def initialize(values={})
if values.is_a?(Hash)
values.map{|k,v| send('%s=' % k.to_s, v)}
@ -38,7 +37,7 @@ module ActionService
class << self
include ActionService::Signature
# Creates a structure member accessible using +name+. Generates
# Creates a structure member with the specified +name+ and +type+. Generates
# accessor methods for reading and writing the member value.
def member(name, type)
write_inheritable_hash("struct_members", name => signature_parameter_class(type))

View File

@ -1,5 +1,5 @@
module ActionService # :nodoc:
# Action Service parameter type specifiers may contain symbols or strings
# Action Service parameter specifiers may contain symbols or strings
# instead of Class objects, for a limited set of base types.
#
# This provides an unambiguous way to specify that a given parameter

View File

@ -26,7 +26,7 @@ module ClientTest
end
class Container < ActionController::Base
service_api API
web_service_api API
attr :value_void
attr :value_normal
@ -71,7 +71,7 @@ module ClientTest
end
def dispatch_request(protocol_request)
dispatch_service_request(protocol_request)
dispatch_web_service_request(protocol_request)
end
end

View File

@ -14,7 +14,7 @@ module BaseTest
end
class Service < ActionService::Base
service_api API
web_service_api API
def add(a, b)
end
@ -24,7 +24,7 @@ module BaseTest
end
class PristineService < ActionService::Base
service_api PristineAPI
web_service_api PristineAPI
def add
end
@ -36,7 +36,7 @@ end
class TC_Base < Test::Unit::TestCase
def test_options
assert(BaseTest::PristineService.service_api.inflect_names == false)
assert(BaseTest::Service.service_api.inflect_names == true)
assert(BaseTest::PristineService.web_service_api.inflect_names == false)
assert(BaseTest::Service.web_service_api.inflect_names == true)
end
end

View File

@ -23,7 +23,7 @@ module ClientSoapTest
end
class ClientContainer < ActionController::Base
client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
web_client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
def get_client
client

View File

@ -22,7 +22,7 @@ module ClientXmlRpcTest
end
class ClientContainer < ActionController::Base
client_api :client, :xmlrpc, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
web_client_api :client, :xmlrpc, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
def get_client
client

View File

@ -6,7 +6,7 @@ module ContainerTest
$deferred_service = Object.new
class DelegateContainer < ActionController::Base
service_dispatching_mode :delegated
web_service_dispatching_mode :delegated
attr :flag
attr :previous_flag
@ -16,12 +16,12 @@ module ContainerTest
@flag = true
end
service :immediate_service, $immediate_service
service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service }
web_service :immediate_service, $immediate_service
web_service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service }
end
class DirectContainer < ActionController::Base
service_dispatching_mode :direct
web_service_dispatching_mode :direct
end
end
@ -32,22 +32,22 @@ class TC_Container < Test::Unit::TestCase
end
def test_registration
assert(ContainerTest::DelegateContainer.has_service?(:immediate_service))
assert(ContainerTest::DelegateContainer.has_service?(:deferred_service))
assert(!ContainerTest::DelegateContainer.has_service?(:fake_service))
assert(ContainerTest::DelegateContainer.has_web_service?(:immediate_service))
assert(ContainerTest::DelegateContainer.has_web_service?(:deferred_service))
assert(!ContainerTest::DelegateContainer.has_web_service?(:fake_service))
end
def test_service_object
assert(@delegate_container.flag == true)
assert(@delegate_container.service_object(:immediate_service) == $immediate_service)
assert(@delegate_container.web_service_object(:immediate_service) == $immediate_service)
assert(@delegate_container.previous_flag.nil?)
assert(@delegate_container.flag == true)
assert(@delegate_container.service_object(:deferred_service) == $deferred_service)
assert(@delegate_container.web_service_object(:deferred_service) == $deferred_service)
assert(@delegate_container.previous_flag == true)
assert(@delegate_container.flag == false)
end
def test_direct_container
assert(ContainerTest::DirectContainer.service_dispatching_mode == :direct)
assert(ContainerTest::DirectContainer.web_service_dispatching_mode == :direct)
end
end

View File

@ -13,7 +13,7 @@ module InvocationTest
end
class Service < ActionService::Base
service_api API
web_service_api API
before_invocation :intercept_before, :except => [:no_before]
after_invocation :intercept_after, :except => [:no_after]
@ -150,7 +150,7 @@ class TC_Invocation < Test::Unit::TestCase
private
def perform_invocation(method_name, *args, &block)
public_method_name = @service.class.service_api.public_api_method_name(method_name)
public_method_name = @service.class.web_service_api.public_api_method_name(method_name)
args ||= []
request = InvocationRequest.new(ConcreteInvocation, public_method_name, method_name, args)
@service.perform_invocation(request, &block)

View File

@ -23,7 +23,7 @@ module ProtocolSoapTest
end
class Service < ActionService::Base
service_api API
web_service_api API
attr :int
attr :string
@ -85,18 +85,18 @@ module ProtocolSoapTest
end
def dispatch_request(protocol_request)
dispatch_service_request(protocol_request)
dispatch_web_service_request(protocol_request)
end
end
class DelegatedContainer < AbstractContainer
service_dispatching_mode :delegated
service :protocol_soap_service, Service.new
web_service_dispatching_mode :delegated
web_service :protocol_soap_service, Service.new
end
class DirectContainer < AbstractContainer
service_api API
service_dispatching_mode :direct
web_service_api API
web_service_dispatching_mode :direct
attr :int
attr :string
@ -207,7 +207,7 @@ class TC_ProtocolSoap < AbstractSoapTest
end
def service
@container == @direct_container ? @container : @container.service_object(:protocol_soap_service)
@container == @direct_container ? @container : @container.web_service_object(:protocol_soap_service)
end
def in_all_containers(&block)

View File

@ -35,7 +35,7 @@ module ProtocolXmlRpcTest
end
class Service < ActionService::Base
service_api API
web_service_api API
attr :result
attr :hashvalue
@ -90,11 +90,11 @@ module ProtocolXmlRpcTest
end
def dispatch_request(protocol_request)
dispatch_service_request(protocol_request)
dispatch_web_service_request(protocol_request)
end
service :xmlrpc, $service
service_dispatching_mode :delegated
web_service :xmlrpc, $service
web_service_dispatching_mode :delegated
end
end

View File

@ -7,7 +7,7 @@ module RouterActionControllerTest
end
class Service < ActionService::Base
service_api API
web_service_api API
attr :added
@ -17,9 +17,9 @@ module RouterActionControllerTest
end
class DelegatedController < ActionController::Base
service_dispatching_mode :delegated
web_service_dispatching_mode :delegated
service(:test_service) { @service ||= Service.new; @service }
web_service(:test_service) { @service ||= Service.new; @service }
end
class DirectAPI < ActionService::API::Base
@ -30,8 +30,8 @@ module RouterActionControllerTest
end
class DirectController < ActionController::Base
service_api DirectAPI
service_dispatching_mode :direct
web_service_api DirectAPI
web_service_dispatching_mode :direct
before_filter :alwaysfail, :only => [:before_filtered]
after_filter :alwaysok, :only => [:after_filtered]
@ -116,7 +116,7 @@ class TC_RouterActionController < AbstractSoapTest
exception = result.detail
assert(exception.cause.is_a?(RuntimeError))
assert_equal("Hi, I'm a SOAP exception", exception.cause.message)
@container.service_exception_reporting = false
@container.web_service_exception_reporting = false
assert_raises(SoapTestError) do
do_soap_call('Thrower')
end
@ -128,7 +128,7 @@ class TC_RouterActionController < AbstractSoapTest
end
def service
@container.service_object(:test_service)
@container.web_service_object(:test_service)
end
def do_soap_call(public_method_name, *args)

View File

@ -16,7 +16,7 @@ module RouterWsdlTest
end
class Service < ActionService::Base
service_api API
web_service_api API
def add(a, b)
a + b
@ -37,7 +37,7 @@ module RouterWsdlTest
end
class DirectController < AbstractController
service_api API
web_service_api API
def add
end
@ -50,8 +50,8 @@ module RouterWsdlTest
end
class DelegatedController < AbstractController
service_dispatching_mode :delegated
service(:test_service) { Service.new }
web_service_dispatching_mode :delegated
web_service(:test_service) { Service.new }
end
end