List Info

Thread: XML::Compile::WSDL11 - accessing the transport layer




XML::Compile::WSDL11 - accessing the transport layer
country flaguser name
Australia
2008-04-10 21:08:39
I'm using XML::Compile::WSDL11 to generate some SOAP
services, but I want to
get access to the LWP::UserAgent object.. to do that I need
to get the
XML::Compile::Transport::SOAPHTTP object, but it's eluding
me on the correct
incantations to retrieve it from the X-C-WSDL11 object.

Can anyone help me with the missing step here?

my $wsdl = slurp('service.wsdl');
my $service = XML::Compile::WSDL11->new($wsdl);
my $transport = $service->????; # <---
my $ua = $transport->userAgent;
my $call = $service->compileClient('MyService', port
=> 'MyPort');
$call->( answer => 42 );

Cheers,
Toby

Re: XML::Compile::WSDL11 - accessing the transport layer
country flaguser name
Australia
2008-04-11 00:02:13
On Fri, Apr 11, 2008 at 12:08:39PM +1000, Toby Corkindale
wrote:
> I'm using XML::Compile::WSDL11 to generate some SOAP
services, but I want to
> get access to the LWP::UserAgent object.. to do that I
need to get the
> XML::Compile::Transport::SOAPHTTP object, but it's
eluding me on the correct
> incantations to retrieve it from the X-C-WSDL11
object.
> 
> Can anyone help me with the missing step here?

I never did figure out the right way to get to the transport
layer, and
eventually decided that X-C-T-SOAPHTTP just didn't export
the package-wide
%transporters hash via any means.

I created a work-around, see below if you ever need to do
this yourself:

> my $wsdl = slurp('service.wsdl');
> my $service = XML::Compile::WSDL11->new($wsdl);

my $transport = XML::Compile::Transport::SOAPHTTP->new(
    address => $server_uri
);
my $ua = $transport->userAgent;
# Hurrah, now set all your custom LWP::UserAgent options.
# ...

my $call = $service->compileClient('MyService',
    port => 'MyPort',
    transport => $transport,
);

> $call->( answer => 42 );


In this case I already knew what the destination address URL
was, and could set
it manually in $server_uri. If you don't know what it is, it
can be obtained by
XML::Compile::WSDL11::Operation's endPoints() function; in
order to get an
Operation object you can call ->operation on your WSDL
object, but you'll have
to pass a valid operation name; a list of these is available
from the
WSDL->operations function.


I welcome any suggestions on easier ways to perform this..

Toby

Re: XML::Compile::WSDL11 - accessing the transport layer
country flaguser name
Netherlands
2008-04-11 03:37:17
* Toby Corkindale (tjcwintrmute.net) [080411 05:02]:
> On Fri, Apr 11, 2008 at 12:08:39PM +1000, Toby
Corkindale wrote:
> > I'm using XML::Compile::WSDL11 to generate some
SOAP services, but I
> > want to get access to the LWP::UserAgent object..
> > 
> > Can anyone help me with the missing step here?
> 
> I never did figure out the right way to get to the
transport layer, and
> eventually decided that X-C-T-SOAPHTTP just didn't
export the package-wide
> %transporters hash via any means.
> 
> I created a work-around, see below if you ever need to
do this yourself:
> 
> > my $wsdl = slurp('service.wsdl');
> > my $service =
XML::Compile::WSDL11->new($wsdl);

You can also do:
    my $service =
XML::Compile::WSDL11->new('service.wsdl');

> my $transport =
XML::Compile::Transport::SOAPHTTP->new(
>     address => $server_uri
> );

The problem is that a WSDL can declare multiple protocols,
which may
not be support by one transport implementation, like LWP. 
For instance,
I already got sucj report about XMPP (Jabber)... not
supported by LWP,
but used in WSDL.

So, there cannot be a $service->userAgent method, even
though there
may be a global variable which contains it...

> my $ua = $transport->userAgent;
> # Hurrah, now set all your custom LWP::UserAgent
options.
> # ...
> 
> my $call = $service->compileClient('MyService',
>     port => 'MyPort',
>     transport => $transport,
> );

The only way to get your hands on the LWP::UserAgent used
for one or
more WSDL operations, is by avoiding the auto-generated
internal
objects, but specify them explicitly.  So, you approach is
sane.

You could also do:
   my $ua    = LWP::UserAgent->new;   # get it somewhere,
SSL setup>
   my $transporter =
XML::Compile::Transport::SOAPHTTP->new(user_agent =>
$ua);
   my $http  = $transporter->compileClient(soap =>
'SOAP11', ...);
   my $call  = $wsdl->compileClient('myport', transport
=> $http);
   $call->($data);

You can leave-out steps 1, 2, and/or 3 in various
combinations, to still
get something working.  Each step has its own
responsibilities, so may
require configuration.  This traject is not documented as a
whole yet.

> I welcome any suggestions on easier ways to perform
this..

Gladly, you can reuse the objects in all above steps, so
probably it
is not too much of a burdon on the whole program when you
need to
configure this communication layers in special ways.
-- 
Regards,
               MarkOv

------------------------------------------------------------
------------
       Mark Overmeer MSc                               
MARKOV Solutions
       MarkOvermeer.net                          solutionsovermeer.net
http://Mark.Overmeer.net
                  http://solutions.overme
er.net


Re: XML::Compile::WSDL11 - accessing the transport layer
country flaguser name
Australia
2008-04-14 02:30:58
On Fri, Apr 11, 2008 at 10:37:17AM +0200, Mark Overmeer
wrote:
> * Toby Corkindale (tjcwintrmute.net) [080411
05:02]:
> > On Fri, Apr 11, 2008 at 12:08:39PM +1000, Toby
Corkindale wrote:
> > > I'm using XML::Compile::WSDL11 to generate
some SOAP services, but I
> > > want to get access to the LWP::UserAgent
object..
> > > 
> > > Can anyone help me with the missing step
here?
> > 
> > I never did figure out the right way to get to the
transport layer, and
> > eventually decided that X-C-T-SOAPHTTP just didn't
export the package-wide
> > %transporters hash via any means.
> > 
> > I created a work-around, see below if you ever
need to do this yourself:
> > 
> > > my $wsdl = slurp('service.wsdl');
> > > my $service =
XML::Compile::WSDL11->new($wsdl);
> 
> You can also do:
>     my $service =
XML::Compile::WSDL11->new('service.wsdl');

Ah, I'd forgotten. In my real-life case I'm actually pulling
the WSDL out via a
configuration stage so as to allow for testing vs production
versions, and
replaced it all with slurp() to simplify the example 

> > my $transport =
XML::Compile::Transport::SOAPHTTP->new(
> >     address => $server_uri
> > );
> 
> The problem is that a WSDL can declare multiple
protocols, which may
> not be support by one transport implementation, like
LWP.  For instance,
> I already got sucj report about XMPP (Jabber)... not
supported by LWP,
> but used in WSDL.
> 
> So, there cannot be a $service->userAgent method,
even though there
> may be a global variable which contains it...

Hmm. I understand your point.

It might be nice if there was an intermediate stage between
the WSDL11() call
and the $wsdl->compileClient() call, where one could
adjust options. I say this
because it is a pity that compileClient()'s result is a
function pointer and
thus rather immutable.

ie. This would be useful to me.. and possibly no-one else


my $service = XML::Compile::WSDL11->new($wsdl);
my $callObj = $service->prepareClient('stock_price');
my $transport = $callObj->transport;
if ($transport->can('userAgent')) {
    my $ua = $transport->userAgent;
    $ua->proxy('http', 'http://example.com:3128')
;
    # etc
}
my $call = $callobj->compile;

$call->(ticker => 'PERL');

[snip]
> The only way to get your hands on the LWP::UserAgent
used for one or
> more WSDL operations, is by avoiding the auto-generated
internal
> objects, but specify them explicitly.  So, you approach
is sane.
> 
> You could also do:
>    my $ua    = LWP::UserAgent->new;   # get it
somewhere, SSL setup>
>    my $transporter =
XML::Compile::Transport::SOAPHTTP->new(user_agent =>
$ua);
>    my $http  = $transporter->compileClient(soap
=> 'SOAP11', ...);
>    my $call  = $wsdl->compileClient('myport',
transport => $http);
>    $call->($data);
> 
> You can leave-out steps 1, 2, and/or 3 in various
combinations, to still
> get something working.  Each step has its own
responsibilities, so may
> require configuration.  This traject is not documented
as a whole yet.

AH, thanks for the alternates; I'll try those out too,
although it seems
confusing that you're calling compileClient twice in the
chain.


I found it tricky to determine that I was allowed to pass
the transport object
through, or that it was even a good idea.
Might I suggest that XML::Compile::WSDL11's document is
modified to mention
how to pass through transport options, as an example, like
the transport_hook
examples?

Thanks for the library by the way - in general it's all
worked well and been
easy to use.

Toby

Re: XML::Compile::WSDL11 - accessing the transport layer
country flaguser name
Netherlands
2008-04-14 03:38:12
* Toby Corkindale (tjcwintrmute.net) [080414 07:30]:
> > > > my $wsdl = slurp('service.wsdl');
> > > > my $service =
XML::Compile::WSDL11->new($wsdl);

> On Fri, Apr 11, 2008 at 10:37:17AM +0200, Mark Overmeer
wrote:
> >     my $service =
XML::Compile::WSDL11->new('service.wsdl');

> Ah, I'd forgotten. In my real-life case I'm actually
pulling the WSDL out
> via a
> configuration stage so as to allow for testing vs
production versions, and
> replaced it all with slurp() to simplify the example


You can also use a variable with filename or string ;-b

> It might be nice if there was an intermediate stage
between the WSDL11() call
> and the $wsdl->compileClient() call, where one could
adjust options. I say this
> because it is a pity that compileClient()'s result is a
function pointer and
> thus rather immutable.

The basic idea behind "compilation" is that the
result is immutable.
When translating a programming-language like thing (like a
schema is)
you can translate this into an object tree, to a virtual
machine like
thing, or into an other language.

SOAP::WSDL translates into objects.  Disadvantage: lot of
run-time
(while message parsing) method call's because you do not
know when the
object changes.  Big advantage: easy to debug.

Perl5 use the second approach: compile into nodes which do
the work.
The way to get this to work for XML::Compile is the use of
closures.
As downsides, Perl5 closures do not support
introspection...

The third way is used by Perl6 and Java: they generate some
other
(binary?) language, which on its own is translated into one
of these
three options (recusively).  It is possible to write
XML::Compile
back-ends which produces Perl in stead of code references
(next to
the existing XmlReader, XmlWriter, Template back-ends),
however I do
not prefer that.

> my $service = XML::Compile::WSDL11->new($wsdl);
> my $callObj =
$service->prepareClient('stock_price');
> my $transport = $callObj->transport;
> ie. This would be useful to me.. and possibly no-one
else 

There are five components in the implementation, which I
really like
to keep as separate as possible:  XML, XML-Schemas, SOAP,
WSDL, HTTP.
In the general case, you do not need to see more thatn the
WSDL
layer, but if you want to interfere with lower-level
interfaces, you
only have to create them in "lowest-level first"
order.  As I showed
in the previous mail.

The decission about how to connect the various components
are made
in the compile routines, not in the object.  It directly
results in
closure captured variables which are used in the code
reference
returned.  For each compiled client, these decissions can
result in
different settings, and therefore it cannot be provided on
the
encapsulating object.  I.e., the object which is the result
of
prepareClient() will decide differently when the compiled
for
SOAP11 or SOAP12...

It is very simple to make all kinds of assumptions about
what can be
found in WSDL files in general.  But the situation is really
complex
(and badly documented in the specs).

> >    my $http  = $transporter->compileClient(soap
=> 'SOAP11', ...);
> >    my $call  = $wsdl->compileClient('myport',
transport => $http);
> > 
> AH, thanks for the alternates; I'll try those out too,
although it seems
> confusing that you're calling compileClient twice in
the chain.

One is a transporter client (HTTP, in this case), the other
is a soap
client.  Overload of the term "client". 
Internally, there are even
more compileClients :(

> I found it tricky to determine that I was allowed to
pass the transport
> object through, or that it was even a good idea.
> Might I suggest that XML::Compile::WSDL11's document is
modified to mention
> how to pass through transport options, as an example,
like the transport_hook
> examples?

There is never sufficient documentation...  Besides, again
in the WSDL
case, there are different options depending on the actual
transport
protocol being used and the implementation of the
transporter.
The text would become very long, too long for the manual
page... probably
there should be a FAQ page as well.  The best you get for
the moment is in
the example scripts.

It would be nice if there were a mailinglist, because the
number of
users grows fast, and now support consumes my development
time.
-- 
Regards,

               MarkOv

------------------------------------------------------------
------------
       Mark Overmeer MSc                               
MARKOV Solutions
       MarkOvermeer.net                          solutionsovermeer.net
http://Mark.Overmeer.net
                  http://solutions.overme
er.net

[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )