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

4059Re: [soaplite] Persistent Database Handles ...

Expand Messages
  • Byrne Reese
    Oct 20, 2004
      Some feedback on the code you posted.

      You may consider adding:
      DESTORY { my $self = shift; $$self{ dbh }->disconnect; }
      You may also want to clean up the statement handle at the end of getbywhere:
      $$self{ _sth }->finish;
      I also find that dealing with compound references (e.g. $$anything) can lead to confusion, which can lead to mistakes down the road. Therefore I always like to use the following new() template:
      sub new {
          my($class)  = shift;
          my(%params) = @_;
          bless {
              "_dbh"    => DBI->connect('CONNSTR','USER','PW') || die $1;,
              "_param1" => [ ],
              "_param2" => undef,
              "_param3" => 0,
          }, $class;
      }
      Then I add accessors for each - Paul Kulchenko showed me this great trick for collapsing all your getters/setters into one small piece of code:
      sub BEGIN {
        no strict 'refs';
        for my $method ( qw(dbh param1 param2 param3) ) {
          my $field = '_' . $method;
          *$method = sub {
            my $self = shift;
            @_ ? $self->{$field} = shift, return $self : return $self->{$field};
          }
        }
      }
      These few changes would allow your code to change into something like this:
      use DBI;
      package Table;
      sub new {
        # Code from above
      }
      sub getbywhere {
          my $self = shift;
          my $where = shift;
          my $sth = $self->dbh->prepare("SELECT id FROM table WHERE $where");
          $sth->execute();
          my @rows = $sth->rows;
          $sth->finish;
          return @rows;
      }
      Ok - that helps to make code a little easier to work with, and it helps to make references easier to grok, but does it solve your problem? Probably not.

      I am dubious if obects_by_reference will work with anything other than another Perl client - so that is something to consider when using this feature - not to mention that it is marked EXPERIMENTAL.

      Also, the proper syntax for objects_by_reference would be:
      my $daemon = SOAP::Transport::HTTP::Daemon
        -> new (LocalPort => 81)
        -> objects_by_reference(qw(Table))
        -> dispatch_to('/lib', 'Table')
        -> options({compress_threshold => 10000});
      As I don't think you need to specify the specific subroutines - just the package name.

      Perhaps Paul can weigh in - I am less familiar with how this all works right now - this capability was added by him quite some time ago.

      Byrne

      tjewell99 wrote:
      Dear all,

      I'm sure this must be fast approaching a FAQ, but I've read all the
      archives and I'm unsure what to do.

      Basically, I'd like to use a persistent database handle. I'm aware of
      the possible problems with Apache child processes, so I thought I'd
      use the simple soap.demon supplied with Soap::Lite 0.60

      I have three elements -

      Table.pm
      --------

      use DBI;

      package Table;

      sub new {
          my $class = shift;
          my $self = {};

          my $dbh = DBI->connect
      ('DBI:mysql:database=mesh:host=localhost','root','') || die $1;

          $$self{ dbh } = $dbh;

          bless $self, ref( $class ) || $class;
          $self;
      }

      sub getbywhere {
          my $self = shift;
          my $where = shift;

          $$self{ _sth } = $$self{ dbh }->prepare("SELECT id FROM table
      WHERE $where");
          $$self{ _sth }->execute();
          $$self{ _sth }->rows;
      }

      soap.demon.pl
      -------------

      my $daemon = SOAP::Transport::HTTP::Daemon
        -> new (LocalPort => 81)
        -> objects_by_reference(qw(Table::new Table::getbywhere))
        -> dispatch_to('/lib', 'Table')
        -> options({compress_threshold => 10000})
      ;
      print "Contact to SOAP server at ", $daemon->url, "\n";
      $daemon->handle;

      soapclient.pl
      -------------

      #!/usr/bin/perl -w -I/lib

      use strict;
      use SOAP::Lite dispatch_from => 'Table' =>
              uri => 'http://localhost:81/Table',
              proxy => 'http://localhost:81/';

      my $node=Table->new() || die $1;
      my $id = $node->getbywhere(" <where clause> ");

      print "Node: $id, $node\n";

      ------

      Now, you can probably guess what happens. Between the 'new' and
      the 'getbywhere' it seems to forget the value of 'dbh'.

      When I first run the script, the server says:

      --
        SV = RV(0x85079cc) at 0x866f5d0
        REFCNT = 1
        FLAGS = (ROK)
        RV = 0x866f498
      --

      For reasons I can't fathom, the second time it says:

      --
      SV = RV(0x8507888) at 0xbfffd8e0
        REFCNT = 1
        FLAGS = (ROK,READONLY)
        RV = 0x866f498
              (in cleanup) dbih_getcom handle DBI::db=HASH(0x866f498) is
      not a DBI handle (has no magic)
      at /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-
      multi/XML/Parser/Expat.pm line 474.
      l5/vendor_perl/5.8.0/i386-linux-thread-multi/XML/Parser/Expat.pm line
      474.
      SV = RV(0x8593048) at 0x865d13c
        REFCNT = 1
        FLAGS = (ROK)
        RV = 0x85727f0
      --

      I know this is a long post, but I'd be extremely grateful if someone
      could give me some pointers as to how to get this working.

      Many thanks in advance,

      Tony.


    • Show all 3 messages in this topic