catalyst require lib across whole application - perl

So I have a .lib file with some of my own subroutines in it that I would like to make available to the entire Catalyst app. Right now I require the file in lib/myapp.pm and I have no issues. However, whenever I try to call that subroutine in a controller, I get this error:
"Undefined subroutine &myapp::Controller::Root::my_sub called at
/home/user/myapp/lib/myapp/Controller/Root.pm line 35, <DATA> line 1003."
If I require the file I want to require in the controller, that gives me no issues. However, I would prefer to have to only load it in one place for the whole application if this was possible. Also, if I require the file within the controller, does that mean that this file is being loaded every time a request is made? (I'm using mod_perl if that makes any difference). I'd like to make this as efficient in terms of the file being loaded once for the whole app and any requests, but also loaded only in one place just for the sake of clean code. Thanks!

use myapp;
is basically
BEGIN {
require myapp;
import myapp;
}
require myapp; executes myapp.pm if it hasn't already been executed. In other words, no matter how many times you do use myapp; in a process, the file will only be executed ("loaded") once.
import myapp; calls myapp::import() if it exists in order to export stuff. Assuming myapp exports my_sub, this is why your code isn't working.
You have two options.
Call the mysub in the myapp package: myapp::my_sub(...).
Use use myapp; to create a local name for my_sub in every package you call my_sub so you can call it using just my_sub(...). (This assusmes myapp exports my_sub.)

The command use myapp; will only load your myapp.pm file once, even when called multiple times. But each time it will call the import routine makes my_sub() available (Assuming you export it using Exporter or something else) without having to write myapp::my_sub().

Related

Perl module function call runs in spite of missing use statement

I'm developing in a library consisting of multiple Perl modules.
The following statement compiles and runs perfectly:
my $x = Foo::Bar::new();
But the necessary use statement is missing from the beginning of the module:
use Foo::Bar;
How is this possible? Is use propagating from used or using modules?
Some background first.
use Foo::Bar;
is short for
BEGIN {
require Foo::Bar;
import Foo::Bar;
}
import Foo::Bar; calls the import method of the module if one exists. This happens every time use is used. With no arguments, most modules' import export a default list of symbols or none at all.
If you don't need to import anything (as is the case in your program), you can forgo the import by using
use Foo::Bar ();
It's a special case equivalent to
BEGIN {
require Foo::Bar;
}
require Foo::Bar; is what loads the module. The modules is only loaded (executed) once per interpreter no matter how many times you do require Foo::Bar; (or use Foo::Bar;).
In your case, you probably loaded a module that loaded Foo::Bar. That allows you to omit use Foo::Bar (); since it wouldn't have done anything anyway.
You don't show any significant code, but one of the modules that you do use probably loads Foo::Bar, making it available to code in every package.
It doesn't matter where the use (or require) appears, as long as it is done before the code that depends on it is executed

Refactoring Perl code on a live Web site. Are mutual module dependencies OK?

We have a big Perl based Web site.
I am assigned to refactor code of many scripts and packages. Sometimes changes are easy and I just modify existing functions. But sometimes I need to rewrite entire functions. The bad news that the functions which I rewrite call other functions. So if I move refactored code in my new module I need also copy all supplementary functions. But if I do not move refactored code to my special module, a tiny syntax error may crash the entire site :-(
Yes, I know we should use version control, etc. But we don't and this is a fact which I can't change. What to do?
So I need to keep some code in a Test module (to avoid syntax errors to crash the entire site). Would it be OK to make circular references from other modules to Test (for my new refactored routines) and from Test to other modules (for supplemetary routines)?
Note that we have some AutoRequire module which is required by most of our scripts and modules. AutoRequire makes A::X() call to automatically load A module (if it is not yet loaded).
My main question is whether it is OK in this settings to use mutual module dependencies. Any other suggestions?
Require works by first checking if the module is already loaded and if not load it and afterwards mark it as loaded. So if you have a dependency that Foo requires Bar and Bar requires Foo it will first try to load Foo, within Foo try to load Bar. But because Bar requires Foo and Bar was not yet finally loaded this can give problems.
Edit after input from #ysth: it will not fail but it might load some thing only partially, which might cause interesting problems later.
So it might just work, but it also might give problems later (like failing to use exported functions or so).
Perl allows mutual dependencies, but they can sometimes lead to unintuitive behaviour. An example I've given before is:
foo.pm
package foo;
use bar;
sub import { printf("%s loaded foo\n", scalar caller) }
1;
bar.pm
package bar;
use foo;
sub import { printf("%s loaded bar\n", scalar caller) }
1;
script.pl
#!/usr/bin/env perl
package main;
use foo;
Output:
foo loaded bar
main loaded foo
Didn't you expect to see bar loaded foo somewhere in that output?
With careful consideration of compile time versus runtime, etc, etc, you'll realise why that line was not output, and that this is proper and documented behaviour. Just not necessarily very intuitive.
That said, for purely object-oriented modules which don't do anything on import (e.g. export anything to their caller, or act as a pragma, or—as in this example—print output), it should generally be pretty safe.
That said, for purely object-oriented modules there's usually no reason to load them upfront with use anyway—instead you can load them with require or Module::Runtime when they are needed.

Why I cannot call a module's function after required or used successfully?

I have a Perl module file named genbank.pm, it has a subroutine new; this Perl module didn't use Exporter and didn't define #EXPORT or #EXPORT_OK. In the same directory I have a Perl file named test.pl, the code of test.pl is:
require 'genbank.pm';
use strict;
our $result = genbank::new();
When I run it with Komodo , it reports:
Undefined subroutine &genbank::new called at /home/mrs/scripts/test.pl line 3;
After I changed the code from
our $result = genbank::new();
to
our $result = genbank->new();
it said:
Can't locate object method "new" via package "genbank"(perhaps you forgot to load "genbank"?) at /home/mrs/scripts/test.pl line 3.
You haven't provided enough information to be entirely certain of the problem, but the most likely cause is that the new sub is in a package other than genbank.
When you attempt to call genbank::new (or genbank->new), Perl looks for a sub named new in the package genbank, not in the file genbank.pm. By convention, the file genbank.pm will contain a package named genbank, but this is purely a matter of convention and convenience. It is not enforced by the language and there is absolutely no automatic connection between file names and package names.
To find out what package your subs are being placed in, look in genbank.pm for any lines saying package xxxx;. The last one to appear before the sub new line will tell you the package that new belongs to. If there isn't a package statement before its definition, it will be in the package main by default.
(If you are responsible for the genbank.pm source code, I would also suggest either adding package genbank; to the file or renaming the file to match the package it actually contains, so as to avoid this sort of confusion in the future.)
Edit in response to OP's comment:
Since the module currently starts with package MRS::Scripts::genbank, then that's the package the new sub is created in. You have two options for calling it:
Call it as MRS::Scripts::genbank::new (or, if it actually is an object constructor, MRS::Scripts::genbank->new). If you want to call it using a package name, then you have to use the correct package name.
Export it from the MRS::Scripts::genbank package and modify your calling script to import symbols from that package (either by moving genbank.pm to MRS/Scripts/genbank.pm and changing your require to use MRS::Scripts::genbank; or by adding MRS::Scripts::genbank->import; after the require), then call it as just new(). While this would work within the limited scope of your question, I advise strongly against it because, as soon as you repeat this with another module containing a sub new, it will all fall apart, since there can't be two news at the same time in the same place.
The cleanest way to resolve this would be to move genbank.pm to MRS/Scripts/genbank.pm, change your require to require MRS::Scripts::genbank.pm (or use; if you don't export anything, they're equivalent), and then call the sub as MRS::Scripts::genbank::new or MRS::Scripts::genbank->new. This approach will bring the file name and package name into sync with each other, which will make life easier for whoever has to maintain the code in the future (which will probably be you...).

Using use without package - big mess?

I have been USEing .pm files willy-nilly in my programs without really getting into using packages unless really needed. In essence, I would just have common routines in a .pm and they would become part of main when use'd (the .pm would have no package or Exporter or the like... just a bunch of routines).
However, I came across a situation the other day which I think I know what happened and why, but I was hoping to get some coaching from the experts here on best practices and how to resolve this. In essence, should packages be used always? Should I "do" files when I just want common routines absorbed into main (or the parent module/package)? Is Exporter really the way to handle all of this?
Here's example code of what I came across (I won't post the original code as it's thousands of lines... this is just the essence of the problem).
Pgm1.pl:
use PM1;
use PM2;
print "main\n";
&pm2sub1;
&pm1sub1;
PM1.pm:
package PM1;
require Exporter;
#ISA=qw(Exporter);
#EXPORT=qw(pm1sub1);
use Data::Dump 'dump';
use PM2;
&pm2sub1;
sub pm1sub1 {
print "pm1sub1 from caller ",dump(caller()),"\n";
&pm2sub1;
}
1;
PM2.pm:
use Data::Dump 'dump';
sub pm2sub1 {
print "pm2sub1 from caller ",dump(caller()),"\n";
}
1;
In essence, I'd been use'ing PM2.pm for some time with its &pm2sub1 subroutine. Then I wrote PM1.pm at some point and it needed PM2.pm's routines as well. However, in doing it like this, PM2.pm's modules got absorbed into PM2.pm's package and then Pgm1.pl couldn't do the same since PM2.pm had already been use'd.
This code will produce
Undefined subroutine &main::pm2sub1 called at E:\Scripts\PackageFun\Pgm1.pl line 4.
pm2sub1 from caller ("PM1", "PM1.pm", 7)
main
However, when I swap the use statements like so in Pgm1.pl
use PM2;
use PM1;
print "main\n";
&pm2sub1;
&pm1sub1;
... perl will allow PM2.pm's modules into main, but then not into PM1.pm's package:
Undefined subroutine &PM1::pm2sub1 called at PM1.pm line 7.
Compilation failed in require at E:\Scripts\PackageFun\Pgm1.pl line 2.
BEGIN failed--compilation aborted at E:\Scripts\PackageFun\Pgm1.pl line 2.
So, I think I can fix this by getting religious about packages and Exporter in all my modules. Trouble is, PM2.pm is already used in a great number of other programs, so it would be a ton of regression testing to make sure I didn't break anything.
Ideas?
See my answer to What is the difference between library files and modules?.
Only use require (and thus use) for modules (files with package, usually .pm). For "libraries" (files without package, usually .pl), use do.
Better yet, only use modules!
use will not load same file more than once. It will, however, call target package's import sub every time. You should format your PM2 as proper package, so use can find its import and export function to requestor's namespace from there.
(Or you could sneak your import function into proper package by fully qualifying its name, but don't do that.)
You're just asking for trouble arranging your code like this. Give each module a package name (namespace), then fully qualify calls to its functions, e.g. PM2::sub1() to call sub1 in package PM2. You are already naming the functions with the package name on them (pm2sub1); it is two extra characters (::) to do it the right way and then you don't need to bother with Exporter either.

Importing a require'd file as if it were a use statement

I am experiencing a problem with using a constant defined in a configuration file.
This is my package:
package myPackage;
require "APIconfig.pl";
APIconfig::import(APIconfig);
use constant SERVICE_URL => APIconfig::SERVICE_URL();
The configuration looks like this:
package APIconfig;
use constant SERVICE_URL => 'http://api.example.org/blah';
1;
When running this code, I get the following error:
Undefined subroutine &APIconfig::SERVICE_URL called at API.pl line 4.
I cannot use 'use' instead of 'require' because this expects the configuration file to be named .pm, and it's called .pl on a lot of servers on our network.
How can I use the package without renaming the file?
There are two differences between 'use' and 'require'. One of them affects your current problem, the other doesn't. Unfortunately you are working around one that has no effect.
The differences are:
1/ 'use' calls the import() function, 'require' doesn't.
2/ 'use' happens at compile time, 'require' happens at runtime.
You're working around the fact that 'require' doesn't call import() by calling it explicitly. This has no effect as your module doesn't export any symbols and doesn't have an import() subroutine.
You're not working around the fact that 'use' statements are executed at runtime. The problem is that "use constant SERVICE_URL => APIconfig::SERVICE_URL();" is executed at compile time and your 'require' hasn't run by then so myPackage knows nothing about APIconfig.
The (nasty, hacky) solution is to put the 'require' statement into a BEGIN block - to force it to be executed at compile time. You'll also want to remove the call to import() as that gives a runtime error (due to the absence of the subroutine).
The test files that I used to work this out are as follows:
$ cat APIconfig.pl
package APIconfig;
use constant SERVICE_URL => 'http://api.example.org/blah';
1;
$ cat api.pl
#!/usr/bin/perl
package myPackage;
BEGIN {
require "APIconfig.pl";
}
# APIconfig::import(APIconfig);
use constant SERVICE_URL => APIconfig::SERVICE_URL();
print SERVICE_URL, "\n";
$ ./api.pl
http://api.example.org/blah
The real solution is to rewrite APIconfig as a real module. You hint that you know that, but that environmental issues prevent you taking this approach. I highly recommend trying to work around those issues and doing things correctly.
That can't be possibly right - there is no subroutine import in package APIconfig. Once you're accessing symbolic names with a full package path, you don't need to export/import anyway.
The solution is to run require at compile time, before use constant. This works:
package myPackage;
BEGIN {
require "APIconfig.pl";
}
use constant SERVICE_URL => APIconfig::SERVICE_URL();
If it's a configuration file, don't make it code. I have a whole chapter in Mastering Perl about that, and there are many modules on CPAN to help you with almost any configuration format.
If it's code, why not just make it a module so you can use use. Modules are so much easier to control and manipulate within another program.
The easiest solutions are the ones where you don't swim against the tide. :)
Beyond that, use is the same as:
BEGIN {
require Module;
Module->import;
}
You just do the same thing with filename and the namespace it defines (as long as the code in the file looks like a module):
BEGIN {
require "file.pl"; # defines SomeNamespace
SomeNamespace->import;
}