带有验证器的 Perl 工作流模块

Posted

技术标签:

【中文标题】带有验证器的 Perl 工作流模块【英文标题】:Perl Workflow module with validator 【发布时间】:2015-03-11 09:10:32 【问题描述】:

我正在尝试使用 perl 工作流模块 - http://search.cpan.org/~jonasbn/Workflow/

我设法弄清楚它是如何与工作流、动作、条件等一起工作的,但我无法将验证器类应用于动作。

我的 _init 方法从验证器加载并打印出我放在那里进行测试的行,但验证方法从未被触发。此外,当从动作类中转储 $self->get_validators() 时,我得到空列表。

我创建了一个简短的示例,所以请尝试一下,如果您发现问题,请提供帮助。天呐!

代码链接 - https://github.com/vmcooper/perl_workflow_test

运行程序

程序开始于

Answer: London
If you answer right the action should change state to 'finished'. Try answering wrong first.
Capital city of England:

如果你回答“伯明翰”,它应该写成

Your answer is being validated!

然后再问一遍。

当你回答“伦敦”时应该

Correct! Current state of workflow is - finished

编辑现在无论您的答案是什么,它都会写出“正确!当前工作流程状态已完成”。

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;

工作流.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>

验证器.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;

编辑: 如果我在创建之后和执行任何操作之前立即转储工作流对象,我会得到:

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' );

如您所见,验证器在这里,一切都已设置好,看起来没问题,但验证器未应用。

【问题讨论】:

hm...我可以将其总结为更清晰和最小化:在执行操作之前不应用验证器。就那么简单。我还包含了代码和一个 github repo,所以我真的不知道如何更精确。 代码很简单,因为我只是希望了解这个模块是如何工作的。您可以在“运行程序”下查看它应该做什么。它是加粗的。让我通知您,我在这里使用的 perl 模块不是我自己编写的。 cpan 顶部有一个链接,您可以在其中看到我正在谈论的模块。这就是为什么我要问是否有人知道如何使用它以及我在配置文件或类中做错了什么? 对不起,错过了伯明翰示例的添加。现在问题确实完成了,谢谢。 我刚刚从 Workflow.pm 本身打印了一些转储。我将转储放在“$action->validate($self);”之前的“execute_action”方法中我试图转储“$action->get_validators()”。结果是空的!所以这就是验证器永远不会被执行的原因。问题是他在工作流对象中,正如您在我的问题中看到的那样,但它并未应用于操作。我是否遗漏了配置中的某些内容,或者这是工作流模块中的错误? 你的例子不完整,你指的是persister.xml,没有包含,你能补充一下吗?乔纳斯本 【参考方案1】:

看起来我们将不得不等待一段时间,或者我们可以参与一个项目来完成这个功能。

滚动到“get_validators”标题,您将看到一个“#TODO”标记。 我不确定这是否意味着需要完成文档或代码,但我确实看过代码,看起来需要为这个功能完成代码。 http://search.cpan.org/~jonasbn/Workflow-1.41/lib/Workflow/Factory.pm

如果我错了,请纠正我。

【讨论】:

【参考方案2】:

我在您的示例中发现了几个问题。

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 execute 
    my $self = shift;
    my $wf = shift;
    print "App::Action::Action1::Execute\n";
    print "Validators: ".Dumper($self->get_validators())."\n";


1;

您的应用程序接收来自用户的输入但您从未将其提供给工作流的主要问题。这是使用上下文完成的,如下所示:

$context->param( answer => $city );

验证器应如下所示:

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;

您的主应用程序应类似于以下内容:

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;

我理解您的困惑,因为文档没有正确反映这一事实,并且无法从分发中的示例应用程序中读取。我会相应地更新文档。

【讨论】:

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review 我已经为您的 Github 存储库创建了 a PR 以及所有文件,很抱歉在创建自己的文件之前忽略了这一点,您的问题中缺少的文件当然在存储库中可用。我自己的回复缺少对验证器所做的更改,我会更新它。 @guillaume-darmont 您是否可以再次查看我的答案,我已对其进行了更新-如果答案当然可以证明这一点,我希望解决-1-谢谢 我对 -1 无能为力,因为 SO 只要求我对您的原始帖子 (***.com/revisions/47498915/1) 进行一些审查。反对票不是我的。

以上是关于带有验证器的 Perl 工作流模块的主要内容,如果未能解决你的问题,请参考以下文章

在 Perl 中,如何验证 Parallel::ForkManager 的每个子项是不是都完成了它的工作?

使用 node.js 验证带有 CA 证书的 X509 证书

测试使用带有 Cucumber 的设计令牌可验证模块的 JSON API

Perl 中的 Google 身份验证器实现

Perl Authen::OATH 和 Google Authenticator - 不兼容?

sh 使用ProFTPd(带有SFTP模块)为密钥验证设置SSH密钥