i'm trying to get things work with perl Workflow module - http://search.cpan.org/~jonasbn/Workflow/
I managed to figure out how it works with workflows, actions, conditions and all but i can't get it to apply validator class to the action.
My _init method from validator loads and prints out the line that i put there for testing but validate method is not triggered ever. Also, when dumping $self->get_validators() from action class i get empty list.
I created a short example so please try it and help out if you see the problem. Tnx!
link to code - https://github.com/vmcooper/perl_workflow_test
Running the program
Program starts with
Answer: London
If you answer right the action should change state to 'finished'. Try answering wrong first.
Capital city of England:
if you answer "Birmingham" it should write
Your answer is being validated!
and ask the question again.
When you answer "London" it should
Correct! Current state of workflow is - finished
edit Now it writes out "Correct! Current state of workflow is - finished" whatever your answer is.
workflow_test.pl
use strict;
use Log::Log4perl qw( get_logger );
use Workflow::Factory qw( FACTORY );
Log::Log4perl::init( 'log4perl.conf' );
system('clear');
# Stock the factory with the configurations; we can add more later if we want
FACTORY->add_config_from_file(
workflow => 'workflow.xml',
action => 'action.xml',
persister => 'persister.xml',
validator => 'validator.xml'
);
my $workflow = FACTORY->create_workflow( "Workflow1" );
my $context = $workflow->context;
while ( $workflow->state eq "INITIAL" ) {
print "If you answer right the action should change state to 'finished'. Try answering wrong first.\n";
my $city = get_response( "Capital city of England: " );
print "You answered - $city\n";
$workflow->execute_action( 'action1' );
if( $workflow->state eq "INITIAL" ) {
print "Your answer is wrong! try again!\n\n";
}
}
print "\nCorrect! Current state of workflow is - ".$workflow->state."\n\n";
# Generic routine to read a response from the command-line (defaults,
# etc.) Note that return value has whitespace at the end/beginning of
# the routine trimmed.
sub get_response {
my ( $msg ) = @_;
print $msg;
my $response = <STDIN>;
chomp $response;
$response =~ s/^\s+//;
$response =~ s/\s+$//;
return $response;
}
workflow.xml
<workflow>
<type>Workflow1</type>
<time_zone>local</time_zone>
<description>This is my workflow.</description>
<persister>Persister1</persister>
<state name="INITIAL">
<action name="action1" resulting_state="finished"/>
</state>
<state name="finished" />
</workflow>
action.xml
<actions>
<action name="action1" class="App::Action::Action1" >
<validator name="validator1">
<arg>$city</arg>
</validator>
</action>
</actions>
validator.xml
<validators>
<validator name="validator1" class="App::Validator::Validator1">
<param name="answer" value="London" />
</validator>
</validators>
App::Action::Action1.pm
package App::Action::Action1;
use strict;
use base qw( Workflow::Action );
use Workflow::Exception qw( validation_error configuration_error );
use Data::Dumper;
sub new {
my $class = shift;
my $self = {};
bless ($self, $class);
return $self;
}
sub execute {
my $self = shift;
my $wf = shift;
print "App::Action::Action1::Execute\n";
print "Validators: ".Dumper($self->get_validators())."\n";
}
1;
App::Validator::Validator1.pm
package App::Validator::Validator1;
use strict;
use base qw( Workflow::Validator );
use Workflow::Exception qw( validation_error configuration_error );
use Data::Dumper;
use Carp qw(carp);
sub _init {
my ( $self, $params ) = @_;
unless ( $params->{answer} ) {
configuration_error
"You must define a value for 'answer' in ",
"declaration of validator ", $self->name;
}
if ( ref $params->{answer} ) {
configuration_error
"The value for 'answer' must be a simple scalar in ",
"declaration of validator ", $self->name;
}
print "Answer: ".$params->{answer}."\n";
$self->{ answer => $params->{answer} };
}
sub validate {
my ( $self, $wf, $city ) = @_;
print "Your answer is being validated!\n";
print "Your answer is - ".$city."\n";
my $check;
if ( $city eq $self->{answer} ){
$check = 1;
} else {
$check = 0;
}
unless ( $check ) {
validation_error "Validation error!";
}
}
1;
Edit: If i dump workflow object right after creation and before any action is executed i get this:
Workflow: $VAR1 = bless( {
'_states' => {
'INITIAL' => bless( {
...,
'_actions' => {
'action1' => {
'resulting_state' => 'finished',
'name' => 'action1'
}
},
'_factory' => bless( {
...,
'_action_config' => {
'default' => {
'action1' => {
'name' => 'action1',
'class' => 'App::Action::Action1',
'validator' => [
{
'arg' => [
'$city'
],
'name' => 'validator1'
}
]
}
}
},
'_validators' => {
'validator1' => bless( {
'name' => 'validator1',
'class' => 'App::Validator::Validator1',
'PARAMS' => {}
}, 'App::Validator::Validator1' )
},
'_validator_config' => {
'validator1' => {
'answer' => 'London',
'name' => 'validator1',
'class' => 'App::Validator::Validator1'
}
},
...
}, 'Workflow::Factory' ),
'type' => 'Workflow1',
'PARAMS' => {}
}, 'Workflow::State' ),
'finished' => $VAR1->{'_states'}{'INITIAL'}{'_factory'}{'_workflow_state'}{'Workflow1'}[1]
},
...
}, 'Workflow' );
As you can see, validator is here and everything is set up and looks like it's ok but the validator is not applied.
Looks like we will have to wait for this a bit or we can participate in a project to get this functionaity done.
Scroll to the "get_validators" heading and you will se a "#TODO" mark. I'm not sure whether this means the documentation needs to be done or code but i did look at the code a bit and it looks like the code needs to be done for this functionality. http://search.cpan.org/~jonasbn/Workflow-1.41/lib/Workflow/Factory.pm
Correct me if i'm wrong.
I located several issues in your example.
Action1.pm has a constructor, this interferes with the inheritance, So this should be deleted leaving your action class as follows
package App::Action::Action1;
use strict;
use base qw( Workflow::Action );
use Workflow::Exception qw( validation_error configuration_error );
use Data::Dumper;
sub execute {
my $self = shift;
my $wf = shift;
print "App::Action::Action1::Execute\n";
print "Validators: ".Dumper($self->get_validators())."\n";
}
1;
The main issue that your application receives the input from the user, but you never feed it to the workflow. This has be done using context, like so:
$context->param( answer => $city );
The validator should looks as follows:
package App::Validator::Validator1;
use strict;
use base qw( Workflow::Validator );
use Workflow::Exception qw( validation_error configuration_error );
use Data::Dumper;
use Carp qw(carp);
sub _init {
my ( $self, $params ) = @_;
unless ( $params->{answer} ) {
configuration_error
"You must define a value for 'answer' in ",
"declaration of validator ", $self->name;
}
if ( ref $params->{answer} ) {
configuration_error
"The value for 'answer' must be a simple scalar in ",
"declaration of validator ", $self->name;
}
print "Answer: ".$params->{answer}."\n";
$self->{answer} = $params->{answer};
}
sub validate {
my ( $self, $wf ) = @_;
my $city = $wf->context->param('answer');
print "Your answer is being validated!\n";
print "Your answer is - ".$city."\n";
my $check;
if ( $city eq $self->{answer} ){
$check = 1;
} else {
$check = 0;
}
unless ( $check ) {
validation_error "Validation error!";
}
}
1;
And your main application should resemble the following:
use strict;
use Log::Log4perl qw( get_logger );
use Workflow::Factory qw( FACTORY );
use lib qw(lib);
Log::Log4perl::init( 'log4perl.conf' );
system('clear');
# Stock the factory with the configurations; we can add more later if we want
FACTORY->add_config_from_file(
workflow => 'workflow.xml',
action => 'action.xml',
persister => 'persister.xml',
validator => 'validator.xml'
);
my $workflow = FACTORY->create_workflow( "Workflow1" );
my $context = $workflow->context;
while ( $workflow->state eq "INITIAL" ) {
print "If you answer right the action should change state to 'finished'. Try answering wrong first.\n";
my $city = get_response( "Capital city of England: " );
print "You answered - $city\n";
$context->param( answer => $city );
$workflow->execute_action( 'action1' );
if( $workflow->state eq "INITIAL" ) {
print "Your answer is wrong! try again!\n\n";
}
}
print "\nCorrect! Current state of workflow is - ".$workflow->state."\n\n";
# Generic routine to read a response from the command-line (defaults,
# etc.) Note that return value has whitespace at the end/beginning of
# the routine trimmed.
sub get_response {
my ( $msg ) = @_;
print $msg;
my $response = <STDIN>;
chomp $response;
$response =~ s/^\s+//;
$response =~ s/\s+$//;
return $response;
}
I understand your confusion, since the documentation does not properly reflect this fact and it cannot be read from the example application in the distribution. I will update the documentation accordingly.
来源:https://stackoverflow.com/questions/27921691/perl-workflow-module-with-validator