📄 book_openwfe.txt
字号:
// METHODS from OwfeDataSource /** * This method when implemented has to return a piece of SQL code * that will be run against any database for connection * validity checking. * (returns "select 1") * * If it were to return null, no connection validity would ever be * performed. */ public String getConnectionValiditySqlCode () { return CON_VALIDITY_SQL_CODE; }} You can see here that it's a matter of providing a decent init() override and an implementation of getConnectionValiditySqlCode(). For this latter method, you can still return 'null' if you trust your DB, the data source will then not perform any test on the connection to determine if it's still 'alive'. Feel free to submit your own implementation of data sources to OpenWFE. Not all of them may be interesting : some databases are really obscure and/or totally proprietary.Dispatchers and listeners Whenever a workitem leaves the engine for the worklist or an APRE, it has to be dispatched (except if the target component is in the same JVM as the engine, in which case, direct delivery may have been configured). Dispatchers are java classes specified in the participant map (usually etc/engine/participant-map.xml). There are currently three dispatcher implementations : file, socket and smtp. Listeners are OpenWFE services tied to an engine, a worklist or an APRE. For each class of dispatcher, there is one class of Listener. Respectively : file, socket and mail.Dispatching over a socket Out of the box, OpenWFE dispatches workitem over TCP sockets. This is configured in the participant-map.xml with for example : <participant name="role-.*"> <param> <param-name>dispatcherClass</param-name> <param-value>openwfe.org.engine.impl.dispatch.SocketDispatcher</param-value> </param> <param> <param-name>host</param-name> <param-value>127.0.0.1</param-value> </param> <param> <param-name>port</param-name> <param-value>7008</param-value> </param> </participant> that tell the engine (and other interested components) that workitem for participants whose name begin with "role-" should be sent by using an instance of the class SocketDispatcher. The parameters of the participant are then fed to the dispatcher, these are 'host' and 'port', they indicate the destination of the socket despatchement. On the other side, the 'receiving' component ought to have a listener ready : <service name="Listener.socket" class="openwfe.org.engine.impl.listen.SocketListener" > <param> <param-name>port</param-name> <param-value>7008</param-value> </param> <param> <param-name>workItemConsumer</param-name> <param-value>Consumer.worklist</param-value> </param> <!-- For machines with multiple interfaces, you can specify on which one it should listen. By default, it listens on all. <param> <param-name>inetAddress</param-name> <param-value>192.168.7.3</param-value> </param> --> </service> The listener is listening on port 7008, the received workitems are fed to the consumer service named 'Consumer.worklist'. For an engine component, the consumer would probably be 'Consumer.engine'. <!-- The consumer takes care of verifying workitems before giving them to other components. This consumer gives workitem to the worklist --> <service name="Consumer.worklist" class="openwfe.org.worklist.ListWorkItemConsumer" > </service> There isn't much to configure about a consumer, but it's important to tie the listener to the appropriate consumer.Dispatching over a smtp(listening to a POP / IMAP account) OpenWFE is able to use the internet mail infrastructure to transmit its workitem. The mail thus sent contain as payload workitems and are thus not intended for human 'consumption'. Though you could imagine one human recipient tweaking XML in a workitem thus 'participating' in a flow. Using the internet email infrastructure might be slower than direct TCP connection, but that infrastructure is robust : a message can stay in a POP3 inbox while no engine MailListener is polling for it. Smtp servers like sendmail and exim do their best at trying to deliver mail messages, they implement proven retry techniques. For a 'WAN' workflow, this dispatcher/listener couple might be optimal. On the emitting side, an smtp enabled participant (etc/engine/participant-map.xml) : <participant name="over-smtp"> <param> <param-name>dispatcherClass</param-name> <param-value>openwfe.org.engine.impl.dispatch.SmtpDispatcher</param-value> </param> <param> <param-name>recipient</param-name> <param-value>pivot@nowhere.comp</param-value> </param> <param> <param-name>smtp-server</param-name> <param-value>mail.nowhere.comp</param-value> </param> <!-- <param> <param-name>smtp-port</param-name> <param-value>25</param-value> </param> --> <param> <param-name>mail-from</param-name> <param-value>glups@nowhere.comp</param-value> </param> <!-- You can specify a 'carbon-copy' recipient. Maybe an 'archive' account. --> <param> <param-name>cc</param-name> <param-value>nada@nowhere.comp</param-value> </param> <param> <param-name>workItemCoder</param-name> <param-value>xmlCoder</param-value> </param> </participant> The 'MailListener' service is a daemon polling a POP3 or an IMAP inbox for new workitems. Consumed workitems are then removed from the box. It's configured in etc/engine/engine-configuration.xml : <service name="mailListener" class="openwfe.org.engine.impl.listen.MailListener" > <param> <param-name>accountUrl</param-name> <param-value>pop3://username:password@mail.nowhere.comp</param-value> </param> <!-- for POP3, defaults to INBOX <param> <param-name>folder</param-name> <param-value>INBOX</param-value> </param> --> <!-- the default frequency is '30s' --> <param> <param-name>frequency</param-name> <param-value>20s</param-value> </param> <param> <param-name>workItemConsumer</param-name> <param-value>Consumer</param-value> </param> </service>Securing the dispatch (showing how to use SSH-tunnelling for easily protecting communications between remote OpenWFE components)How should the workitem get encoded Dispatchers do decide which encoder is used to turn a workitem instance into a stream of bytes transferrable from one OpenWFE component to the other.OpenWFE as a service This chapter is intended for sysadmins being tasked to install an instance of OpenWFE on a system.OpenWFE as a linux service A linux system usually places its services' start scripts in /etc/rc.d/ or /etc/init.d/. Here is an example of a start script for a Debian system. (OpenWFE is developed on Debian GNU/Linux). Figure 4.2. OpenWFE Debian start script#! /bin/shset -ePATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin## may be necessary##export JAVA_HOME=/usr/local/java#OWFE_USER=toto#OWFE_GROUP=totoOWFE=/usr/local/owfe-suite.shNAME=openwfeDESC="OpenWFE - Open source WorkFlow Engine"SCRIPTNAME=/etc/init.d/$NAME# Gracefully exit if the package has been removed.test -x $DAEMON || exit 0case "$1" in start) echo "Starting $DESC: $NAME." #start-stop-daemon --start --quiet --chuid $OWFE_USER:$OWFE_GROUP --exec $OWFE start-stop-daemon --start --quiet --exec $OWFE ;; stop) echo "Stopping $DESC: $NAME." $OWFE stop ;; *) # echo "Usage: $SCRIPTNAME {start|stop}" >&2 echo "Usage: $SCRIPTNAME {start|stop}" >&2 exit 1 ;;esacexit 0 You can see that in this example, OpenWFE has been deployed in /usr/local/openwfe and is run as the root user. This script located at /etc/init.d/openwfe can then be chmod a+x /etc/init.d/openwfe and added to the services started at boot time with update-rc.d openwfe defaults. The service can then be manually started or stopped with /etc/init.d/openwfe start or invoke-rc.d openwfe startOpenWFE as a windows service (Maybe someone charitable will contribute this section, I myself run OpenWFE on linux exclusively)Chapter 5. An example : a ticket system This example chapter got really out of date, so it got removed. A better document to look at is 'Vamsee Newbie Guide' that can be found in the Documentation section of http://www.openwfe.org.Chapter 6. Workflow definitions Table of Contents How does the workflow engine works ? Workflow definitions Expressions Workitems Expressing a business process The 'participant' expression set if case equals not and or greater-than lesser-than when sleep save and restore inc unset undefined defined subprocess log using variables with the dollar notation using constants with the dollar notation functions Implementing your own expressions Validation of an XML workflow definitionHow does the workflow engine works ?Workflow definitions A workflow definition is simply a text file. Actually, this text is structured as XML. Each release of OpenWFE comes with a process-definitions/ directory where all those files do fit. This directory is mapped to a small Jetty webserver that listens on port 7079 (it is launched as service 'EngineContext.workflowDefinitionServer' in etc/engine/engine-configuration.xml) You don't have to restart the engine in order to activate your newly designed workflow definitions, you just have to copy it in workflow-definitions/ or directly edit it there. Let's assume you've created a workflow definition for flow named 'myflow' with revision '1.0' and saved it under myflow__1.0.xml.General structure of a workflow definition Workflow definitions are XML documents. The root node is named 'process-definition' and has two mandatory attributes : 'name' and 'revision'. An XML Schema for the workflow definitions can be found at http://www.openwfe.org/flowdef_r1.5.0.xsd If you want to take leverage of it with a power-xml-editor, your workflow definition XML document like this :<process-definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.openwfe.org/flowdef_r1.5.0.xsd" name="myflow" revision="1.x"> the first children nodes may be description nodes like : <description language="default"> A filtered flow. The participant 'alice' may not have complete access to all fields of the workitems transiting to her through this flow. </description> <description language="fr"> Un flux filtr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -