0
votes

I have inherited an old perl app that I'm trying to resurrect. Sadly I'm not a perl guy (and only a novice developer). I've had some success fixing other problems with this app by finding solutions online, but a solution to this has eluded me so far, so felt it was time to ask for advice.

I have hit a roadblock and looking for advice on how to troubleshoot an error I'm receiving.

This is the error:

Can't locate object method "new" via package "CGI" at 
/opt/app/htdocs/lib/APP/CGI.pm line 26.Compilation failed 
in require at /opt/app/htdocs/lib/APP/CGI.pm line 4.

Here is the first 26 lines of /opt/app/htdocs/lib/APP/CGI.pm:

 package APP::CGI;

 use CGI;

 use CGI::Carp qw(fatalsToBrowser set_message);
 use APP::Error;

 BEGIN {
      sub handle_errors {
         my $msg = shift;
         &APP::Error::error($msg);
     }
     set_message(\&handle_errors);

 }

 use strict;
 # hack:  added these to resolve "can't locate" errors
 use lib qw(/opt/app/htdocs);
 use lib qw(/opt/app/htdocs/lib);
 use lib qw(/opt/app/htdocs/lib/APP);
 use lib qw(/opt/app/htdocs/lib/APP/Service);
 # end hack
 use vars qw/ $CGI %REDIRS /;

 $CGI = new CGI();

I've been having to add the following to other scripts in the app to make things work (to resolve can't locate errors), so I've added them in this script, but it hasn't resolved the issue.

 use lib qw(/opt/app/htdocs);
 use lib qw(/opt/app/htdocs/lib);
 use lib qw(/opt/app/htdocs/lib/APP);
 use lib qw(/opt/app/htdocs/lib/APP/Service);

My guess is that my app cannot find the CGI module (referenced as "use CGI;" in the snippet). I have confirmed the CGI module is installed and up-to-date:

 cpanm -i CGI
 CGI is up to date. (4.40)

Perl Version is 5.26.2, if that matters.

Any tips on how to troubleshoot? I feel like this CGI.pm file cannot find the CGI module, which is why it can't execute the method "new"... but it's just a guess.

2
That's not the reason; if it can't find the module, "use" will throw an error which is not what happened here.Grinnz
Try changing the new CGI(); to CGI->new();. That type of indirect object syntax was added to Perl when it was trying to be like the cool kids, but it can confuse Perl's interpreter so it's no longer recommended. See this perldoc for more info: perldoc.perl.org/perlobj.html#Indirect-Object-Syntaxinterduo

2 Answers

6
votes
package APP::CGI;

[…]

use lib qw(/opt/app/htdocs/lib);
use lib qw(/opt/app/htdocs/lib/APP);
use lib qw(/opt/app/htdocs/lib/APP/Service);

These use lib lines look really wrong. If this pattern was used in other files as well, it will cause use CGI to be resolved to /opt/lib/htdocs/lib/APP/CGI.pm (i.e, the file that you're looking at!), not the standard module that was intended.

Remove all use lib lines from Perl modules (.pm) in your project. This directive should only appear in top-level Perl scripts (.pl, .cgi, etc); even there, there should only be one use lib referring to the lib directory of your project, not to any subdirectories.

2
votes

Your use lib lines are too over-eager. You are adding a bunch of paths to the beginning of @INC, but you need to only add the base directory. use CGI; will search @INC for the first file it finds by adding CGI.pm to the path, this will find /opt/app/htdocs/lib/APP/CGI.pm due to the extra paths you added. Obviously, that's not CGI, and doesn't define the CGI package, so there's no new method for it to find there. Your lib path is likely just /opt/app/htdocs/lib.