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

Object variables on server, methods on client

Expand Messages
  • kesslernicolas@yahoo.com
    Hi I realize this question has probably more to do with my Perl-OO-Ignorance than with SOAP::Lite, but the context is a typical SOAP situation: I have a class
    Message 1 of 6 , May 21, 2001
    • 0 Attachment
      Hi

      I realize this question has probably more to do
      with my Perl-OO-Ignorance than with SOAP::Lite,
      but the context is a typical SOAP situation:

      I have a class that provides numerous access
      methods to a huge hash. Object instantiation
      on the SOAP client will transfer all of the hash
      to the client, which is not acceptable.
      I would like to access the hash on the server
      but call the object's methods from the client.

      How do I have to build this solution? Please
      explain slowly :-)

      Regards,
      Nicolas
    • Paul Kulchenko
      Hi, Nicolas! Store it as a class data on server side: package My; my %huge_hash = ( a = 1, ); sub new { my $proto = shift; my $class = ref($proto) || $proto;
      Message 2 of 6 , May 21, 2001
      • 0 Attachment
        Hi, Nicolas!

        Store it as a class data on server side:

        package My;

        my %huge_hash = (
        a => 1,
        );

        sub new {
        my $proto = shift;
        my $class = ref($proto) || $proto;
        bless {} => $class;
        }

        sub access_hash {
        #... do something with %huge_hash
        }

        And do NOT include reference to this hash in object (blessed ref).
        This example will work if you have the same hash for all objects.

        If you hash is different for different objects, but you don't want to
        transfer them anyway, then take a look into object-by-reference.
        Examples for server side is available in PersistentIterator.pm
        SessionIterator.pm, Chat.pm and others (almost all server examples
        have references to those modules). No changes required on client
        side, but this technique is more complex, require managing garbage
        collection and additional coding on server side. If you can I
        recommend to stay with the first option.

        Best wishes, Paul.

        --- kesslernicolas@... wrote:
        > Hi
        >
        > I realize this question has probably more to do
        > with my Perl-OO-Ignorance than with SOAP::Lite,
        > but the context is a typical SOAP situation:
        >
        > I have a class that provides numerous access
        > methods to a huge hash. Object instantiation
        > on the SOAP client will transfer all of the hash
        > to the client, which is not acceptable.
        > I would like to access the hash on the server
        > but call the object's methods from the client.
        >
        > How do I have to build this solution? Please
        > explain slowly :-)
        >
        > Regards,
        > Nicolas
        >
        >
        >
        > 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!?
        Yahoo! Auctions - buy the things you want at great prices
        http://auctions.yahoo.com/
      • Douglas Bonar
        ... In some sense the case of a different hash for each object isn t that much different from the one big hash. It is a nice model to use for OO Perl tasks.
        Message 3 of 6 , May 21, 2001
        • 0 Attachment
          Paul Kulchenko wrote:
          >
          > Hi, Nicolas!
          >
          > Store it as a class data on server side:
          >
          > package My;
          >
          > my %huge_hash = (
          > a => 1,
          > );
          >
          > sub new {
          > my $proto = shift;
          > my $class = ref($proto) || $proto;
          > bless {} => $class;
          > }
          >
          > sub access_hash {
          > #... do something with %huge_hash
          > }
          >
          > And do NOT include reference to this hash in object (blessed ref).
          > This example will work if you have the same hash for all objects.
          >
          > If you hash is different for different objects, but you don't want to
          > transfer them anyway, then take a look into object-by-reference.

          In some sense the case of a different hash for each object
          isn't that much different from the one big hash. It is a nice
          model to use for OO Perl tasks. You might call this a 'handle/body'
          or 'double reference' technique.

          The following is the (rough) idea typed in from memory.
          The object you are passing back to the user is just a reference
          to a scalar. The value of that scalar is the pointer to the
          actual data location (it only matters that it is a unique string
          value associated with the real data hash), and at the same time
          the key for the internal (private) %Data hash. Then rather than
          the standard '1st argument is a hash reference' template in your
          methods, you add the extra line that the '1st argument is the key
          to retrieve the hash reference'.

          The 2 subtleties seem to be:
          * It is built on a closure which some people are scared of. That
          just means you need to define all of your methods inside
          the scope including %Data.
          * There needs to be a destructor in the package. When the scalar
          object goes out of scope, we need to clean out the private
          %Data hash. The internal %data hash created in the constructor
          would otherwise always hang around because the %Data hash has
          a reference to it.


          Blame me for the faults in the presentation or details.
          The good idea came to me from Damian Conway's excellent OOPerl book.

          Doug



          my Package;
          { my %Data;

          sub new {
          my $class = shift;
          my %data = @_; # assuming an array for simplicity
          my $addr = ref \%data;
          $Data{$addr} = \%data;
          return bless \$addr, ref $class || $class;
          }

          sub method {
          my ($self, @args) = @_;
          $self = $Data{$$self};
          # do something with the data, working with $self just as usual
          }

          sub DESTROY {
          delete $Data{${$_[0]}};
          }

          }
        • Paul Kulchenko
          Hi, Douglas! While idea is right and valid, it may not work as planned for SOAP implementation. Here is why. First, I don t have a proper way to serialize
          Message 4 of 6 , May 21, 2001
          • 0 Attachment
            Hi, Douglas!

            While idea is right and valid, it may not work as planned for SOAP
            implementation. Here is why. First, I don't have a proper way to
            serialize reference to scalar (I'm using subelements right now), so
            it'll be deserialized as hash. I'm working on finding the right way,
            but it seems like other languages don't have direct analogies and
            other XML serializers in Perl don't do SCALAR refs. Second problem is
            that object will be destroyed on server side right after
            serialization, so when it'll come back from client side proper
            element from %Data won't be there anymore. That's why you need to
            manage it based on different approach. The same problem as with any
            other session management for stateless protocol. I would like to
            build o-b-r based on Apache::Session, so you'll be able to get access
            and manage sessions based on way you like (thru the different
            interfaces).

            Best wishes, Paul.

            --- Douglas Bonar <Doug.Bonar@...> wrote:
            > Paul Kulchenko wrote:
            > >
            > > Hi, Nicolas!
            > >
            > > Store it as a class data on server side:
            > >
            > > package My;
            > >
            > > my %huge_hash = (
            > > a => 1,
            > > );
            > >
            > > sub new {
            > > my $proto = shift;
            > > my $class = ref($proto) || $proto;
            > > bless {} => $class;
            > > }
            > >
            > > sub access_hash {
            > > #... do something with %huge_hash
            > > }
            > >
            > > And do NOT include reference to this hash in object (blessed
            > ref).
            > > This example will work if you have the same hash for all objects.
            > >
            > > If you hash is different for different objects, but you don't
            > want to
            > > transfer them anyway, then take a look into object-by-reference.
            >
            > In some sense the case of a different hash for each object
            > isn't that much different from the one big hash. It is a nice
            > model to use for OO Perl tasks. You might call this a
            > 'handle/body'
            > or 'double reference' technique.
            >
            > The following is the (rough) idea typed in from memory.
            > The object you are passing back to the user is just a reference
            > to a scalar. The value of that scalar is the pointer to the
            > actual data location (it only matters that it is a unique string
            > value associated with the real data hash), and at the same time
            > the key for the internal (private) %Data hash. Then rather than
            > the standard '1st argument is a hash reference' template in your
            > methods, you add the extra line that the '1st argument is the key
            > to retrieve the hash reference'.
            >
            > The 2 subtleties seem to be:
            > * It is built on a closure which some people are scared of. That
            > just means you need to define all of your methods inside
            > the scope including %Data.
            > * There needs to be a destructor in the package. When the scalar
            > object goes out of scope, we need to clean out the private
            > %Data hash. The internal %data hash created in the constructor
            > would otherwise always hang around because the %Data hash has
            > a reference to it.
            >
            >
            > Blame me for the faults in the presentation or details.
            > The good idea came to me from Damian Conway's excellent OOPerl
            > book.
            >
            > Doug
            >
            >
            >
            > my Package;
            > { my %Data;
            >
            > sub new {
            > my $class = shift;
            > my %data = @_; # assuming an array for simplicity
            > my $addr = ref \%data;
            > $Data{$addr} = \%data;
            > return bless \$addr, ref $class || $class;
            > }
            >
            > sub method {
            > my ($self, @args) = @_;
            > $self = $Data{$$self};
            > # do something with the data, working with $self just as usual
            > }
            >
            > sub DESTROY {
            > delete $Data{${$_[0]}};
            > }
            >
            > }
            >
            > 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!?
            Yahoo! Auctions - buy the things you want at great prices
            http://auctions.yahoo.com/
          • Douglas Bonar
            ... Oops. I didn t know that. So, instead of a scalar ref you ld need to actually bless and pass back a hash ref with just one key/value pair { PackageId
            Message 5 of 6 , May 21, 2001
            • 0 Attachment
              Paul Kulchenko wrote:
              >
              > Hi, Douglas!
              >
              > While idea is right and valid, it may not work as planned for SOAP
              > implementation. Here is why. First, I don't have a proper way to
              > serialize reference to scalar (I'm using subelements right now), so
              > it'll be deserialized as hash. I'm working on finding the right way,
              > but it seems like other languages don't have direct analogies and
              > other XML serializers in Perl don't do SCALAR refs.

              Oops. I didn't know that. So, instead of a scalar
              ref you'ld need to actually bless and pass back a hash ref
              with just one key/value pair { 'PackageId' => $addr }. Then the
              method calls would have to be changed slightly as well. That's
              not as efficient, but not much of a change. Certainly passing
              back the one key/value pair is much better than passing back
              a very large hash/object.


              > Second problem is
              > that object will be destroyed on server side right after
              > serialization, so when it'll come back from client side proper
              > element from %Data won't be there anymore. That's why you need to
              > manage it based on different approach. The same problem as with any
              > other session management for stateless protocol. I would like to
              > build o-b-r based on Apache::Session, so you'll be able to get access
              > and manage sessions based on way you like (thru the different
              > interfaces).
              >

              I guess I was looking at that as a separate problem. Working
              with the handle (scalar or slim hash) rather than the full body (actual
              data hash) is a way to avoid passing large amounts of data in each
              message. Yes, it requires you to think of object lifetimes and session
              management. As you say, if you don't hold onto a local (server-side)
              reference to the object you're passing back you'll loose it right after
              sending it off. The simplest fix is not using the DESTROY method
              (so it isn't cleaned automatically) and putting a release method into
              your interface.

              I like the 2 layered idea in standard Perl modules, but
              I'm not sure about it for SOAP. If I pass you back an object that
              is really just a key to identify an object living on the server,
              all your interactions with that object are over the wire. As long
              as the interface is suitably large grained, that's not so bad.
              But certainly you wouldn't want to be acting with an object like
              we're often accustomed to (accessor/mutator methods, lots of method
              calls). And, if the interface really is large grained, maybe
              you shouldn't think of it as an object you keep the identity
              of, but more like a singleton that you tell to do things occasionally.

              At the same time, by having the client process hold onto
              the identify of an object on the server, you're building in the
              a fair amount of complexity. The server (probably) has to try to
              keep track of whether you're still around. There probably has
              to be logic to account for remaking the object if the server thought
              you went away, but it was wrong, or if the original server goes down
              and the client wants to talk to a backup.

              Just my thoughts. Though I really like the transparency
              that SOAP::Lite gives, I'm wary of trying to build on that to
              change from function calls to distributed objects.

              Doug

              > Best wishes, Paul.
              >
              > --- Douglas Bonar <Doug.Bonar@...> wrote:
              > > Paul Kulchenko wrote:
              > > >
              > > > Hi, Nicolas!
              > > >
              > > > Store it as a class data on server side:
              > > >
              > > > package My;
              > > >
              > > > my %huge_hash = (
              > > > a => 1,
              > > > );
              > > >
              > > > sub new {
              > > > my $proto = shift;
              > > > my $class = ref($proto) || $proto;
              > > > bless {} => $class;
              > > > }
              > > >
              > > > sub access_hash {
              > > > #... do something with %huge_hash
              > > > }
              > > >
              > > > And do NOT include reference to this hash in object (blessed
              > > ref).
              > > > This example will work if you have the same hash for all objects.
              > > >
              > > > If you hash is different for different objects, but you don't
              > > want to
              > > > transfer them anyway, then take a look into object-by-reference.
              > >
              > > In some sense the case of a different hash for each object
              > > isn't that much different from the one big hash. It is a nice
              > > model to use for OO Perl tasks. You might call this a
              > > 'handle/body'
              > > or 'double reference' technique.
              > >
              > > The following is the (rough) idea typed in from memory.
              > > The object you are passing back to the user is just a reference
              > > to a scalar. The value of that scalar is the pointer to the
              > > actual data location (it only matters that it is a unique string
              > > value associated with the real data hash), and at the same time
              > > the key for the internal (private) %Data hash. Then rather than
              > > the standard '1st argument is a hash reference' template in your
              > > methods, you add the extra line that the '1st argument is the key
              > > to retrieve the hash reference'.
              > >
              > > The 2 subtleties seem to be:
              > > * It is built on a closure which some people are scared of. That
              > > just means you need to define all of your methods inside
              > > the scope including %Data.
              > > * There needs to be a destructor in the package. When the scalar
              > > object goes out of scope, we need to clean out the private
              > > %Data hash. The internal %data hash created in the constructor
              > > would otherwise always hang around because the %Data hash has
              > > a reference to it.
              > >
              > >
              > > Blame me for the faults in the presentation or details.
              > > The good idea came to me from Damian Conway's excellent OOPerl
              > > book.
              > >
              > > Doug
              > >
              > >
              > >
              > > my Package;
              > > { my %Data;
              > >
              > > sub new {
              > > my $class = shift;
              > > my %data = @_; # assuming an array for simplicity
              > > my $addr = ref \%data;
              > > $Data{$addr} = \%data;
              > > return bless \$addr, ref $class || $class;
              > > }
              > >
              > > sub method {
              > > my ($self, @args) = @_;
              > > $self = $Data{$$self};
              > > # do something with the data, working with $self just as usual
              > > }
              > >
              > > sub DESTROY {
              > > delete $Data{${$_[0]}};
              > > }
              > >
              > > }
              > >
              > > 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!?
              > Yahoo! Auctions - buy the things you want at great prices
              > http://auctions.yahoo.com/
              >
              > 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/
            • kesslernicolas@yahoo.com
              Douglas, Paul: Many thanks for sharing your thoughts on this problem; I am relieved there was no obvious solution :-) Paul: I do have several instances of the
              Message 6 of 6 , May 22, 2001
              • 0 Attachment
                Douglas, Paul:

                Many thanks for sharing your thoughts on this problem;
                I am relieved there was no obvious solution :-)

                Paul: I do have several instances of the object in
                question, but I could prepare them all on the server
                in advance and they would just wait there (in
                a mod_perl environment) to be queried.

                I will try to understand and apply Douglas' suggestion
                (and work through Damian's book, once again).

                Regards,
                Nicolas
              Your message has been successfully submitted and would be delivered to recipients shortly.