Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

getting automatic error checking with Win32::OLE and Moose

by glasswalk3r (Friar)
on Jan 15, 2013 at 15:53 UTC ( [id://1013414]=perlquestion: print w/replies, xml ) Need Help??

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

UPDATED due bug found by tobyink

Greetings monks,

I'm trying to figure out a way to have automatic error checking when invoking methods from a Win32::OLE object, for example:

my $sa = Win32::OLE->new("SiebelDataServer.ApplicationObject") or die +"failed"; $rcref = Variant(VT_I2|VT_BYREF, 0); $sa->LoadObjects($cfg, $rcref); x("a", $rcref); sub x { my ($tag, $rc) = @_; warn("[$tag] " . $sa->GetLastErrText()) unless $rc == 0) }

This way I will need to call x function every time after calling a Win32::OLE method. This seems to be quite boring.

Instead, I would like to encapsulate the Win32::OLE object inside a Moose object and execute the error checking automatically.

First thought that I had is using the Triggers in a attribute that has a reference to the Win32::OLE::Variant object, but this does not look like it will work because a trigger will be activated only when a writer method is invoked for the attribute or during the object construction.

After that I considered using AROUND_modifiers in a to be defined role, doing it for every method that invokes a Win32::OLE method internally. The AROUND would look like this (I didn't check if this code would work, just an example):

package Automatic:Check; use Moose::Role; around 'load_objects' => sub { my $orig = shift; my $self = shift; $rcref = Variant(VT_I2|VT_BYREF, 0); return $self->$orig(@_, $rcref); }; package SA::Application; use Moose; use Automatic::Check; has ole => ( is => 'ro', isa => 'Win32::OLE', builder => '_build_ole') +; sub _build_ole { return Win32::OLE->new("SiebelDataServer.ApplicationObject" or die + "failed"; } sub load_objects { my $self = shift; my $cfg = shift; die "error" unless ( $rcref == 0 ); $self->ole()->LoadObjects($cfg); } package main; my $cfg = 'somefile.cfg'; my $sa = SA::Application->new(); eval { my $sa->load_objects($cfg); }; if ($@) { die $sa->GetLastErrText(); }

But this does not seems to be lazy enough since I would need to create a new role for each different kind of Win32::OLE classes that I'm using.

Do you monks have any other suggestion that could improve this laziness?

Alceu Rodrigues de Freitas Junior
---------------------------------
"You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

Replies are listed 'Best First'.
Re: getting automatic error checking with Win32::OLE and Moose
by tobyink (Canon) on Jan 15, 2013 at 16:46 UTC

    Firstly, your around modifier is broken...

    around 'load_objects' => sub { my $orig = shift; my $self = shift; $rcref = Variant(VT_I2|VT_BYREF, 0); return $self->$orig(@_, $rcref); die "error" unless ( $rcref == 0 ); };

    The die is after an unconditional return statement, so will never happen.

    As I understand it, you have a single wrapper function that you'd like to apply to a lot of methods. But you don't want to hard-code within the wrapper role the names of all those functions.

    This is a natural desire; to avoid tightly coupling the wrapper code with the class being wrapped. (See also: Aspect-Oriented Programming.)

    Anyhow, although it's still at an early stage of development, my module MooseX::ModifyTaggedMethods might be of help. This allows you to tag methods within a class, and write roles that use these tags to decide which methods to wrap.

    package Automatic::Check { use MooseX::RoleQR; use MooseX::ModifyTaggedMethods; around methods_tagged('ShouldCheck') => sub { my $orig = shift; my $self = shift; $rcref = Variant(VT_I2|VT_BYREF, 0); return $self->$orig(@_, $rcref); die "error" unless ( $rcref == 0 ); # never happens }; } package SA::Application { use Moose; use Sub::Talisman qw( ShouldCheck ); with 'Automatic::Check'; has ole => ( is => 'ro', isa => 'Win32::OLE', builder => '_build_ole +'); sub _build_ole { return Win32::OLE->new("SiebelDataServer.ApplicationObject" or die + "failed"; } sub load_objects : ShouldCheck { my $self = shift; my $cfg = shift; $self->ole->LoadObjects($cfg); } }

    I don't have Windows, so can't test the above, but it should give you the idea of how it works.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
    $orig(@_, $rcref); die unless ( $rcref == 0 ); # never happens }; } package SA::Application { use Moose; use Sub::Talisman qw( ShouldCheck ); with
Re: getting automatic error checking with Win32::OLE and Moose
by Arunbear (Prior) on Jan 15, 2013 at 18:21 UTC
    What about a simpler way:
    package Automatic::Check; use Moose::Role; requires qw(wrapped check_ref assert_check_ref); sub call { my $self = shift; my $method = shift; my $check_ref = $self->check_ref; $self->wrapped->$method(@_, $check_ref); $self->assert_check_ref($check_ref); warn 'ok'; } package FakeOLE; sub new { bless {} } sub LoadObjects { my $self = shift; my $cfg = shift; $_[0] = $cfg ? 0 : -1; } package SA::Application; use Moose; has wrapped => ( is => 'ro', builder => '_build_ole'); with qw/Automatic::Check/; sub _build_ole { return FakeOLE->new; } sub check_ref { 1 } sub assert_check_ref { my ($self, $check_ref) = @_; die "error" unless ( $check_ref == 0 ); } package main; my $cfg = 'somefile.cfg'; my $sa = SA::Application->new(); $sa->call('LoadObjects', $cfg); # ok $sa->call('LoadObjects', 0); # dies
    Here the role could be applied to any of your wrapper classes as long as they provide methods to get the wrapped object, the validation logic and the $rcref.
Re: getting automatic error checking with Win32::OLE and Moose
by Anonymous Monk on Jan 16, 2013 at 09:12 UTC

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2024-04-20 04:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found