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

Re: [soaplite] The troublesome unless (defined %{"${class}::"})

Expand Messages
  • 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 1 of 3 , Oct 14, 2003
      > 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 2 of 3 , Oct 14, 2003
        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.