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

The troublesome unless (defined %{"${class}::"})

Expand Messages
  • jhebertocx
    I see in the archive one other poster has found this method of checking to see if a class has already been loaded to be troublesome, and now so have I.
    Message 1 of 3 , Oct 13, 2003
    • 0 Attachment
      I see in the archive one other poster has found this method of
      checking to see if a class has already been loaded to be troublesome,
      and now so have I.

      Everything has been working great, we use SOAP::LIte 0.55 on perl
      5.6.0 under MacOS X 10.2.x and ActiveState's 5.6.1 build.

      Now, trying to use perl 5.8.1 under MacOS X, this doesn't work in one
      specific case, because the check for:

      (defined %{"${class}::"})

      in sub find_target is suddenly true when it should be false. I still
      haven't gotten to the bottom of why, but if I hack some logging into
      SOAP::Lite itself, here's what I come with. First of all, the module
      really, really isn't loaded. I'm sure. But, somehow, someone or
      something is putting the following two entries in the symbol table
      (output from Dumper \ %{"${class}::"} ) :

      'AUTOLOAD' => *Foo::Bar::AUTOLOAD,
      'DESTROY' => *Foo::Bar::DESTROY

      (Foo::Bar:: used in place of my actual class name)

      Anyways, this crud tricks SOAP::Lite into thinking the module has
      already been loaded. Then, it doesn't 'require' the module for me,
      and more importantly, doesn't add that class name to
      $self->dispatched(). As a result, later on in the function it throws
      a 'die' because the class I'm trying to access isn't listen in the
      (empty) dispatched() list.

      My questions are:

      1) Does anyone know what might be causing these rogue things to end up
      in the symbol table?

      2) Would it be agreeable if SOAP::Lite required Devel::Symdump ? I
      experimented with inspecting the symbol table with this module, and it
      does NOT show Foo::Bar in the list of loaded modules, nor does it even
      show Foo::Bar::AUTOLOAD or Foo::Bar::DESTROY in the list of defined
      functions, so it seems that this library more-properly implements what
      SOAP::Lite is trying to accomplish with this direct inspection of the
      symbol table.

      If nothing else, it might be worth it to have this be one of the many
      cases where SOAP::Lite will use a library if it's installed, but falls
      back to an internally-implemented method otherwise. Clearly the
      current check works for most people, so maybe a new external
      dependency would be resented, but if it was optional would people
      mind?

      I'd be happy to write the code and submit the patch for such a thing
      if the maintainers tell me they're not totally opposed to the idea.
      (Obviously, the code itself would also have to pass muster, I'm not
      seeking acceptance of codesight-unseen, just any leanings on the
      idea.)

      3) Does anyone have any suggested workaround for this?

      Note that this only happens in the specific case where I'm trying to
      actually do work on instances, rather than just class-static methods.
      I can call 'new' OK, but when I turn around and try to call some
      method on the class later it fails.

      The simplest case to reproduce I can give you is, if I take the
      Temperatures example from soaplite.com, and slightly change it:

      # the cgi:

      #!/usr/bin/perl -w
      use SOAP::Transport::HTTP;
      SOAP::Transport::HTTP::CGI
      -> dispatch_to('/some/directory')
      -> handle;

      # /some/directory/Temperatures.pm contains the class from the example:

      #!/usr/bin/perl -w
      package Temperatures;

      [all the guts of that package]

      1;

      And the client is the autodispatch-based client:

      use SOAP::Lite +autodispatch =>
      uri => 'http://svr/Temperatures',
      proxy => 'http://svr/cgi-bin/temp.cgi';

      my $temperatures = Temperatures->new(100);
      print $temperatures->as_fahrenheit;

      If I run this in the debugger, I can see that the $som returned
      contains:

      Denied access to method (as_fahrenheit) in class (Temperatures) at
      /Library/Perl/5.8.1/SOAP/Lite.pm line 2267.

      At this point, I'm not really prepared to change the cgi to naming the
      classes I'm exporting, we really strapped ourselves in to rely on
      being able to just point to a directory and have all the things in
      that directory exported (just about everything except the CGI itself
      is changable at this point, but the CGI is part of a standard system
      footprint that has been replicated onto a lot of machines by now).

      Sorry for the long post. Thanks for any input anyone has.

      --jim

      Jim Hebert
    • Duncan Cameron
      ... up ... it ... even ... what ... falls ... the ... Jim This appears to be a problem with using the CGI interface. The same client and server work when using
      Message 2 of 3 , Oct 14, 2003
      • 0 Attachment
        > I see in the archive one other poster has found this method of
        > checking to see if a class has already been loaded to be troublesome,
        > and now so have I.
        >
        > Everything has been working great, we use SOAP::LIte 0.55 on perl
        > 5.6.0 under MacOS X 10.2.x and ActiveState's 5.6.1 build.
        >
        > Now, trying to use perl 5.8.1 under MacOS X, this doesn't work in one
        > specific case, because the check for:
        >
        > (defined %{"${class}::"})
        >
        > in sub find_target is suddenly true when it should be false. I still
        > haven't gotten to the bottom of why, but if I hack some logging into
        > SOAP::Lite itself, here's what I come with. First of all, the module
        > really, really isn't loaded. I'm sure. But, somehow, someone or
        > something is putting the following two entries in the symbol table
        > (output from Dumper \ %{"${class}::"} ) :
        >
        > 'AUTOLOAD' => *Foo::Bar::AUTOLOAD,
        > 'DESTROY' => *Foo::Bar::DESTROY
        >
        > (Foo::Bar:: used in place of my actual class name)
        >
        > Anyways, this crud tricks SOAP::Lite into thinking the module has
        > already been loaded. Then, it doesn't 'require' the module for me,
        > and more importantly, doesn't add that class name to
        > $self->dispatched(). As a result, later on in the function it throws
        > a 'die' because the class I'm trying to access isn't listen in the
        > (empty) dispatched() list.
        >
        > My questions are:
        >
        > 1) Does anyone know what might be causing these rogue things to end
        up
        > in the symbol table?
        >
        > 2) Would it be agreeable if SOAP::Lite required Devel::Symdump ? I
        > experimented with inspecting the symbol table with this module, and
        it
        > does NOT show Foo::Bar in the list of loaded modules, nor does it
        even
        > show Foo::Bar::AUTOLOAD or Foo::Bar::DESTROY in the list of defined
        > functions, so it seems that this library more-properly implements
        what
        > SOAP::Lite is trying to accomplish with this direct inspection of the
        > symbol table.
        >
        > If nothing else, it might be worth it to have this be one of the many
        > cases where SOAP::Lite will use a library if it's installed, but
        falls
        > back to an internally-implemented method otherwise. Clearly the
        > current check works for most people, so maybe a new external
        > dependency would be resented, but if it was optional would people
        > mind?
        >
        > I'd be happy to write the code and submit the patch for such a thing
        > if the maintainers tell me they're not totally opposed to the idea.
        > (Obviously, the code itself would also have to pass muster, I'm not
        > seeking acceptance of codesight-unseen, just any leanings on the
        > idea.)
        >
        > 3) Does anyone have any suggested workaround for this?
        >
        > Note that this only happens in the specific case where I'm trying to
        > actually do work on instances, rather than just class-static methods.
        > I can call 'new' OK, but when I turn around and try to call some
        > method on the class later it fails.
        >
        > The simplest case to reproduce I can give you is, if I take the
        > Temperatures example from soaplite.com, and slightly change it:
        >
        > # the cgi:
        >
        > #!/usr/bin/perl -w
        > use SOAP::Transport::HTTP;
        > SOAP::Transport::HTTP::CGI
        > -> dispatch_to('/some/directory')
        > -> handle;
        >
        > # /some/directory/Temperatures.pm contains the class from the
        example:
        >
        > #!/usr/bin/perl -w
        > package Temperatures;
        >
        > [all the guts of that package]
        >
        > 1;
        >
        > And the client is the autodispatch-based client:
        >
        > use SOAP::Lite +autodispatch =>
        > uri => 'http://svr/Temperatures',
        > proxy => 'http://svr/cgi-bin/temp.cgi';
        >
        > my $temperatures = Temperatures->new(100);
        > print $temperatures->as_fahrenheit;
        >
        > If I run this in the debugger, I can see that the $som returned
        > contains:
        >
        > Denied access to method (as_fahrenheit) in class (Temperatures) at
        > /Library/Perl/5.8.1/SOAP/Lite.pm line 2267.
        >
        > At this point, I'm not really prepared to change the cgi to naming
        the
        > classes I'm exporting, we really strapped ourselves in to rely on
        > being able to just point to a directory and have all the things in
        > that directory exported (just about everything except the CGI itself
        > is changable at this point, but the CGI is part of a standard system
        > footprint that has been replicated onto a lot of machines by now).
        >
        > Sorry for the long post. Thanks for any input anyone has.
        >
        Jim

        This appears to be a problem with using the CGI interface. The same
        client and server work when using a soap daemon.
        I think that the cause of the problem is in the deserialisation of the
        SOAP message when it is deserialised into a Temperature object and
        blessed into the Temperature class. This simple example shows that the
        symbol table entry is created as you described:

        use strict;
        use Data::Dumper;
        my $class = 'Some';
        bless {a => 1}, $class;

        no strict 'refs';
        print Dumper \ %{"Some::"}; #exists
        print Dumper \ %{"Else::"}; # does not exist

        You can work around the problem by patching the line to test %INC
        (which shows the modules that have been loaded) :

        unless (exists $INC{"${class}::"}) {

        I don't know enough about what is going on to know why this could not
        be a permanent change.


        Duncan


        ________________________________________________________________________
        Want to chat instantly with your online friends? Get the FREE Yahoo!
        Messenger http://mail.messenger.yahoo.co.uk
      • Jim Hebert
        ... Ah, yes. I actually stopped and figured that out, at one point, too, but then I thought that was so crazy that I must have done something wrong and didn t
        Message 3 of 3 , Oct 14, 2003
        • 0 Attachment
          On Tue, 14 Oct 2003, Duncan Cameron wrote:

          > This appears to be a problem with using the CGI interface. The same
          > client and server work when using a soap daemon.

          Ah, yes. I actually stopped and figured that out, at one point, too, but
          then I thought that was so crazy that I must have done something wrong
          and didn't mention it. I was too antsy to go back and re-confirm. :-)

          > blessed into the Temperature class. This simple example shows that the
          > symbol table entry is created as you described:

          Wow, good find.

          So, I went back over your previous thread about this, I understand now why
          certain people might not want to rely on %INC or things like that to
          check if a class is loaded. Without going as gonzo as Devel::Symdump, I
          think a possible compromise might be:

          right now it tries to look, and only do the require if it thinks it has to.

          What if, instead, it did the require, then looked? Either it worked
          (great), it was a no-op because it was already loaded (fine), or it fails.

          Like:
          { # braces to retain the ability to safely mess with local @INC:

          # allow all for static and only specified path for dynamic bindings
          local @INC = (($static ? @INC : ()), grep {!ref && m![/\\.]!} $self->dispatch_to);
          eval 'local $^W; ' . "require $class";
          die "Failed to access class ($class): $@" unless (defined %{"${class}::"});
          $self->dispatched($class) unless $static;
          }

          (Untested.)

          Something like the above could be a small enough change that hopefully
          it'd be agreeable to merge into the .60 beta?

          Obviously I can patch my local copy but I'd prefer it if I could avoid
          maintaining an in-house fork... :-)

          (I'm new to the list - who with commit priviledges do I have to convince?
          :-)

          Thanks for the help Duncan, and thanks to everyone who produced such a
          great SOAP library.

          jim
        Your message has been successfully submitted and would be delivered to recipients shortly.