in reply to SOAP::Lite dispatch routine

I was going to point you to the security link, but tilly beat me to it. When you say that your $object is just a simple blessed hash, well, isn't that what all Perl objects are, simple blessed thingies? You aren't trying to pass the database handle back inside your SOAP object, are you?

Here an example that uses mod_soap, if you are not using mod_soap then i recommend you take a look at it. First, my Apache http.conf directive to make mod_soap autodispatch:

<Location /mod_soap> SetHandler perl-script PerlHandler Apache::SOAP PerlSetVar dispatch_to "/usr/local/apache/lib/soap" </Location>
Next, the dispatch object code - Factory.pm:
package Factory; use strict; use DBI; my $dbh = DBI->connect( qw(DBI:vendor:database:host user pass), { RaiseError => 1} ); sub instantiate { my ($self,$package,$id) = @_; my $sth = $dbh->selectall_arrayref(' select title,artist,year from songs where id = ? ',undef,$id)->[0]; my $obj = eval { $package->new($id,@$sth) }; return $@ ? undef : $obj; } package My::User; use strict; sub new { my ($class,$id,$title,$artist,$year) = @_; my $self = { id => $id, title => $title, artist => $artist, year => $year, }; return bless $self,$class; } # this will be discussed later ... sub foo { 'foo' } 1;
And finally, the client:
use strict; use SOAP::Lite; use Data::Dumper; my $soap = SOAP::Lite ->uri("http://127.0.0.1/Factory") ->proxy("http://127.0.0.1/mod_soap"); my $object = $soap->instantiate('My::User','5')->result; print Dumper $object;
When run, the following is printing:
$VAR1 = bless( { 'artist' => 'Van Halen', 'title' => 'You Really Got Me', 'id' => '5', 'year' => '1978' }, 'My::User' );
The idea is to just return data - not code. SOAP is insecure enough already. As a matter of fact, if you try to return a DBI handle, you get back a nice fat undefined value.

SOAP really helped me to understand more about Perl OO, especially the fact that an object DOES NOT carry its methods with it - instead, the interpreter knows which package the object is blessed and is able to find the method in question because you use'ed or require'ed the package.

To see what i mean, call the foo method from package My::User inside your SOAP client ...

my $object = $soap->instantiate('My::User','5')->result; print $object->foo(); # yields: Can't locate object method "foo" via package "My::User" at ./instantia +te.pl line 23.
Pass data - not code, that's what COM and DCOM do (pass code and/or data). Hope this helps, and feel free to ask more. ;)

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
F--F--F--F--F--F--F--F--
(the triplet paradiddle)

Replies are listed 'Best First'.
Re: (jeffa) Re: SOAP::Lite dispatch routine
by gildir (Pilgrim) on Jan 04, 2002 at 13:51 UTC
    Yes and No,

    Yes, Perl objects are just a blessed references, but they may have inner objects which in turn may have other inner objects .. which may have xsub references in them or even open file descriptors. And that is a kind of my case. Every persistent object ($object) has in it a reference to its storage object. And that storage object includes an open (and bound) handle to LDAP storage.

    And No, your example will not work in any elegant way if you want to modify an object. Look at an example.

    use strict; use SOAP::Lite; use Data::Dumper; my $soap = SOAP::Lite ->uri("http://127.0.0.1/Factory") ->proxy("http://127.0.0.1/mod_soap"); my $object = $soap->instantiate('My::User','5')->result; print Dumper $object; #$VAR1 = bless( { # 'artist' => 'Van Halen', # 'title' => 'You Really Got Me', # 'id' => '5', # 'year' => '1999' hmm, aparently wrong # }, 'My::User' ); $object->year(1978); # modify the year # aaaagrh, it does not work!
    I have fetched $object by use of instantiate() method as you suggested. But as the object is just a plain hash, it has no connection with original object on server. Modification of this object will no modify server-side object. Too bad. No persistence.

    What I'm trying to achieve is to get a 'proxy object' or a 'remote reference' on the SOAP client side. Something that I call $object->year(2002), it will call year() method on the original server-side object. This is more like CORBA IORs work.

    Passing object by reference, not by value.

      IIRC, SOAP doesn't act like CORBA by design, but you can fake it if you like. Like jeffa said, you should be able to pass the modified object back with a command to save it. The SOAP process acting as a proxy could have remembered the object when you requested it and when you pass it back for modification, save that particular object. It's not as elegant or clean as CORBA, but it's not as hairy or expensive either.

      Chris
      M-x auto-bs-mode

      I was waiting for you to take the bait ;).

      You can't do that with SOAP. You will have to pass the object back to the server if you want to modify it.

      Think about it. Looks like you need a COM/DCOM/CORBA solution, because SOAP don't do that. It's Simple Object Access PROTOCOL, not PERSISTANCE. It IS procedural RPC, just made easier.

      Have you looked into SPOPS yet?

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      F--F--F--F--F--F--F--F--
      (the triplet paradiddle)