talexb has asked for the wisdom of the Perl Monks concerning the following question:

I am attempting to use CGI::Application for the development of a base web application that I'll be able to use for several clients. Right now I'm at the prototype stage. Having started with code based on the docs, I am having a problem with the startup code that requests a DBI connection handle:
use base 'CGI::Application'; use strict; sub setup { my $Self = shift; ... $Self->param ( 'mydbh' => DBI->connect ( ... ) ); }
This results in a
Issuing rollback() for database handle being DESTROY'd without explici +t disconnect()
error in the web log. I can see why it's complaining -- I've allocated a database handle that appears to be going out of scope with the appropriate disconnect. Of course, it only appears to be going out of scope .. I'm saving the handle in the Web Application object and will use it properly (including disconnecting at the appropriate time).

How can I soothe Perl and/or correct my mistake? Help would be appreciated.

--t. alex

"Excellent. Release the hounds." -- Monty Burns.

Replies are listed 'Best First'.
Re: DBI handle destroyed during CGI::Application setup
by rob_au (Abbot) on Jan 07, 2002 at 04:26 UTC
    From as far as I can see, this is expected behaviour - With CGI::Application, in addition to the setup method for the establishment of parameters such as database handles, there is also the teardown method, which is implemented automatically after the application is run and can be used for the clean up of handles and objects that require an explicit closure before script termination.

    The error you are experiencing is a result of the DBI handle not being explicitedly disconnected prior to termination of CGI::Application execution - This error is not due to the closure of scope within the setup method. To correct this behaviour, you should make use of the teardown method within your CGI::Application class:

    sub teardown { my $self = shift; $self->param('mydbh')->disconnect; }

    This should correct your problem. This method and a couple of other 'gotchas' for CGI::Application is described in my review of this module here.

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      I have implemented a teardown routine; but not calling it is not the cause of my error.

      And I still don't understand how your sub setup executes without error -- you are creating a DBI handle within your call to $self->param just as I was -- and I got a DBI error out of that.

      I also note that you have also made the change from

      $self->run_modes( 'mode1' => 'showform', 'mode2' => 'showlist' );
      to
      $self->run_modes( 'mode1' => \&showform, 'mode2' => \&showlist );
      Is the original documentation inaccurate? After some skull sweat I figured out the answer myself, and I'm glad to see that you have it correctly on your page. I will peruse your node with a magnifying glass to see how many other 'gotcha's there are -- thanks for your contribution.

      --t. alex

      "Excellent. Release the hounds." -- Monty Burns.

        I'll post some sample code that makes uses a DBI handle within a param object for illustration - It might be worthwhile your putting a more complete segment of your code up on your scratchpad for me to have a look through because the implementation of the disconnect method on the DBI handle within the teardown method should correct your errors.

        Some sample CGI::Application code using DBI handles follows - Note that my usage of the param function differs slightly as I prefer to define my parameters through the instance object of my CGI::Application class.

(jeffa) Re: DBI handle destroyed during CGI::Application setup
by jeffa (Bishop) on Jan 07, 2002 at 03:43 UTC

    <warning msg="hack alert">

    Don't do this - follow rob_au's advice at Re: DBI handle destroyed during CGI::Application setup instead.

    I should be flogged for giving advice like this. I'd vote to reap it, but that fact that it works blanketed by TIMTOWDTI (at least in the current version ....) makes it worth keeping methinks. But it is buggy at best, because the setup method will get called twice, once with an undefined argument (when new() is called). bad jeffa!

    </warning>

    How about:
    my $DBH = DBI->connect( ...); # call setup method ... foo->setup($DBH); $DBH->disconnect(); # and for the setup method: sub setup { my ($self,$DBH) = #_; ... $self->param ( 'mydbh' => $DBH ); }
    The DBI object IS going out of scope in your code, and because you are not keeping a reference to it yourself, the bad thing happens. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
      While this certainly works, the problem which talexb is experiencing is not related to scope of the DBI handle within the setup method of the CGI::Application class, but rather failure to explicitly disconnect the handle prior to application termination.

      The incorporation of the DBI external to the CGI::Application class, while increasing the variable's scope and solving the immediate problem, to a certain extent invalidates the usefulness of the param methods and the specific scope that they offer.

      Just my random thoughts on the subject.

       

      perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      Awesome. And, now I think about it, a straightforward solution. I was just way too frazzled to see it. Yeah, I like it.

      A million thanks. Thank you. Thank you. Thank you.

      --t. alex

      "Excellent. Release the hounds." -- Monty Burns.

      <Update (19:54 local time)> I tried it a little differently than what you suggested. Check out my Scratch Pad for more information. </Update>