Loading ...
Sorry, an error occurred while loading the content.

Class inheritance

Expand Messages
  • rog2@foskett.f9.co.uk
    Hi, I am trying to use a local perl module that inherits methods from a remote Perl SOAP class. I think SOAP::Lite gets confused however as with trace enabled
    Message 1 of 4 , Jun 19, 2001
    • 0 Attachment
      Hi,

      I am trying to use a local perl module that inherits methods from a
      remote Perl SOAP class. I think SOAP::Lite gets confused however as
      with trace enabled on the server, the following message is displayed:

      Use of uninitialized value in join
      at /opt/www/perl5/lib/site_perl/5.6.0/SOAP/Lite.pm line 1604.
      SOAP::Serializer::envelope: Client Failed to access class (CLI):
      Can't locate CLI.pm in @INC (@INC
      contains: /home/rfos/dev/soap/remote) at (eval 10) line 3.
      http://titan:8080/

      The result is that the remote object constructors accessed in the
      local module return undefined.

      The setup is as follows:

      CLI.pm : local module that accesses remote Temp.pm class
      Temp.pm : remote dispatched class
      client1.pl : uses CLI.pm
      client2.pl : accesses Temp.pm directly via SOAP
      preforker.pl : SOAP daemon (dispatches to dir containing Temp.pm)

      The code:

      --------------------- CLI.pm ---------------------
      package CLI;
      use SOAP::Lite +autodispatch =>
      uri => 'http://titan/',
      proxy => 'http://titan:8080';
      sub new {
      my $class = shift;
      my $self = Temp->new;
      bless $self; return $self;
      }
      sub print_c2f {
      my ($self, $c) = @_; print "c2f $c = ".$self->c2f($c)."\n";
      }
      1;

      --------------------- Temp.pm ---------------------
      package Temp;
      sub new {
      my $class = shift; my $self = {};
      bless $self, ref ($class) || $class;
      }
      sub c2f {
      my ($self, $c) = @_; return 5/9*($c-32);
      }
      1;

      --------------------- Client1.pm ---------------------
      #!/opt/perl5/bin/perl -w
      use FindBin;
      use lib "$FindBin::Bin";
      use CLI;
      my $c = CLI->new;
      my $t = 5;
      print "Inherited c2f> $t = ".$c->c2f($t)."\n";

      --------------------- Client2.pm ---------------------
      #!/opt/perl5/bin/perl -w
      use SOAP::Lite +autodispatch =>
      uri => 'http://titan/',
      proxy => 'http://titan:8080';
      my $c = Temp->new;
      my $t = 5;
      print "Direct c2f> $t = ".$c->c2f($t)."\n";

      ------------------------------------------------------

      client2.pl works perfectly as expected, though I am having trouble
      with client1.pl which I cannot get working as the Temp->new remote
      method call in the CLI constructor returns undef for some reason.

      Am I going about this in the wrong way?
      I'd appreciate any ideas

      many thanks

      Roger Foskett
    • Paul Kulchenko
      Hi, Roger! I thought I m the only crazy person who thinks about remote inheritance :)). ... Problem rather fundamental, than in your code. Imagine the
      Message 2 of 4 , Jun 19, 2001
      • 0 Attachment
        Hi, Roger!

        I thought I'm the only crazy person who thinks about remote
        inheritance :)).

        > Am I going about this in the wrong way?
        > I'd appreciate any ideas
        Problem rather fundamental, than in your code. Imagine the situation:
        You have class 'A' on server side and want to inherit class 'B' from
        it on client side. So, we create shadow of class 'A' on client side
        that will redispatch all calls remotely and put @B::ISA = 'A' as
        usual.

        What happens when you call B->new()? Call is unresolved in 'B', goes
        to 'A' and then goes to remote server with 'B' as target class. But
        server knows NOTHING about 'B' and returns error. At the same time we
        can't make a call A->new() on server side, because it'll return
        object blessed in class 'A' (so B->new() will return object blessed
        in 'A'), but we're waiting for object in class 'B'.

        What we CAN do however is make a call B->A:new() on server side which
        will do everything we need. But, we need to have this support on
        server side (which is not a problem) AND we need to pass this
        information there, which IS the problem, because before we passed
        only one class (A->method, which is the same as A->A::method), now we
        need to pass two, at least in some casses (B->A::method) and there is
        no place to do it. Perl passes class name as the first parameter, but
        I'm not sending it in the SOAP call, to make it consistent with
        object creations in other implementations. I'll take a closer look,
        because that's the feature I would like to add in the next version,
        but we need to resolve this problem first.

        Best wishes, Paul.

        --- rog2@... wrote:
        > Hi,
        >
        > I am trying to use a local perl module that inherits methods from a
        >
        > remote Perl SOAP class. I think SOAP::Lite gets confused however
        > as
        > with trace enabled on the server, the following message is
        > displayed:
        >
        > Use of uninitialized value in join
        > at /opt/www/perl5/lib/site_perl/5.6.0/SOAP/Lite.pm line 1604.
        > SOAP::Serializer::envelope: Client Failed to access class (CLI):
        > Can't locate CLI.pm in @INC (@INC
        > contains: /home/rfos/dev/soap/remote) at (eval 10) line 3.
        > http://titan:8080/
        >
        > The result is that the remote object constructors accessed in the
        > local module return undefined.
        >
        > The setup is as follows:
        >
        > CLI.pm : local module that accesses remote Temp.pm class
        > Temp.pm : remote dispatched class
        > client1.pl : uses CLI.pm
        > client2.pl : accesses Temp.pm directly via SOAP
        > preforker.pl : SOAP daemon (dispatches to dir containing
        > Temp.pm)
        >
        > The code:
        >
        > --------------------- CLI.pm ---------------------
        > package CLI;
        > use SOAP::Lite +autodispatch =>
        > uri => 'http://titan/',
        > proxy => 'http://titan:8080';
        > sub new {
        > my $class = shift;
        > my $self = Temp->new;
        > bless $self; return $self;
        > }
        > sub print_c2f {
        > my ($self, $c) = @_; print "c2f $c = ".$self->c2f($c)."\n";
        > }
        > 1;
        >
        > --------------------- Temp.pm ---------------------
        > package Temp;
        > sub new {
        > my $class = shift; my $self = {};
        > bless $self, ref ($class) || $class;
        > }
        > sub c2f {
        > my ($self, $c) = @_; return 5/9*($c-32);
        > }
        > 1;
        >
        > --------------------- Client1.pm ---------------------
        > #!/opt/perl5/bin/perl -w
        > use FindBin;
        > use lib "$FindBin::Bin";
        > use CLI;
        > my $c = CLI->new;
        > my $t = 5;
        > print "Inherited c2f> $t = ".$c->c2f($t)."\n";
        >
        > --------------------- Client2.pm ---------------------
        > #!/opt/perl5/bin/perl -w
        > use SOAP::Lite +autodispatch =>
        > uri => 'http://titan/',
        > proxy => 'http://titan:8080';
        > my $c = Temp->new;
        > my $t = 5;
        > print "Direct c2f> $t = ".$c->c2f($t)."\n";
        >
        > ------------------------------------------------------
        >
        > client2.pl works perfectly as expected, though I am having trouble
        > with client1.pl which I cannot get working as the Temp->new remote
        > method call in the CLI constructor returns undef for some reason.
        >
        > Am I going about this in the wrong way?
        > I'd appreciate any ideas
        >
        > many thanks
        >
        > Roger Foskett
        >
        >
        >
        >
        >
        >
        > To unsubscribe from this group, send an email to:
        > soaplite-unsubscribe@yahoogroups.com
        >
        >
        >
        > Your use of Yahoo! Groups is subject to
        > http://docs.yahoo.com/info/terms/
        >
        >


        __________________________________________________
        Do You Yahoo!?
        Spot the hottest trends in music, movies, and more.
        http://buzz.yahoo.com/
      • rog2@foskett.f9.co.uk
        this is a nasty hack/cheat that seems to work and maintains instance data though it is very ugly and probably breaks lots of things. Also it only assumes
        Message 3 of 4 , Jun 20, 2001
        • 0 Attachment
          this is a nasty hack/cheat that seems to work and maintains instance
          data though it is very ugly and probably breaks lots of things. Also
          it only assumes single inheritance, and cannot make proper use of
          @ISA.

          Though the below is not nice, would SOAP::Lite perhaps be able to
          make use of AUTOLOAD in a similar vein (ie provide an AUTOLOAD method
          for each unresolved class in @ISA?!)

          ho-hum,

          many thanks

          Roger Foskett

          ----------------- CLI.pm (client side) ------------
          package CLI;
          use SOAP::Lite +autodispatch =>
          uri => 'http://titan/',
          proxy => 'http://titan:8080';
          use strict;
          use vars qw($AUTOLOAD);

          sub AUTOLOAD {
          my $self = shift;
          my ($meth) = ($AUTOLOAD=~/::(.+)$/);
          bless $self,'Temp';
          my @res = $self->$meth(@_);
          bless $self,__PACKAGE__;
          return wantarray ? @res : $res[0];
          }
          sub new {
          my $class = shift;
          my $self = Temp->new;
          bless $self, $class;
          return $self;
          }
          sub print_c2f {
          my ($self, $c) = @_; print "print_c2f $c = ".$self->c2f($c)."\n";
          }
          1;

          ----------------- Temp.pm (server side) ------------
          package Temp;
          sub new {
          my $class = shift;
          my $self = {};
          bless $self, ref ($class) || $class;
          }
          sub c2f {
          my ($self, $c) = @_;
          print "C = '".(defined $self->{C}?$self->{C}:'<undef>')."'\n";
          $self->{F} = $c;
          return 32+$c*9/5;
          }
          1;
          ----------------- Client.pm (Client side) ------------
          use strict;
          use Data::Dumper;
          use FindBin;
          use lib "$FindBin::Bin";
          use CLI;

          my $c = CLI->new;
          print Dumper($c);
          print "Inherited c2f> 5 = ".$c->c2f(5)."\n";
          print Dumper($c);
          $c->{C} = 6;
          $c->print_c2f(4);
          print Dumper($c);

          ----------------- Client Output ---------------
          titan:/home/rfos/dev/soap> client1.pl
          $VAR1 = bless( {}, 'CLI' );
          Inherited c2f> 5 = 41
          $VAR1 = bless( {
          'F' => '5'
          }, 'CLI' );
          print_c2f 4 = 39.2
          $VAR1 = bless( {
          'F' => '4',
          'C' => '6'
          }, 'CLI' );




          --- In soaplite@y..., Paul Kulchenko <paulclinger@y...> wrote:
          > Hi, Roger!
          >
          > I thought I'm the only crazy person who thinks about remote
          > inheritance :)).
          >
          > > Am I going about this in the wrong way?
          > > I'd appreciate any ideas
          > Problem rather fundamental, than in your code. Imagine the
          situation:
          > You have class 'A' on server side and want to inherit class 'B' from
          > it on client side. So, we create shadow of class 'A' on client side
          > that will redispatch all calls remotely and put @B::ISA = 'A' as
          > usual.
          >
          > What happens when you call B->new()? Call is unresolved in 'B', goes
          > to 'A' and then goes to remote server with 'B' as target class. But
          > server knows NOTHING about 'B' and returns error. At the same time
          we
          > can't make a call A->new() on server side, because it'll return
          > object blessed in class 'A' (so B->new() will return object blessed
          > in 'A'), but we're waiting for object in class 'B'.
          >
          > What we CAN do however is make a call B->A:new() on server side
          which
          > will do everything we need. But, we need to have this support on
          > server side (which is not a problem) AND we need to pass this
          > information there, which IS the problem, because before we passed
          > only one class (A->method, which is the same as A->A::method), now
          we
          > need to pass two, at least in some casses (B->A::method) and there
          is
          > no place to do it. Perl passes class name as the first parameter,
          but
          > I'm not sending it in the SOAP call, to make it consistent with
          > object creations in other implementations. I'll take a closer look,
          > because that's the feature I would like to add in the next version,
          > but we need to resolve this problem first.
          >
          > Best wishes, Paul.
          >
        • Paul Kulchenko
          Hi, Roger! ... Yes. I have a similar hack that will honor inheritance according to @ISA and look nice, but it also DOES reblessing (as you did) and it might
          Message 4 of 4 , Jun 22, 2001
          • 0 Attachment
            Hi, Roger!

            > Though the below is not nice, would SOAP::Lite perhaps be able to
            > make use of AUTOLOAD in a similar vein (ie provide an AUTOLOAD
            > method for each unresolved class in @ISA?!)
            Yes. I have a similar hack that will honor inheritance according to
            @ISA and look nice, but it also DOES reblessing (as you did) and it
            might not be right thing to do in all cases and users don't have a
            control over it, so I'm still thinking what do to. Unfortunately I
            don't know any other way right now, but I'm looking for it.

            Idea is simple. I'm creating the SAME class as you have on other
            side:

            package Remote;

            sub AUTOLOAD {
            ....
            }

            so in your code you can just inherit from 'Remote' as you usually do.
            The only problem when you do:

            Your::Class->new(....)

            I need to send it as Remote->new() on server and then rebless the
            result. It's doable, but it'll ALWAYS do it, which might be not what
            you want. Any ideas will be appreciated. If I CAN send class as the
            first parameter, then it seems like I shouldn't have a problem, but
            I'm not doing it right now (to be compatible with other
            implementations). Thank you.

            Best wishes, Paul.

            --- rog2@... wrote:
            > this is a nasty hack/cheat that seems to work and maintains
            > instance
            > data though it is very ugly and probably breaks lots of things.
            > Also
            > it only assumes single inheritance, and cannot make proper use of
            > @ISA.
            >
            > Though the below is not nice, would SOAP::Lite perhaps be able to
            > make use of AUTOLOAD in a similar vein (ie provide an AUTOLOAD
            > method
            > for each unresolved class in @ISA?!)
            >
            > ho-hum,
            >
            > many thanks
            >
            > Roger Foskett
            >
            > ----------------- CLI.pm (client side) ------------
            > package CLI;
            > use SOAP::Lite +autodispatch =>
            > uri => 'http://titan/',
            > proxy => 'http://titan:8080';
            > use strict;
            > use vars qw($AUTOLOAD);
            >
            > sub AUTOLOAD {
            > my $self = shift;
            > my ($meth) = ($AUTOLOAD=~/::(.+)$/);
            > bless $self,'Temp';
            > my @res = $self->$meth(@_);
            > bless $self,__PACKAGE__;
            > return wantarray ? @res : $res[0];
            > }
            > sub new {
            > my $class = shift;
            > my $self = Temp->new;
            > bless $self, $class;
            > return $self;
            > }
            > sub print_c2f {
            > my ($self, $c) = @_; print "print_c2f $c =
            > ".$self->c2f($c)."\n";
            > }
            > 1;
            >
            > ----------------- Temp.pm (server side) ------------
            > package Temp;
            > sub new {
            > my $class = shift;
            > my $self = {};
            > bless $self, ref ($class) || $class;
            > }
            > sub c2f {
            > my ($self, $c) = @_;
            > print "C = '".(defined $self->{C}?$self->{C}:'<undef>')."'\n";
            > $self->{F} = $c;
            > return 32+$c*9/5;
            > }
            > 1;
            > ----------------- Client.pm (Client side) ------------
            > use strict;
            > use Data::Dumper;
            > use FindBin;
            > use lib "$FindBin::Bin";
            > use CLI;
            >
            > my $c = CLI->new;
            > print Dumper($c);
            > print "Inherited c2f> 5 = ".$c->c2f(5)."\n";
            > print Dumper($c);
            > $c->{C} = 6;
            > $c->print_c2f(4);
            > print Dumper($c);
            >
            > ----------------- Client Output ---------------
            > titan:/home/rfos/dev/soap> client1.pl
            > $VAR1 = bless( {}, 'CLI' );
            > Inherited c2f> 5 = 41
            > $VAR1 = bless( {
            > 'F' => '5'
            > }, 'CLI' );
            > print_c2f 4 = 39.2
            > $VAR1 = bless( {
            > 'F' => '4',
            > 'C' => '6'
            > }, 'CLI' );
            >
            >
            >
            >
            > --- In soaplite@y..., Paul Kulchenko <paulclinger@y...> wrote:
            > > Hi, Roger!
            > >
            > > I thought I'm the only crazy person who thinks about remote
            > > inheritance :)).
            > >
            > > > Am I going about this in the wrong way?
            > > > I'd appreciate any ideas
            > > Problem rather fundamental, than in your code. Imagine the
            > situation:
            > > You have class 'A' on server side and want to inherit class 'B'
            > from
            > > it on client side. So, we create shadow of class 'A' on client
            > side
            > > that will redispatch all calls remotely and put @B::ISA = 'A' as
            > > usual.
            > >
            > > What happens when you call B->new()? Call is unresolved in 'B',
            > goes
            > > to 'A' and then goes to remote server with 'B' as target class.
            > But
            > > server knows NOTHING about 'B' and returns error. At the same
            > time
            > we
            > > can't make a call A->new() on server side, because it'll return
            > > object blessed in class 'A' (so B->new() will return object
            > blessed
            > > in 'A'), but we're waiting for object in class 'B'.
            > >
            > > What we CAN do however is make a call B->A:new() on server side
            > which
            > > will do everything we need. But, we need to have this support on
            > > server side (which is not a problem) AND we need to pass this
            > > information there, which IS the problem, because before we passed
            > > only one class (A->method, which is the same as A->A::method),
            > now
            > we
            > > need to pass two, at least in some casses (B->A::method) and
            > there
            > is
            > > no place to do it. Perl passes class name as the first parameter,
            >
            > but
            > > I'm not sending it in the SOAP call, to make it consistent with
            > > object creations in other implementations. I'll take a closer
            > look,
            > > because that's the feature I would like to add in the next
            > version,
            > > but we need to resolve this problem first.
            > >
            > > Best wishes, Paul.
            > >
            >
            >
            >
            > To unsubscribe from this group, send an email to:
            > soaplite-unsubscribe@yahoogroups.com
            >
            >
            >
            > Your use of Yahoo! Groups is subject to
            > http://docs.yahoo.com/info/terms/
            >
            >


            __________________________________________________
            Do You Yahoo!?
            Get personalized email addresses from Yahoo! Mail
            http://personal.mail.yahoo.com/
          Your message has been successfully submitted and would be delivered to recipients shortly.