.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Gantry::Plugins::SOAP::RPC 3"
.TH Gantry::Plugins::SOAP::RPC 3 "2008-01-18" "perl v5.8.8" "User Contributed Perl Documentation"
.SH "NAME"
Gantry::Plugins::SOAP::RPC \- RPC style SOAP support
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
In your \s-1GEN\s0 module:
.PP
.Vb 7
\& use Your::App::BaseModule qw( -PluginNamespace=YourApp SOAP::RPC );
\& # this will export these into your package:
\& # soap_in
\& # soap_out
\& # do_main
\& # do_wsdl
\& # return_error
.Ve
.PP
.Vb 2
\& sub get_soap_ops {
\& my $self = shift;
.Ve
.PP
.Vb 16
\& 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' },
\& ],
\& },
\& ],
\& };
.Ve
.PP
.Vb 1
\& }
.Ve
.PP
Add as many operations as you need.
.PP
In your stub:
.PP
.Vb 1
\& use Your::GEN::Module;
.Ve
.PP
.Vb 3
\& sub get_count {
\& my $self = shift;
\& my $data = shift;
.Ve
.PP
.Vb 2
\& return { ... };
\& }
.Ve
.PP
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 traps those and uses its
\&\f(CW\*(C`return_error\*(C'\fR method which sends valid \s-1SOAP\s0 fault messages.
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This plugin is for rpc style \s-1SOAP\s0 requests only. If you need document
style requests, you should use Gantry::Plugins::SOAP::Doc.
.PP
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.
.PP
For each \s-1SOAP\s0 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 \s-1GEN\s0 module (or controller if you don't have
a \s-1GEN\s0) uses this module and accepts all the exports (the list is mainly
for documentation, since all of them are exported by default).
.PP
Two of the exports are Gantry handlers: \f(CW\*(C`do_main\*(C'\fR and \f(CW\*(C`do_wsdl\*(C'\fR. 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 \s-1WSDL\s0 file. For example,
suppose you have this in your httpd.conf:
.PP
.Vb 4
\&
\& SetHandler perl-script
\& PerlHandler YourApp::YourSoapStub
\&
.Ve
.PP
Then users will hit \f(CW\*(C`/appname/SOAP\*(C'\fR to get the service and
\&\f(CW\*(C`/appname/SOAP/wsdl\*(C'\fR to get the \s-1WSDL\s0 file.
.PP
This module registers a \f(CW\*(C`pre_init\*(C'\fR callback which steals all of the
body of the \s-1POST\s0 from the client. Then it lets Gantry do its normal
work. So your stub methods will be called through a site object.
.PP
All \s-1SOAP\s0 requests are handled by \f(CW\*(C`do_main\*(C'\fR, which this module exports.
It uses the internal \f(CW\*(C`soap_in\*(C'\fR method to parse the input. You must
import \f(CW\*(C`soap_in\*(C'\fR, so it will be in the site object. It fishes the
client's desired action out of the incoming \s-1SOAP\s0 request and calls
the method of the same name in the stub module. That method receives
the \s-1SOAP\s0 request as parsed by XML::Simple's \f(CW\*(C`XMLin\*(C'\fR function.
It must return the structure which will be returned to the client.
.PP
The action method's structure is then fed to \f(CW\*(C`soap_out\*(C'\fR (which you
must also import) and the result is returned as a plain text/xml
\&\s-1SOAP\s0 message to the client. \f(CW\*(C`SOAP::Lite\*(C'\fR's \f(CW\*(C`SOAP::Data\*(C'\fR and
\&\f(CW\*(C`SOAP::Serializer\*(C'\fR are used to the hard work of making output.
.PP
Here are the details of what your need to implement.
.PP
You need a \f(CW\*(C`namespace\*(C'\fR method which returns the same name as the
\&\f(CW\*(C`\-PluginNamespace\*(C'\fR.
.PP
You also need a \f(CW\*(C`get_soap_ops\*(C'\fR method which returns a hash describing your
\&\s-1WSDL\s0 file. See the \s-1SYNOPSIS\s0 for an example. Here's what the keys do:
.IP "soap_name" 4
.IX Item "soap_name"
This is used whenever \s-1SOAP\s0 requires a name. Prefixes and suffices are
appended to it, as in NAME_Binding.
.IP "location" 4
.IX Item "location"
Normally, you should make this \f(CW\*(C`<$self\-\*(C'\fRlocation>>, so that all requests
come to the same \s-1SOAP\s0 controller which produced the \s-1WSDL\s0 file.
.IP "namespace_base" 4
.IX Item "namespace_base"
This should be everything after \f(CW\*(C`http://\*(C'\fR and before \f(CW\*(C`<$self\-\*(C'\fRapp_rootp>>
in the \s-1URL\s0 of the \s-1SOAP\s0 service. Usually that is just the domain.
.IP "operations" 4
.IX Item "operations"
An array reference of hashes describing the services you offer. Each
element is a hash with these keys:
.RS 4
.IP "name" 4
.IX Item "name"
The name of the action method in your stub controller, which will handle
the request.
.IP "expects" 4
.IX Item "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 \s-1WSDL\s0 file. If you need to define types, see \s-1WSDL\s0 \s-1TYPES\s0 below.
.IP "returns" 4
.IX Item "returns"
An array exactly like expects, except that it represents your promise
to the client of what will be in the \s-1SOAP\s0 response.
.RE
.RS 4
.RE
.IP "get_callbacks" 4
.IX Item "get_callbacks"
Called by Gantry's import method to register the callbacks for this module.
.SH "WSDL TYPES"
.IX Header "WSDL TYPES"
Gantry ships with wsdl.tt which it uses by default to construct the \s-1WSDL\s0
file from the result of \f(CW\*(C`get_soap_ops\*(C'\fR. 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 \f(CW\*(C`get_soap_ops\*(C'\fR and return whatever your template
expects.
.SH "METHODS"
.IX Header "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.
.IP "steal_post_body" 4
.IX Item "steal_post_body"
Steals the body of the \s-1POST\s0 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:
.Sp
.Vb 4
\& use Your::App qw(
\& -PluginNamespace=module_name
\& SOAP::RPC
\& );
.Ve
.Sp
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
\&\f(CW\*(C`steal_post_body\*(C'\fR, leaving you without form data.
.Sp
Then, you must also implement a method called \f(CW\*(C`namespace\*(C'\fR which returns
the same string as the \f(CW\*(C`\-PluginNamespace\*(C'\fR.
.Sp
This method delegates its work to \f(CW\*(C`consume_post_body\*(C'\fR, which is exported
by each engine.
.IP "do_main" 4
.IX Item "do_main"
The \s-1SOAP\s0 service. Fishes the \s-1POST\s0 body with \f(CW\*(C`get_post_body\*(C'\fR parses it
using \f(CW\*(C`soap_in\*(C'\fR, dispatches to your action method, makes the \s-1SOAP\s0 response
with \f(CW\*(C`soap_out\*(C'\fR, and returns it.
.IP "do_wsdl" 4
.IX Item "do_wsdl"
Uses wsdl.tt to return a \s-1WSDL\s0 file for your service to the client.
It uses \f(CW\*(C`get_soap_ops\*(C'\fR to know what to put in the \s-1WSDL\s0 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.
.IP "soap_in" 4
.IX Item "soap_in"
For internal use. Uses XML::Simple to parse the incoming \s-1SOAP\s0 request.
.IP "soap_out" 4
.IX Item "soap_out"
For internal use. Forms a valid (though simple) \s-1SOAP\s0 response. Note
that this module may not be able to handle your complex types.
It uses \f(CW\*(C`SOAP::Lite\*(C'\fR's \f(CW\*(C`SOAP::Data\*(C'\fR and \f(CW\*(C`SOAP::Serializer\*(C'\fR
modules to generate the \s-1XML\s0 response.
.IP "return_error" 4
.IX Item "return_error"
Returns a valid \s-1SOAP\s0 fault response. You must either accept this method
in your imports or write one yourself. The standard error is not \s-1SOAP\s0
aware.
.SH "AUTHOR"
.IX Header "AUTHOR"
Phil Crow,
.SH "COPYRIGHT and LICENSE"
.IX Header "COPYRIGHT and LICENSE"
Copyright (c) 2007, Phil Crow
.PP
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.