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

Hello Venerable Monks,

I humbly ask your help on this matter.

I also know that this is kind of a long post but I simply wanted to include all the relevant information to the problem at hand.

I am new to Moose and am writing an admin server using it.

I am using plugins to carry out specific parsing tasks and I intend to call these plugins using a Parser module via my master POE server. I am implementing an abstract base class by virtue a Moose Role and am asking various plugins to implement the methods listed in the base class.

Here is a snippet of the Parser module:

package Admin_server::Parser; use MooseX::FollowPBP; # Simon Cozens Perl Best Practices. use Moose; # Sugar!! use Module::Pluggable::Object; # To enable application plugins. use aliased 'Admin_server::Interface::ParserInterface'; #---------------------------------------------------------- # Define attributes. #---------------------------------------------------------- has 'plugins' => ( is => 'ro', lazy_build => 1, isa => 'HashRef' ); <readmore> #---------------------------------------------------------- # Define methods. #---------------------------------------------------------- sub _build_plugins { #=== FUNCTION ==================================== # NAME: _build_plugins # PURPOSE: To build up the applications hash. # PARAMETERS: None. # RETURNS: Nothing. # DESCRIPTION: Populates the applications hash with the list of # available application parser plugins. # THROWS: no exceptions # COMMENTS: none #=============================================== my ($self) = @_; my $base = __PACKAGE__ . '::Plugin';# Location of parser plugins. my %parser_plugins; # Stores the instantiated plugins. # Scan plugins at $base. my $mpo = Module::Pluggable::Object->new( search_path => [$base] ) +; my @available_plugins = $mpo->plugins(); print 'Found plugins ...', "@available_plugins", "\n"; # Load the available plugins. foreach my $plugin (@available_plugins) { print "Loading plugin $plugin", "\n"; Class::MOP::load_class($plugin); print "finished loading $plugin" . "\n" if ( Class::MOP::is_class_loaded($plugin) ); # Ensure that each class confirms to the plugin API. confess("Plugin $plugin in ${base}" . ' namespace doesn\'t implement ParserInterface.' ) unless ( $plugin->does(ParserInterface) ); # Record and instantiate the valid plugin objects in a hash. ( my $plugin_name = $plugin ) =~ s/\Q${base}::\E//; $parser_plugins{$plugin_name} = $plugin->new(); } print STDOUT sort keys %parser_plugins, "\n"; return \%parser_plugins; } # ---------- end of subroutine _build_applications ---------- </readmore>

The deal is the plugins won't be loaded for some reason and I am at a loss how to debug the issue.

The output of my t/Parser.t is:

$prove -lv t/Parser.t t/Parser.t .. 1..4 ok 1 - use Admin_server::Parser; ok 2 - Admin_server::Parser can be instantiated. ok 3 - Instantiated object is of type Admin_server::Parser Found plugins ...Admin_server::Parser::Plugin::FeedHandler Loading plugin Admin_server::Parser::Plugin::FeedHandler Can't locate object method "does" via package "Admin_server::Parser::P +lugin::FeedHandler" (perhaps you forgot to load "Admin_server::Parser +::Plugin::FeedHandler"?) at /Volumes/UserData/Users/tintin/Programs/P +erl/Work_area/Admin_server/lib/Admin_server/Parser.pm line 68. # Looks like you planned 4 tests but ran 3. # Looks like your test exited with 255 just after 3. Dubious, test returned 255 (wstat 65280, 0xff00) Failed 1/4 subtests Test Summary Report ------------------- t/Parser.t (Wstat: 65280 Tests: 3 Failed: 0) Non-zero exit status: 255 Parse errors: Bad plan. You planned 4 tests but ran 3. Files=1, Tests=3, 1 wallclock secs ( 0.03 usr 0.01 sys + 0.24 cusr + 0.02 csys = 0.30 CPU) Result: FAIL

Looks like Module::Pluggable::Object is able to locate the plugin's but won't load them.(At the moment, I only have 1 plugin i.e. FeedHandler)

P.S: The print statements in the code above are for debugging only.

I am also including my test file for convenience.

############################################################ ########### PRAGMATA ######## ############################################################ use strict; use warnings; use Test::More tests => 4; # last test to print ############################################################ ########### VARIABLES USED ######## ############################################################ ############################################################ ########### TESTING BEGINS ######## ############################################################ #---------------------------------------------------------- # Ensure that Admin_server::Parser can be use'd. #---------------------------------------------------------- BEGIN { use_ok('Admin_server::Parser'); } #---------------------------------------------------------- # Check if the plugin can be instantiated. #---------------------------------------------------------- ok( my $parser = Admin_server::Parser->new(), 'Admin_server::Parser can be instantiated.' ); #---------------------------------------------------------- # Conform that the new object is of the correct type. #---------------------------------------------------------- is( ref($parser), 'Admin_server::Parser', 'Instantiated object is of type Admin_server::Parser' ); #---------------------------------------------------------- # Check whether plugins are correctly loaded. #---------------------------------------------------------- ok( $parser->get_plugins(), 'Plugin hash can be accessed.' ); #ok( exists ${ $parser->get_plugins() }->{'FeedHandler'}, # 'Feed handler plugin found.' ); done_testing();

The directory structure is:

$ls -1R bin config lib logs t ./bin: Master_server.pl Master_server.pl.bkp ./config: admin_server.conf ./lib: Admin_server ./lib/Admin_server: Interface Parser Parser.pm ./lib/Admin_server/Interface: ParserInterface.pm ./lib/Admin_server/Parser: Plugin ./lib/Admin_server/Parser/Plugin: FeedHandler.pm ./logs: Application admin_server.log ./logs/Application: ./t: 01app.t Interface Parser.t Plugin ./t/Interface: ParserInterface.t ./t/Plugin: FeedHandler.t

Replies are listed 'Best First'.
Re: Class::MOP won't load a class!!
by stvn (Monsignor) on Sep 23, 2009 at 18:04 UTC

    What does Admin_server::Parser::Plugin::FeedHandler look like? Are you 100% sure it actually has a does method? Perl is generating that error because it can't find the does method, the comment about it not being loaded is just perl suggesting a possible cause.

    -stvn
      Hi Steven,

      Thanks for the reply.

      doesis a sugar function exported by Moose. It's job is to check if a given Moose class 'does' a role. (See http://search.cpan.org/~drolsky/Moose-0.89/lib/Moose/Manual/Roles.pod).

      I am more inclined to believe that the class hasn't been loaded because in the output of t/Parser.t, I don't see the line finished loading plugin.

      Admin_server::Parser::Plugin::FeedHandler has four functions - none of which is does. I could list them out but not sure if they are relevant to the discussion.

        does is a sugar function exported by Moose. It's job is to check if a given Moose class 'does' a role.

        Yes, I know, I am the (original) author of Moose and Class::MOP :)

        And actually, does is not part of the exported sugar, it is a method of Moose::Object.

        I am more inclined to believe that the class hasn't been loaded because in the output of t/Parser.t, I don't see the line finished loading plugin.

        Yes, but the failure is saying there is no does method, and you don't call the does until after that line would be printed. There is no reason why Class::MOP::is_class_loaded would be calling does as does is a Moose thing and not a Class::MOP thing. Perhaps you are calling or loading an older version of the Admin_server::Parser module?

        Admin_server::Parser::Plugin::FeedHandler has four functions - none of which is does. I could list them out but not sure if they are relevant to the discussion.

        Perhaps it wouldn't be helpful, but it wouldn't hurt either. It also might be good to let us know the version of Moose/Class::MOP your running too.

        For what its worth, it works on my machine when I reproduced your code and setup.

        -stvn