NAME
Gantry::Plugins::SOAPMP20 - mod_perl 2 SOAP support
SYNOPSIS
In your GEN module:
use Your::App::BaseModule qw( -PluginNamespace=YourApp SOAPMP20 );
use Gantry::Plugins::SOAPMP20 qw(
soap_in
soap_out
do_main
do_wsdl
custom_error
);
sub get_soap_ops {
my $self = shift;
return {
soap_name => 'Kids',
location => $self->location,
namespace_base => 'localhost',
operations => [
{
name => 'get_count',
expects => [
{ name => 'table_name', type => 'xsd:string' },
],
returns => [
{ name => 'count', type => 'xsd:int' },
],
},
],
};
}
Add as many operations as you need.
In your stub:
use Your::GEN::Module;
sub get_count {
my $self = shift;
my $data = shift;
return { ... };
}
Your data will have whatever was in your client's soap request. You are responsible for diagnosing all errors and for returning the correct structure (it should match the returns list). But feel free to just die when you spot an error, this module has a custom_error
method which sends valid SOAP fault messages.
DESCRIPTION
Currently SOAP is only supported for mod_perl 2.
Bigtop can help a lot with the use of this plugin. Below is what you need to do manually, should you choose that route. But first, I'll explain what is happening from overhead.
For each SOAP handler in your app, there should be one controller (or a stub/GEN controller pair) placed on a location in your httpd conf. If you do the normal thing, the GEN module (or controller if you don't have a GEN) uses this module and accepts all the exports (the list is mainly for documentation, since all of them are exported by default).
Two of the exports are Gantry handlers: do_main
and do_wsdl
. This means that the caller will look for the service itself at the location from httpd.conf, while they will add /wsdl to get the WSDL file. For example, suppose you have this in your httpd.conf:
<Location /appname/SOAP>
SetHandler perl-script
PerlHandler YourApp::YourSoapStub
</Location>
Then users will hit /appname/SOAP
to get the service and /appname/SOAP/wsdl
to get the WSDL file.
This module registers a pre_init
callback which steals all of the body of the POST from the client. Then it lets Gantry do its normal work. So your stub methods will be called through a site object.
All SOAP requests are handled by do_main
, which this module exports. It uses the internal soap_in
method to parse the input. You must import soap_in
, so it will be in the site object. It fishes the client's desired action out of the incoming SOAP request and calls the method of the same name in the stub module. That method receives the SOAP request as parsed by XML::Simple's XMLin
function. It must return the structure which will be returned to the client.
The action method's structure is then fed to soap_out
(which you must also import) and the result is returned as a plain text/xml SOAP message to the client. SOAP::Lite
's SOAP::Data
and SOAP::Serializer
are used to the hard work of making output.
Here are the details of what your need to implement.
You need a namespace
method which returns the same name as the -PluginNamespace
.
You also need a get_soap_ops
method which returns a hash describing your WSDL file. See the SYNOPSIS for an example. Here's what the keys do:
- soap_name
-
This is used whenever SOAP requires a name. Prefixes and suffices are appended to it, as in NAME_Binding.
- location
-
Normally, you should make this
<$self-
location>>, so that all requests come to the same SOAP controller which produced the WSDL file. - namespace_base
-
This should be everything after
http://
and before<$self-
app_rootp>> in the URL of the SOAP service. Usually that is just the domain. - operations
-
An array reference of hashes describing the services you offer. Each element is a hash with these keys:
- name
-
The name of the action method in your stub controller, which will handle the request.
- expects
-
An array reference of parameters the method expects. These have two keys: name and type. They type can be any valid xsd: type or any other type in your WSDL file. If you need to define types, see WSDL TYPES below.
- returns
-
An array exactly like expects, except that it represents your promise to the client of what will be in the SOAP response.
- get_callbacks
-
Called by Gantry's import method to register the callbacks for this module.
WSDL TYPES
Gantry ships with wsdl.tt which it uses by default to construct the WSDL file from the result of get_soap_ops
. If you need to define types, simply copy that template into your own root path and add the types you need. If you want to supply your own data to the template, just implement your own get_soap_ops
and return whatever your template expects.
METHODS
All of these are exported by default. You may supply your own, or accept the imports. Failure to do one of those two is fatal. Doing both will earn you a subroutine redefinition warning.
- steal_post_body
-
Steals the body of the POST request before Gantry's engine can get to it. This method must be registered to work. Do that by using the plugin as you use your base module:
use Your::App qw( -PluginNamespace=module_name SOAPMP20 );
Note that you don't have to do this in the same place as you load the engine. In fact, that probably isn't a great idea, since it could lead you down the primrose path to all of your modules using the plugin's
steal_post_body
, leaving you without form data.Then, you must also implement a method called
namespace
which returns the same string as the-PluginNamespace
. - do_main
-
The SOAP service. Fishes the POST body out of
pnotes
(where it is calledraw_body
), parses it usingsoap_in
, dispatches to your action method, makes the SOAP response withsoap_out
, and returns it. - do_wsdl
-
Uses wsdl.tt to return a WSDL file for your service to the client. It uses
get_soap_ops
to know what to put in the WSDL file. Its template is wsdl.tt. You must call yours that, but feel free to copy the standard one to an earlier element of the root template path and edit it. - soap_in
-
For internal use. Uses XML::Simple to parse the incoming SOAP request.
- soap_out
-
For internal use. Forms a valid (though simple) SOAP response. Note that this module may not be able to handle your complex types. It uses
SOAP::Lite
'sSOAP::Data
andSOAP::Serializer
modules to generate the XML response. - custom_error
-
Returns a valid SOAP fault response. You must either accept this method in your imports or write one yourself. The standard error is not SOAP aware.
AUTHOR
Phil Crow, <crow.phil@gmail.com>
COPYRIGHT and LICENSE
Copyright (c) 2007, Phil Crow
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.