How to interact with working items

7 views
Skip to first unread message

Igor Sutton

unread,
Jul 5, 2007, 11:33:51 AM7/5/07
to OpenWFEru users
Hi there,

I'm trying implementing an OpenWFEru and Rails application, but I have
no idea on how can I interact with the workflow.

I need some user input at each workflow step, but I have no success
and no idea on how to proceed about it.

Thanks!

John Mettraux

unread,
Jul 5, 2007, 7:03:23 PM7/5/07
to openwfe...@googlegroups.com

Hi Igor,

you have to store the workitems for the 'user input' into some kind of
persisted participant.

The engine will put the workitems in those store participants and your
application can then interact with them, manipulating the workitems,
and then you can forward (proceed) the workitem back into its process
via the store's forward method.


You could use HashParticipant
(http://openwferu.rubyforge.org/participants.html#HashParticipant),
but it's not persisted at all (you restart your application and the
workitems are gone).

There is then the YamlParticipant
(http://openwferu.rubyforge.org/participants.html#YamlParticipant)
which behaves as the HashParticipant but the workitems are persisted.

The YamlParticipant is used in this example :
http://openwferu.rubyforge.org/examples/mano_tracker.rb
It shows how to interact with those 'store participants'.

You can consider those participants as "workitem stores" for workitems
ready for user input are stored.


There is a third participant that you might consider, it's not yet
publicly released. It stores the records in your database via
ActiveRecord. It's at
http://viewvc.rubyforge.mmmultiworks.com/cgi/viewvc.cgi/trunk/densha/?root=openwferu

The core is at http://viewvc.rubyforge.mmmultiworks.com/cgi/viewvc.cgi/trunk/densha/lib/openwfe/densha/?root=openwferu

There is a test case that my help you :
http://viewvc.rubyforge.mmmultiworks.com/cgi/viewvc.cgi/trunk/densha/test/with_engine_test.rb?root=openwferu&view=markup


If you have any other question, just ask. Feedback is welcome. Best regards,

--
John Mettraux -///- http://jmettraux.openwfe.org

Igor Sutton Lopes

unread,
Jul 6, 2007, 11:44:41 AM7/6/07
to openwfe...@googlegroups.com
Hi,

Nice, I read those documents, and now I have more questions.

My workflow is defined this way:

<code>
class RequisicaoProcessDefinition < OpenWFE::ProcessDefinition
def make
sequence do
participant :ref => 'Vendedor', :task => 'SolicitaOrcamento'
wait :until => "${f:status} == 'pronto'"
participant :ref => 'Fornecedor', :task => 'OutraAcao'
end
end
end
</code>

And my participants are defined this way - they're identical:

<code>
class VendedorParticipant < OpenWFE::YamlParticipant
include LocalParticipant

def logger
@logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
end

def consume(workitem)
fe = get_flow_expression(workitem)
task = fe.attributes['task']

raise "request parameter is undefined" unless task

logger.debug("Vendedor Participant request: #{task}")
reply_to_engine(workitem)
end
end
</code>

I'm searching for the participant in Rails controller like this:

<code>
def list
@participant = $engine.get_participant_map.lookup_participant
('Vendedor')
end
</code>

Now, the questions:

- At the 'wait' expression in my process definition, who 'owns' it?
'Vendedor' or 'Fornecedor'?

- At the Rails controller, how can I find the processes which are
waiting for @participant action?

- The participants on my system will be the same as my system's
Roles, instead of being each participant some different person like
Mano's sample. Is that a good approach for it?

Thanks for your support!

PGP.sig

John Mettraux

unread,
Jul 7, 2007, 12:06:27 AM7/7/07
to openwfe...@googlegroups.com
Hi Igor,

On 7/7/07, Igor Sutton Lopes <igor....@gmail.com> wrote:
>
> My workflow is defined this way:
>
> <code>
> class RequisicaoProcessDefinition < OpenWFE::ProcessDefinition
> def make
> sequence do
> participant :ref => 'Vendedor', :task => 'SolicitaOrcamento'
> wait :until => "${f:status} == 'pronto'"
> participant :ref => 'Fornecedor', :task => 'OutraAcao'
> end
> end
> end
> </code>

You can write it :

---8<---
class RequisitionProcessDefinition < OpenWFE::ProcessDefinition


sequence do
participant :ref => 'Vendedor', :task => 'SolicitaOrcamento'
wait :until => "${f:status} == 'pronto'"
participant :ref => 'Fornecedor', :task => 'OutraAcao'
end
end

--->8---

It works fine as well and looks more like a Class definition.

> And my participants are defined this way - they're identical:
>
> <code>
> class VendedorParticipant < OpenWFE::YamlParticipant
> include LocalParticipant
>
> def logger
> @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
> end
>
> def consume(workitem)
> fe = get_flow_expression(workitem)
> task = fe.attributes['task']
>
> raise "request parameter is undefined" unless task
>
> logger.debug("Vendedor Participant request: #{task}")
> reply_to_engine(workitem)
> end
> end
> </code>

First, let me please give you a piece of advice, but please don't take
it personally. You should never use something other than English in a
language whose base construction bricks are in English. It breaks
readability and maintainability. Portuguese must be kept away from the
code, it should appear at localization time only (and of course in
data).

OK, you want to use the YamlParticipant, good idea, I don't think you
need to extend it. Maybe just in this way.

---8<---
class HumanParticipant < OpenWFE::YamlParticipant

def initialize (dirname, application_context)
super


@logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
end

def consume (workitem)

task = workitem.params['task']
unless task
#
# rejecting workitems whose participant did not have the
# 'task' attribute
#
workitem.error = "request parameter is undefined"
reply_to_engine workitem
else
#
# workitem is OK, let the father class do the work :
# storing the workitem in a YAML file.
#
@logger.debug "consume() human participant request : #{task}"
super
end
end
end

#...

$engine.register_participant :salesman, HumanParticipant
$engine.register_participant :supplier, HumanParticipant
#
# in the process definition itself, I would forget about having
any Portuguese.
--->8---


> I'm searching for the participant in Rails controller like this:
>
> <code>
> def list
> @participant = $engine.get_participant_map.lookup_participant
> ('Vendedor')
> end
> </code>

---8<---
def list
@participant = $engine.get_participant :salesman
# there is this get_participant() shortcut in the engine
end
--->8---

> Now, the questions:
>
> - At the 'wait' expression in my process definition, who 'owns' it?
> 'Vendedor' or 'Fornecedor'?

Nobody owns it. You should not use wait in your process definition.
The wait thing you want is implicit with the YamlParticipant you are
using. The workitem stays in the YamlParticipant until you call
participant.reply_to_engine(workitem) (workitem possibly modified)
from one of your controller, at which point the process instance
resumes. No need for a "wait".

So your process definition could look like :

---8<---
class RequisitionProcessDefinition < OpenWFE::ProcessDefinition
sequence do
participant :ref => salesman, :task => 'Orcamento Request'
participant :ref => supplier, :task => 'Other Acao'
end
end
--->8---

or even like :

---8<---
class RequisitionProcessDefinition < OpenWFE::ProcessDefinition
sequence do
salesman :task => 'Orcamento Request'
supplier :task => 'Other Acao'
end
end
--->8---

The 'wait' expression is used in concurrent cases when you wait for a
condition to realize in another (parallel) branch of the process.


> - At the Rails controller, how can I find the processes which are
> waiting for @participant action?

For example to get all the workitems waiting for a salesman action/activity :

$engine.get_participant(:salesman).each do |fei, workitem|
puts " - #{fei.wfid} -- #{workitem.params['task']}"
end

or in your view

@participant.each do |fei, workitem|
#... do some rendering...
end

see : http://openwferu.rubyforge.org/rdoc/classes/OpenWFE/YamlParticipant.html
and its mixin :
http://openwferu.rubyforge.org/rdoc/classes/OpenWFE/StoreParticipantMixin.html


> - The participants on my system will be the same as my system's
> Roles, instead of being each participant some different person like
> Mano's sample. Is that a good approach for it?

I think your approach is better. It's very good to use role names like
:salesman or :supplier. Well done.


Your questions and feedback are welcome, best regards,

Reply all
Reply to author
Forward
0 new messages