Search code examples
perlmoosemoosex-types

Newbie Moose, MooseX::Storage, and MooseX::Log4Perl problem: Can't store object


I'm writing my first moose base program. The program creates a "state" object that is a composition of several other moose objects. At the end of the program, I wish to save the "state" object to a file. I'm attempting to use MooseX::Storage to do this. I get an error (below) that implies to me that it is trying to serialize the MooseX::Log::Log4perl object.

Object (Log::Log4perl::Logger=HASH(0x2211c800)) does not have a &pack method, cannot collapse at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Engine.pm line 205
    MooseX::Storage::Engine::__ANON__('Log::Log4perl::Logger=HASH(0x2211c800)', 'HASH(0x20c54890)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Engine.pm line 88
MooseX::Storage::Engine::collapse_attribute_value('MooseX::Storage::Engine=HASH(0x2211cac0)', 'Moose::Meta::Attribute=HASH(0x20419510)', 'HASH(0x20c54890)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Engine.pm line 60
MooseX::Storage::Engine::collapse_attribute('MooseX::Storage::Engine=HASH(0x2211cac0)', 'Moose::Meta::Attribute=HASH(0x20419510)', 'HASH(0x20c54890)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Engine.pm line 141
MooseX::Storage::Engine::map_attributes('MooseX::Storage::Engine=HASH(0x2211cac0)', 'collapse_attribute', 'HASH(0x20c54890)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Engine.pm line 37
MooseX::Storage::Engine::collapse_object('MooseX::Storage::Engine=HASH(0x2211cac0)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Basic.pm line 13
MooseX::Storage::Basic::pack('ScanCtr::State=HASH(0x2100ee40)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/Format/JSON.pm line 24
MooseX::Storage::Format::JSON::freeze('ScanCtr::State=HASH(0x2100ee40)') called at /usr/lib/perl5/site_perl/5.8.8/MooseX/Storage/IO/File.pm line 19

Here's my setup. I have a class called "ScanCtr::ScanMe" and it does only this:

package ScanCtr::ScanMe;
use Moose;
with 'MooseX::Log::Log4perl';
use namespace::autoclean;
use Log::Log4perl qw(:easy);
BEGIN {
    Log::Log4perl->easy_init({
        level   => $DEBUG,
        file    => ">>/var/log/sc.log",
        layout  => '%d %p [%P] %l %m%n',
    });
};
1;

My other objects including extend this object (which may be my problem) so I can do stuff like $self->log->debug("debug message"); within each of my objects. For example:

package ScanCtr::State;
use ScanCtr::Request;
use Moose;
extends 'ScanCtr::ScanMe';
use Moose::Util::TypeConstraints;
use MooseX::Storage;
our $VERSION = '0.01';
with Storage ( 'format' => 'JSON', 'io' => 'File');
use namespace::autoclean;


has 'requests'          => (
    traits  => [ 'Hash' ],
    is      => 'rw',
    isa     => 'HashRef[ScanCtr::Request]',
    default => sub { {} },
    handles => {
        count           => 'count',
        get             => 'get',
        set             => 'set',
        delete_request  => 'delete',
        request_keys    => 'keys',
        kv              => 'kv',
    }
);
1;

So is there a way to exclude the MooseX::Log::Log4perl from the Storage? Is there a better approach that will avoid this problem? What other newbie mistakes am I making?

Thanks for any help, Todd.


Solution

  • This should work (but I haven't tested it). Inside ScanCtr::ScanMe you need to override the Logger attribute and apply the DoNotSerialize trait from MooseX::Storage.

    package ScanCtr::ScanMe;
    use Moose;
    with 'MooseX::Log::Log4perl';
    use namespace::autoclean;
    use Log::Log4perl qw(:easy);
    BEGIN {
        Log::Log4perl->easy_init({
            level   => $DEBUG,
            file    => ">>/var/log/sc.log",
            layout  => '%d %p [%P] %l %m%n',
        });
    };
    
    has '+logger' => { traits => ['DoNotSerialize'] };
    
    1;