Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Using CGI::Ajax and CGI::Application::Plugin::DBH

by jrsimmon (Hermit)
on Aug 25, 2009 at 19:00 UTC ( [id://791158]=perlquestion: print w/replies, xml ) Need Help??

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

This isn't verbatim what I'm doing, since posting a webapp in here doesn't really make sense. But I'll try to be true to the problem I'm trying to solve. Please forgive me any typos.

What I would like to do is use CGI::Application::Plugin::DBH to provide access to my database in conjunction with CGI::Ajax. When the page loads normally, the CGI::Application setup sub is called and Plugin::DBH can do its thing. However, when 'BUILD_CHART' is called from the the javascript function 'GET_CHART', it doesn't go through the setup routine. Can I still access the database config set up Plugin::DBH when executing a the 'BUILD_CHART' sub? How?

package MyWebApp; use base 'CGI::Application'; use strict; use CGI; use CGI::Ajax; use CGI::Carp qw(fatalsToBrowser); use CGI::Application::Plugin::DBH qw(dbh_config dbh); use DBI qw(:sql_types); use DBIx::Chart; sub setup{ my $self = shift; $self->start_mode('mode1'); $self->mode_param('rm'); $self->run_modes( 'mode1' => 'runMode1', 'mode2' => 'runMode2' ); $self->dbh_config('dbh1', ['DBI:DB2:DS1', 'usr', 'pwd', {RaiseError +=> 0, PrintError => 0}]); } sub runMode1 { my $q = new CGI; my $pjx = new CGI::Ajax('GET_CHART' => \&BUILD_CHART, 'skip_header' +=> 1); open(SRC, "pageSrc.htm") or die $!; my $src = <SRC>; close(SRC); my $output = $q->start_html; $output .= $src; $output .= $q->end_html; return $pjx->build_html($q, $output); } sub BUILD_CHART { my ($chartSelection, $screenWidth) = @_; my $chartWidth = $screenWidth / 2; #this is where I want to take advantage of CGI::Application::Plugin: +:DBH -- so that I don't have to build this connection every time an a +jax call is made to this subroutine my $dbh = DBIx::Chart->connect('DBI:DB2:DS1', 'usr', 'pwd', {RaiseEr +ror => 0, PrintError => 0}) or die $DBI::errstr; my $qryStatement = "SELECT SOMETHING FROM SOMEWHERE"; my $chartStatement = "RETURNING BARCHART(*), IMAGEMAP WHERE ..."; my $sth = $dbh->prepare("$qryStatement $chartStatement"); unless(eval{$sth->execute();}){ die "Failed to execute!"; } my $tempChartRef = $sth->fetchrow_arrayref or die "Failed to fetch!" +; $sth->finish; my $imageData = $$tempChartRef[0]; my $imageMap = $$tempChartRef[1]; my $imageName = &WRITE_IMAGE_TO_DISK($imageData, 'PNG', 'barchart'); my $html = "<IMG SRC=\"/$imageName\" USEMAP=\"#barMap\">"; $html .= $imageMap; return $html; }

Replies are listed 'Best First'.
Re: Using CGI::Ajax and CGI::Application::Plugin::DBH
by trwww (Priest) on Aug 25, 2009 at 19:25 UTC

    Make BUILD_CHART a CGI::App runmode.

    UPDATE:

    Well I guess its not quite as simple as all that... but probably what I would do would somehow make a bridge between CGI::App and CGI::Ajax, possibly via the CGI::App plugin mechanism.

    To get it going quickly, you could probably instantiate your CGI::App subclass in BUILD_CHART:

    my $dbh = MyWebApp->new->dbh

      The problem is that when called through CGI::Ajax, 'BUILD_CHART' doesn't utilize runmodes. It dynamically builds the XMLHTTP request and, as far as i can tell, is able to bypass the instance script altogether.

      Just getting it working isn't a problem -- I can build up and tear down the connections within 'BUILD_CHART' itself with no problems.

      It occurred to me while talking this over with a coworker that it's likely going to require a port from cgi to mod_perl to achieve the persistent connection in the background -- that is, unless someone has a better suggestion?

        The problem is that when called through CGI::Ajax, 'BUILD_CHART' doesn't utilize runmodes. It dynamically builds the XMLHTTP request and, as far as i can tell, is able to bypass the instance script altogether.

        Sure it does not all work together out of the box. But I've given suggestions as to how to make it work.

        It occurred to me while talking this over with a coworker that it's likely going to require a port from cgi to mod_perl to achieve the persistent connection in the background.

        There is nothing in what you are trying to do that requires this. As I mentioned already, you are going to have to do one of A) modify CGI::App or CGI::Ajax to your liking, B) use the CGI::App plugin system to make a shim for what you need, or C) subclass one or the other or both to get the CGI::App object in to the CGI::Ajax callback.

        Again, at the very least, if you simply call:

        my $dbh = MyApp->new->dbh;

        in the CGI::Ajax callback you should be all set.

Re: Using CGI::Ajax and CGI::Application::Plugin::DBH
by astroboy (Chaplain) on Aug 26, 2009 at 02:28 UTC
    You should make BUILD_CHART a run mode, All access from the web, whether via Ajax or not, should be via a run mode. BTW, I usually put my dbh connection calls in the cgiapp_init method, because I consider it part of the application initialisation. If you have a base class for all of your controller packages, you can put it in there, and it will be accessible to all of the controller runmode methods, including BUILD_CHART
Re: Using CGI::Ajax and CGI::Application::Plugin::DBH
by james2vegas (Chaplain) on Aug 26, 2009 at 03:00 UTC
    You can pass in your rm parameter to your script, thus triggering your cgi-app runmode. An example (without DBH, but should be easy enough to add) here.

    There is also detail on how to use cgi-app with Ajax without a specific Ajax module here.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://791158]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-04-24 04:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found