From b73a62db06923953d7f1239ee9e2920397f58bf3 Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Tue, 10 Dec 2024 22:56:50 +0100 Subject: [PATCH] docu --- src/site/markdown/engine/adminp.md | 40 ++--- src/site/markdown/engine/configsource.md | 17 +- src/site/markdown/engine/documentservice.md | 147 +++++++++-------- src/site/markdown/engine/index.md | 42 ++--- src/site/markdown/engine/modelservice.md | 12 +- .../markdown/engine/plugins/howto_extend.md | 60 +++---- src/site/markdown/engine/remote_lookup.md | 30 ++-- src/site/markdown/engine/scheduler.md | 32 ++-- src/site/markdown/engine/workflowscheduler.md | 24 +-- src/site/markdown/engine/workflowservice.md | 148 +++++++++--------- src/site/markdown/modelling/dataobject.md | 74 ++++----- src/site/markdown/modelling/deployment.md | 32 ++-- src/site/markdown/quickstart.md | 30 ++-- src/site/markdown/testing.md | 44 +++--- src/site/markdown/webtools/resourcebundle.md | 11 +- src/site/site.xml | 1 - 16 files changed, 376 insertions(+), 368 deletions(-) diff --git a/src/site/markdown/engine/adminp.md b/src/site/markdown/engine/adminp.md index bf942a259..8f2065688 100644 --- a/src/site/markdown/engine/adminp.md +++ b/src/site/markdown/engine/adminp.md @@ -92,29 +92,29 @@ The following fields part of the Job description are defined by the AdminP servi A JobHandler may throw a AdminPException if something went wrong. See the following example of a JobHandler implementation: ```java - public class JobHandlerDemo implements JobHandler { - @Inject - DocumentService documentService; - - @Override - public ItemCollection run(ItemCollection adminp) throws AdminPException { - // find documents... - List result=documentService.fine("type:'workitem'",0,100); - // do something... - try { - .... - } catch (Exception e) { - // throw exception if something went wrong - throw new AdminPException("ERROR", "Error...", e); - } +public class JobHandlerDemo implements JobHandler { + @Inject + DocumentService documentService; + + @Override + public ItemCollection run(ItemCollection adminp) throws AdminPException { + // find documents... + List result=documentService.fine("type:'workitem'",0,100); + // do something... + try { .... - // more work to do? - if (... more work ...) { - adminp.replaceItemValue(JobHandler.ISCOMPLETED, true); - } - return adminp; + } catch (Exception e) { + // throw exception if something went wrong + throw new AdminPException("ERROR", "Error...", e); + } + .... + // more work to do? + if (... more work ...) { + adminp.replaceItemValue(JobHandler.ISCOMPLETED, true); } + return adminp; } +} ``` To start the JobHandler via the AdminP Service interface the attribute 'job' must be set to the class name of the CDI Bean. diff --git a/src/site/markdown/engine/configsource.md b/src/site/markdown/engine/configsource.md index dc9591dac..f2e48f21d 100644 --- a/src/site/markdown/engine/configsource.md +++ b/src/site/markdown/engine/configsource.md @@ -22,18 +22,21 @@ If the same property is defined in multiple ConfigSources, based on the ordinal Each individual property can be injected directly. The injected value is static and the value is fixed on application starting. - @Inject @ConfigProperty(name="lucence.indexDir") - String lucenePath; +```java +@Inject @ConfigProperty(name="lucence.indexDir") +String lucenePath; +``` ### Config Object Injection The config object can also be injected. With this object you can use the getValue() method to retrieve an individual property at runtime. - @Inject Config config; - ... - String lucenePath = config.getValue("lucence.indexDir", String.class); - .... - +```java +@Inject Config config; +... +String lucenePath = config.getValue("lucence.indexDir", String.class); +.... +``` ## Deployment: diff --git a/src/site/markdown/engine/documentservice.md b/src/site/markdown/engine/documentservice.md index 2ab8b80c7..5a0fad464 100644 --- a/src/site/markdown/engine/documentservice.md +++ b/src/site/markdown/engine/documentservice.md @@ -10,17 +10,17 @@ A Document in the Imixs-Workflow systems is represented by the [ItemCollection c The following example shows how an instance of an ItemCollection can be saved using the _DocumentService_: ```java - @Inject - DocumentService documentService; - //... - - ItemCollection myDocument=new ItemCollection; - myDocument.setItemValue("type","product"); - myDocument.setItemValue("name","coffee"); - myDocument.setItemValue("weight",new Integer(500)); - - // save ItemCollection - myDocument=documentService.save(myDocument); +@Inject +DocumentService documentService; +//... + +ItemCollection myDocument=new ItemCollection; +myDocument.setItemValue("type","product"); +myDocument.setItemValue("name","coffee"); +myDocument.setItemValue("weight",new Integer(500)); + +// save ItemCollection +myDocument=documentService.save(myDocument); ``` In this example a new ItemCollection is created and the properties 'type, 'name' and 'weight' are stored into a ItemCollection. The save() method stores the document into the database. If the document is stored the first time, the method generates an ID which can be used to identify the document for later access. This ID is provided in the property '$uniqueid' which will be added automatically by the _DocumentService_. If the document was saved before, the method updates only the items of the document in the database. @@ -28,15 +28,15 @@ In this example a new ItemCollection is created and the properties 'type, 'name' The next example shows how to use the $uniqueid of a stored ItemCollection to load the document from the database. For this the ID is passed to the load() method: ```java - @Inject - DocumentService documentService; - //... - // save document - myDocument=documentService.save(myDocument); - // get ID from ItemCollection - String id=myDocument.getUniqueID(); - // load the document from database - myDocument=documentService.load(id); +@Inject +DocumentService documentService; +//... +// save document +myDocument=documentService.save(myDocument); +// get ID from ItemCollection +String id=myDocument.getUniqueID(); +// load the document from database +myDocument=documentService.load(id); ``` __Note:__ The method load() checks if the CallerPrincipal has read access to a document. If not, the method returns null. The method doesn't throw an AccessDeniedException if the user is not allowed to read the document. This is to prevent an aggressor with informations about the existence of that specific document. @@ -45,16 +45,16 @@ __Note:__ The method load() checks if the CallerPrincipal has read access to a d A document is categorized by the item 'type'. The type attribute can be used to group document or select documents by its type. - - ItemCollection myDocument=new ItemCollection; - myDocument.settemValue("type","product"); - .... - // save ItemCollection - myDocument=documentService.save(myDocument); - - // select documents by type... - List products=documentService.getDocumentsByType("product"); - +```java +ItemCollection myDocument=new ItemCollection; +myDocument.settemValue("type","product"); +.... +// save ItemCollection +myDocument=documentService.save(myDocument); + +// select documents by type... +List products=documentService.getDocumentsByType("product"); +``` ### Creation and Modified Date @@ -62,11 +62,10 @@ A document is categorized by the item 'type'. The type attribute can be used to The _DocumentService_ also creates TimeStamps to mark the creation and last modified date of a document. These properties are also part of the document returned by the save method. The items are named "$created" and "$modified". ```java - //... - // save ItemCollection - myDocument=documentService.save(myDocument); - Date created=myDocument.getItemValueDate("$Created"); - Date modified=myDocument.getItemValueDate("$Modified"); +// save ItemCollection +myDocument=documentService.save(myDocument); +Date created=myDocument.getItemValueDate("$Created"); +Date modified=myDocument.getItemValueDate("$Modified"); ``` ### Immutable Documents @@ -85,15 +84,15 @@ The find() method of the _DocumentService_ can be used to query documents by a L The following example returns all documents starting with the search term 'Imixs': ```java - String serachTerm="(imixs*)"; - result=documentService.find(serachTerm); +String serachTerm="(imixs*)"; +result=documentService.find(serachTerm); ``` To query for a specific subset of documents, it is also possible to add individual attributes to the search term. The follwoing example will return all documents with the serach term 'imixs' and the Type 'workitem': ```java - String serachTerm="(type:'workitem')(imixs*)"; - result=documentService.find(serachTerm); +String serachTerm="(type:'workitem')(imixs*)"; +result=documentService.find(serachTerm); ``` See the section [Query Syntax](queries.html) for details about how to search for documents. @@ -103,9 +102,9 @@ See the section [Query Syntax](queries.html) for details about how to search for The _DocumentService_ finder method can also be called by providing a pagesize and a pageindex. With these parameters navigate by pages through a search result. See the following example: ```java - String serachTerm="(imixs*)"; - // return only the first 10 documents - result=documentService.find(serachTerm,10,0); +String serachTerm="(imixs*)"; +// return only the first 10 documents +result=documentService.find(serachTerm,10,0); ``` Note that the pageindex starts with 0. @@ -115,10 +114,10 @@ Note that the pageindex starts with 0. Per default the search result is sorted by the lucene internal score of each document returned by the index. To sort the documents by a specific attribute a sortItem and a sort direction can be given: ```java - String serachTerm="(imixs*)"; - // return only the first 10 documents - // sort by $created descending - result=documentService.findStubs(serachTerm,10,0,'$created',true); +String serachTerm="(imixs*)"; +// return only the first 10 documents +// sort by $created descending +result=documentService.findStubs(serachTerm,10,0,'$created',true); ``` ### Document Stubs @@ -126,7 +125,7 @@ Per default the search result is sorted by the lucene internal score of each doc The Imixs Search Index provides a feature to store parts of a document directly into the index. This feature allows you to search for the so called 'Document Stubs'. A Document stub contains only a subset of Items from the full Document. This search method is much faster and can be used to display a preview of a document in the result-set like you know it from the Internet search. ```java - result = documentService.findStubs(query, 100, 0, '$created' , true); +result = documentService.findStubs(query, 100, 0, '$created' , true); ``` You can later load the full document by the $uniqueid which is part of the document stub. @@ -164,22 +163,22 @@ All documents are managed by the Java Persistece API (JPA). The Java Persistence Additional the _DocumentService_ allows to restrict the read- and write access for a document by providing a [ACL](.acl.html). The items '$readaccess' and '$writeaccess' can be added into a document to restrict the access. The items can provide a list of UserIds or Roles. ```java - @Inject - DocumentService documentService; - //... - - ItemCollection myDocument=new ItemCollection; - myDocument.setItemValue("type","product"); - myDocument.setItemValue("name","coffee"); - myDocument.setItemValue("weight",new Integer(500)); - - // restrict read access to 'bob' - myDocument.setItemValue("$readaccess","bob"); - // restrict write access to 'anna' - myDocument.setItemValue("$readaccess","anna"); - - // save ItemCollection - myDocument=documentService.save(myDocument); +@Inject +DocumentService documentService; +//... + +ItemCollection myDocument=new ItemCollection; +myDocument.setItemValue("type","product"); +myDocument.setItemValue("name","coffee"); +myDocument.setItemValue("weight",new Integer(500)); + +// restrict read access to 'bob' +myDocument.setItemValue("$readaccess","bob"); +// restrict write access to 'anna' +myDocument.setItemValue("$readaccess","anna"); + +// save ItemCollection +myDocument=documentService.save(myDocument); ``` For further details read the [section ACL](./acl.html). @@ -200,11 +199,11 @@ Based on CDI Events your can inject custom user groups from your own application The typically implementation of this mechanism is done by an CDI observer pattern: ```java - public void onUserGroupEvent(@Observes UserGroupEvent userGroupEvent) { - List customGroups = new ArrayList(); - customGroups.add("my-group"); - userGroupEvent.setGroups(customGroups); - } +public void onUserGroupEvent(@Observes UserGroupEvent userGroupEvent) { + List customGroups = new ArrayList(); + customGroups.add("my-group"); + userGroupEvent.setGroups(customGroups); +} ``` ## The CDI DocumentEvent @@ -226,13 +225,13 @@ The class _DocumentEvent_ defines the following event types: This _DocumentEvent_ can be consumed by another Session Bean or managed bean implementing the @Observes annotation: ```java - @Stateless - public class DocumentServiceListener { - public void onEvent(@Observes DocumentEvent documentEvent){ - ItemCollection document=documentEvent.getDocument(); - System.out.println("Received DocumentEvent Type = " + documentEvent.getType()); - } +@Stateless +public class DocumentServiceListener { + public void onEvent(@Observes DocumentEvent documentEvent){ + ItemCollection document=documentEvent.getDocument(); + System.out.println("Received DocumentEvent Type = " + documentEvent.getType()); } +} ``` In both event types, an observer client can change the data of the document. \ No newline at end of file diff --git a/src/site/markdown/engine/index.md b/src/site/markdown/engine/index.md index 2fcd84aaa..a6a93e073 100644 --- a/src/site/markdown/engine/index.md +++ b/src/site/markdown/engine/index.md @@ -16,10 +16,10 @@ Further more, all services are subject to the [Imixs-Workflow Security Model](./ The `WorkflowService` is the core service to create, update and read a process instance. To create a process instance a workitem is assigned to a BPMN 2.0 model definition managed by the `ModelService`. ```java - @Inject - WorkflowService workflowService; - ItemCollection workitem=new ItemCollection().model("1.0.0").task(100).event(10); - workitem=workflowService.processWorkItem(workitem); +@Inject +WorkflowService workflowService; +ItemCollection workitem=new ItemCollection().model("1.0.0").task(100).event(10); +workitem=workflowService.processWorkItem(workitem); ``` Read more about in the section [Imixs WorkflowService](../engine/workflowservice.html). @@ -29,18 +29,18 @@ The `DocumentService` is the general persistence layer of the Imixs-Workflow eng The `DocumentService` is independent from the workflow engine and can not only be used to persist a process instance (`workitem`), but also any other kind of business data, not necessarily associated with the workflow engine (e.g configuration data). ```java - @Inject - DocumentService documentService; - ItemCollection myDocument=new ItemCollection; - myDocument.setItemValue("type","product"); - myDocument.setItemValue("name","coffee"); - myDocument=documentService.save(myDocument); +@Inject +DocumentService documentService; +ItemCollection myDocument=new ItemCollection; +myDocument.setItemValue("type","product"); +myDocument.setItemValue("name","coffee"); +myDocument=documentService.save(myDocument); ``` The `DocumentService` provides also a [Full-Text-Search](./luceneservice.html). In this way documents can be accessed through a search query: ```java - List result=documentService.find("(type:'workitem')(imixs*)"); +List result=documentService.find("(type:'workitem')(imixs*)"); ``` Read more about in the section [DocumentService](../engine/documentservice.html). @@ -49,25 +49,25 @@ Read more about in the section [DocumentService](../engine/documentservice.html) The _ModelService_ provides methods to manage BPMN model definitions. A model can be created with the Eclipse based modeling tool [Imixs-BPMN](../modelling/index.html). ```java - @Inject - ModelService modelService; - InputStream inputStream = new FileInputStream(new File("ticket.bpmn")); - ticketModel = BPMNParser.parseModel(inputStream, "UTF-8"); - modelService.addModel(model); +@Inject +ModelService modelService; +InputStream inputStream = new FileInputStream(new File("ticket.bpmn")); +ticketModel = BPMNParser.parseModel(inputStream, "UTF-8"); +modelService.addModel(model); ``` The `ModelService` is used internally by the `WorkflowService` but can also be used by your application to navigate through a model definition. ```java - @Inject - ModelService modelService; - Model ticketModel = modelService.getModel("ticket-1.0.0"); - List tasks = modelService.findAllTasks(); +@Inject +ModelService modelService; +Model ticketModel = modelService.getModel("ticket-1.0.0"); +List tasks = modelService.findAllTasks(); ``` Read more about in the section [ModelService](../engine/modelservice.html). ### The ReportService -The _ReportService_ component supports methods to create, find and execute business reports created with the Eclipse based [Imixs-Workflow Modeler](../modelling/index.html). A report is used to generate aggregated information from data objects managed by the `DocumentService`. +The `ReportService` component supports methods to create, find and execute business reports created with the Eclipse based [Imixs-Workflow Modeler](../modelling/index.html). A report is used to generate aggregated information from data objects managed by the `DocumentService`. diff --git a/src/site/markdown/engine/modelservice.md b/src/site/markdown/engine/modelservice.md index 50b59fc60..b40de0637 100644 --- a/src/site/markdown/engine/modelservice.md +++ b/src/site/markdown/engine/modelservice.md @@ -38,17 +38,17 @@ If no modelversion is provided by a workitem but the $workflowgroup matches a mo The ModelService provides a method to add a BPMNModel object. This object can be created from a file. See the following example: ```java - @Inject - ModelService modelService; - InputStream inputStream = new FileInputStream(new File("ticket.bpmn")); - ticketModel = BPMNParser.parseModel(inputStream, "UTF-8"); - modelService.addModel(model); +@Inject +ModelService modelService; +InputStream inputStream = new FileInputStream(new File("ticket.bpmn")); +ticketModel = BPMNParser.parseModel(inputStream, "UTF-8"); +modelService.addModel(model); ``` You can also persist the model into the data storage ```java - modelService.save(ticketModel,"ticket.bpmn"); +modelService.save(ticketModel,"ticket.bpmn"); ``` A persisted model will be automatically loaded when the workflow service starts. diff --git a/src/site/markdown/engine/plugins/howto_extend.md b/src/site/markdown/engine/plugins/howto_extend.md index 2e35c37fe..6f6d41478 100644 --- a/src/site/markdown/engine/plugins/howto_extend.md +++ b/src/site/markdown/engine/plugins/howto_extend.md @@ -7,23 +7,23 @@ The **Imixs Plugin-API** is the extension concept of the Imixs-Workflow Engine. Most plugins provided by the Imixs-Workflow engine are extending the AbstractPlugin class. This class provides a set of convenient methods to access the Imixs-Workflow environment and processing logic. For custom implementation this is a good starting point to subclass from the class: ```java - public class MyPlugin extends AbstractPlugin { +public class MyPlugin extends AbstractPlugin { + + @Override + public void init(WorkflowContext actx) throws PluginException { + // setup ... + } - @Override - public void init(WorkflowContext actx) throws PluginException { - // setup ... - } - - @Override - public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException { - // your code goes here... - } - - @Override - public void close(boolean rollbackTransaction) throws PluginException { - // tear down... - } + @Override + public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException { + // your code goes here... } + + @Override + public void close(boolean rollbackTransaction) throws PluginException { + // tear down... + } +} ``` Read more about the Imixs Plugin-API in the section [core concepts](../../core/plugin-api.html). @@ -43,27 +43,27 @@ This abstract plugin class provides a set of helper methods: Imixs-Workflow supports CDI for the plugin API. So an EJB or Resource can be injected into a plugin class by the corresponding annotation. See the following example: ```java - public class DemoPlugin extends AbstractPlugin { - // inject services... - @Inject - ModelService modelService; - ... - } +public class DemoPlugin extends AbstractPlugin { + // inject services... + @Inject + ModelService modelService; + ... +} ``` ## How to lookup a JDBC Resource from a plugin A plugin class can also lookup an existing JDBC Resource via a jndi lookup, for example to query a database using SQL statements. The same principle explained in this section is applicable to all resources (such as JMS destinations, JavaMail sessions, Remote EJBs and so on). The resource-ref element in the ejb-jar.xml deployment descriptor file maps the JNDI name of a resource reference to the resource-ref element in the ejb-jar.xml deployment descriptor file. This is similar to a EJB lookup explained before. The resource lookup in the plugin code looks like this: ```java - public void init(WorkflowContext actx) throws Exception { - super.init(actx); - InitialContext ic = new InitialContext(); - String dsName = "java:comp/env/jdbc/HelloDbDs"; - DataSource ds = (javax.sql.DataSource)ic.lookup(dsName); - Connection connection = ds.getConnection(); - .... - ..... - } +public void init(WorkflowContext actx) throws Exception { + super.init(actx); + InitialContext ic = new InitialContext(); + String dsName = "java:comp/env/jdbc/HelloDbDs"; + DataSource ds = (javax.sql.DataSource)ic.lookup(dsName); + Connection connection = ds.getConnection(); + .... + ..... +} ``` The resource being queried is listed in the res-ref-name element of the ejb-jar.xml file as follows: diff --git a/src/site/markdown/engine/remote_lookup.md b/src/site/markdown/engine/remote_lookup.md index 88d5695aa..1b5229548 100644 --- a/src/site/markdown/engine/remote_lookup.md +++ b/src/site/markdown/engine/remote_lookup.md @@ -4,12 +4,12 @@ Imixs-Workflow supports CDI for all service components which makes it easy to ti For example an bean or a Resource can be easily injected into a plugin class by the corresponding annotation. See the following example injecting the `ModelService`: ```java - public class DemoPlugin extends AbstractPlugin { - // inject services... - @Inject - ModelService modelService; - ... - } +public class DemoPlugin extends AbstractPlugin { + // inject services... + @Inject + ModelService modelService; + ... +} ``` # EJB JNDI Lookup @@ -18,15 +18,15 @@ In some situations where CDI does not work, it can be necessary to fetch a Servi The following Example shows a JNDI Lookup for an external Service EJB from the WorkflowService: ```java - MyServiceBean myService; - try { - String ejbName="ejb/MyServiceBean"; - InitialContext ic = new InitialContext(); - myService = (MyServiceBean) ic.lookup(ejbName); - } catch (Exception e) { - e.printStackTrace(); - workflowService = null; - } +MyServiceBean myService; +try { + String ejbName="ejb/MyServiceBean"; + InitialContext ic = new InitialContext(); + myService = (MyServiceBean) ic.lookup(ejbName); +} catch (Exception e) { + e.printStackTrace(); + workflowService = null; +} ``` The JNDI Name is defined by the application server. To lookup a EJB or resource by JNDI name, the name need to be configured in ejb-jar.xml. The following example shows the configuration for wildfly: diff --git a/src/site/markdown/engine/scheduler.md b/src/site/markdown/engine/scheduler.md index 69d8d229d..4e03e15a7 100644 --- a/src/site/markdown/engine/scheduler.md +++ b/src/site/markdown/engine/scheduler.md @@ -16,21 +16,21 @@ The SchedulerService will automatically call the concrete scheduler implementati ```java - public class MyScheduler implements Scheduler { - ... - @Inject - WorkflowService workflowService; - - public ItemCollection run(ItemCollection configuration) throws SchedulerException { - - try { - // do the job... - ..... - } catch (Exception e) { - // set item _schduler_enabled to false to cancel the timer. - configuration.setItemValue("scheduler_enabled",false); - } - return configuration; +public class MyScheduler implements Scheduler { + ... + @Inject + WorkflowService workflowService; + + public ItemCollection run(ItemCollection configuration) throws SchedulerException { + + try { + // do the job... + ..... + } catch (Exception e) { + // set item _schduler_enabled to false to cancel the timer. + configuration.setItemValue("scheduler_enabled",false); } - } + return configuration; + } +} ``` diff --git a/src/site/markdown/engine/workflowscheduler.md b/src/site/markdown/engine/workflowscheduler.md index 8e626b282..f645ad3d6 100644 --- a/src/site/markdown/engine/workflowscheduler.md +++ b/src/site/markdown/engine/workflowscheduler.md @@ -51,17 +51,19 @@ A timer configuration can be created with the following item definitions: The Scheduler configuration object can also be created by the *WorkflowSchedulerController* bean: - @Inject - WorkflowSchedulerController workflowSchedulerController; - - public void setup() { - ItemCollection config=workflowSchedulerController.getConfiguration(); - config.setItemValue("_scheduler_definition", "hour=*"); - config.appendItemValue("_scheduler_definition", "minute=/5"); - workflowSchedulerController.setConfiguration(config); - workflowSchedulerController.saveConfiguration(); - workflowSchedulerController.startScheduler(); - } +```java +@Inject +WorkflowSchedulerController workflowSchedulerController; + +public void setup() { + ItemCollection config=workflowSchedulerController.getConfiguration(); + config.setItemValue("_scheduler_definition", "hour=*"); + config.appendItemValue("_scheduler_definition", "minute=/5"); + workflowSchedulerController.setConfiguration(config); + workflowSchedulerController.saveConfiguration(); + workflowSchedulerController.startScheduler(); +} +``` With the method call startScheduler() the workflow scheduler will be started. diff --git a/src/site/markdown/engine/workflowservice.md b/src/site/markdown/engine/workflowservice.md index aec710fc2..3cdecd20c 100644 --- a/src/site/markdown/engine/workflowservice.md +++ b/src/site/markdown/engine/workflowservice.md @@ -1,9 +1,9 @@ # The WorkflowService -The WorkflowService is the Java EE implementation of the [WorkflowManager interface](../core/workflowmanager.html) from the core API. This service component allows to process, update and lookup workItems in the Imixs-Workflow engine. +The `WorkflowService` is the Jakarta EE implementation of the [WorkflowManager interface](../core/workflowmanager.html) from the core API. This is the central service component that allows you to process, update and lookup workItems. ## How to Process a Workitem -Before a workitem can be processed by the WorkflowService, a process model need to be defined and deployed together with the workflow engine. See the section [Imixs-BPMN Modeler](../modelling/index.html) for details about how to create a model and upload it into the workflow server. The following example shows how a workitem can be processed using the WorkflowService component. A workitem must provide at least the following properties: +Before a workitem can be processed by the `WorkflowService`, a process model need to be defined and deployed together with the workflow engine. See the section [Imixs-BPMN Modeler](../modelling/index.html) for details about how to create a model and upload it into the workflow server. A workitem must provide at least the following properties: * $ModelVersion * $TaskID @@ -11,40 +11,44 @@ Before a workitem can be processed by the WorkflowService, a process model need These properties are defining the workflow activity which should be processed by the workflowManager. +The following example shows how a new workitem can be creaetd and processed by injecting the `WorkflowService` component: + ```java - @Inject - WorkflowService workflowService; - //... - // create an empty workitem assigend to a model - ItemCollection workitem=new ItemCollection().model("1.0.0").task(100).event(10); - // assign business data - workitem.setItemValue("_name", "M. Alex"); - workitem.setItemValue("_Titel", "My first workflow example"); - - // process the workitem - workitem=workflowService.processWorkItem(workitem); +@Inject +WorkflowService workflowService; +//... +// create an empty workitem assigend to a model +ItemCollection workitem=new ItemCollection().model("1.0.0").task(100).event(10); +// assign business data +workitem.setItemValue("_name", "M. Alex"); +workitem.setItemValue("_Titel", "My first workflow example"); + +// process the workitem +workitem=workflowService.processWorkItem(workitem); ``` +The `WorkflowService` will automatically persist the workitem into the database and controls the status for future access. -The model version can also be specified as a regex. +The model version of a new WorkItem can either be specified by it's model version or as a regular expression: ```java - // take best match for model version 1.x - ItemCollection workitem=new ItemCollection().model("(^1.)").task(100).event(10); +// take best match for model version 1.x +ItemCollection workitem=new ItemCollection().model("(^1.)").task(100).event(10); ``` -Another alternative to assign a new workitem with a model version is by specifying the $workflowgroup. + +Another alternative to assign a new workitem with a model version is by specifying the `$workflowgroup`: ```java - // create an empty workitem assigend to a workflow group - ItemCollection workitem=new ItemCollection().task(100).event(10); - // assign group - workitem.setItemValue(WorkflowKernel.WORKFLOWGROUP, "Invoice"); - // assign the workitem to the latest version matching the workfow group 'invoice' - workitem=workflowService.processWorkItem(workitem); +// create an empty workitem assigend to a workflow group +ItemCollection workitem=new ItemCollection().task(100).event(10); +// assign group +workitem.setItemValue(WorkflowKernel.WORKFLOWGROUP, "Invoice"); +// assign the workitem to the latest version matching the workfow group 'invoice' +workitem=workflowService.processWorkItem(workitem); ``` -After a new workitem is process the first time, it is under the control of the _WorkflowService_. +The `WorkflowService` will automatically assign the first matching model version holding the given workflow group. ## Worklist Methods @@ -57,19 +61,19 @@ To get the current list of all workitems, the _WorkflowService_ provides a set o The method getWorkListByCreator can be called to read the list of all workitems created by a specific user: ```java - @Inject - org.imixs.workflow.jee.ejb.WorkflowService workflowService; - // get the first 10 workitem for the current user - Collection worklist=workflowService.getWorkListByCreator(null,10,0); - // get list for a named user - Collection worklist=workflowService.getWorkListByCreator('manfred',10,0); +@Inject +org.imixs.workflow.jee.ejb.WorkflowService workflowService; +// get the first 10 workitem for the current user +Collection worklist=workflowService.getWorkListByCreator(null,10,0); +// get list for a named user +Collection worklist=workflowService.getWorkListByCreator('manfred',10,0); ``` The WorkflowManager provides a paging mechanism to browse through long result-sets. The following example shows how to get 5 workitems from the tenth page ```java - Collection worklist=workflowService.getWorkListByCreator(null,5,10); +Collection worklist=workflowService.getWorkListByCreator(null,5,10); ``` @@ -77,18 +81,18 @@ shows how to get 5 workitems from the tenth page The method returns a collection of workitems for the current user. A Workitem belongs to a user or role if the user has at least read write access to this workitem. ```java - Collection list=workflowService.getWorkList(); - //... +Collection list=workflowService.getWorkList(); +//... ``` You can specify the type, the start position, the count and sort order of workitems returned by this method. The type of a workitem is defined by the workitem property 'type' which can be set before a workitem is processed. ```java - String type="workitem"; - Collection list=workflowService.getWorkList(0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +Collection list=workflowService.getWorkList(0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByAuthor @@ -98,11 +102,11 @@ The method returns a collection of workitems belonging to a specified user. This processed by the user. ```java - String type="workitem"; - String user="manfred" - Collection list=workflowService.getWorkList(user,0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +String user="manfred" +Collection list=workflowService.getWorkList(user,0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByGroup @@ -111,11 +115,11 @@ The method returns a collection of workitems belonging to a specified workflow g a business process ```java - String type="workitem"; - String group="Ticketservice"; - Collection list=workflowService.getWorkListByGroup(group,0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +String group="Ticketservice"; +Collection list=workflowService.getWorkListByGroup(group,0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByProcessID @@ -123,10 +127,10 @@ The method returns a collection of workitems belonging to a specified workflow g The method returns a collection of workitems belonging to a specified $processID defined by the workflow model. ```java - String type="workitem"; - Collection list=workflowService.getWorkListByProcessID(2100,0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +Collection list=workflowService.getWorkListByProcessID(2100,0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByOwner @@ -134,11 +138,11 @@ The method returns a collection of workitems belonging to a specified $processID The method returns a collection of workitems containing a '$owner' item belonging to a specified username. The '$owner' item is typical controlled by the OwnerPlugin using the Imixs Workflow Modeler ```java - String type="workitem"; - String user="Manfred" - Collection list=workflowService.getWorkListByOwner(user,0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +String user="Manfred" +Collection list=workflowService.getWorkListByOwner(user,0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByWriteAccess @@ -146,10 +150,10 @@ The method returns a collection of workitems containing a '$owner' item belongin The method returns a collection of workitems where the current user has at least writeAccess. This means the either the username or one of the user roles is contained in the $writeaccess property of each workitem returned by the method. ```java - String type="workitem"; - Collection list=workflowService.getWorkListByWriteAccess(0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +Collection list=workflowService.getWorkListByWriteAccess(0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ### getWorkListByRef @@ -157,10 +161,10 @@ The method returns a collection of workitems where the current user has at least The method returns a collection of workitems belonging to a specified workitem identified by the attribute $UniqueIDRef. ```java - String type="workitem"; - Collection list=workflowService.getWorkListByRef(refID,0,-1, - type,WorkflowService.SORT_ORDER_CREATED_DESC); - //... +String type="workitem"; +Collection list=workflowService.getWorkListByRef(refID,0,-1, + type,WorkflowService.SORT_ORDER_CREATED_DESC); +//... ``` ## Model Version Management @@ -186,13 +190,13 @@ The class `ProcessingEvent` defines the following event types: This event can be consumed by another Session Bean or managed bean implementing the @Observes annotation: ```java - @Stateless - public class WorkflowServiceListener { - public void onEvent(@Observes ProcessingEvent processingEvent){ - ItemCollection workitem=processingEvent.getDocument(); - System.out.println("Received ProcessingEvent Type = " + processingEvent.getType()); - } +@Stateless +public class WorkflowServiceListener { + public void onEvent(@Observes ProcessingEvent processingEvent){ + ItemCollection workitem=processingEvent.getDocument(); + System.out.println("Received ProcessingEvent Type = " + processingEvent.getType()); } +} ``` ## Evaluate the Next Task Element @@ -203,7 +207,7 @@ The method supports 'conditional-events' as well as 'split-events'. A condition ```java - // get next process entity - nextTask = workflowService.evalNextTask(adocumentContext, adocumentActivity); +// get next process entity +nextTask = workflowService.evalNextTask(adocumentContext, adocumentActivity); ``` diff --git a/src/site/markdown/modelling/dataobject.md b/src/site/markdown/modelling/dataobject.md index 8a99201d6..b8058b6f9 100644 --- a/src/site/markdown/modelling/dataobject.md +++ b/src/site/markdown/modelling/dataobject.md @@ -16,16 +16,16 @@ Plugins or Adapter classes can access the data object by the ModelService: ### Plug-In Example: ```java - public class MyPlugin implements Plugin { - @Inject - ModelService modelService; - - public ItemCollection run(ItemCollection workitem, ItemCollection event) throws Exception { - // extract the data from a DataObject - String data = modelService.getDataObject(event, "MyObject"); - .... - } +public class MyPlugin implements Plugin { + @Inject + ModelService modelService; + + public ItemCollection run(ItemCollection workitem, ItemCollection event) throws Exception { + // extract the data from a DataObject + String data = modelService.getDataObject(event, "MyObject"); + .... } +} ``` This example plug-in code extracts the Data stored in a BPMN Data Object with the name 'MyObject' associated to an Event Element. The method 'getDataObject' returns null if no DataObject with the given name is associated with the event element. @@ -34,19 +34,19 @@ This example plug-in code extracts the Data stored in a BPMN Data Object with th ### Adapter Example: ```java - public class DemoAdapter implements org.imixs.workflow.SignalAdapter { - // inject services... - @Inject - ModelService modelService; - ... - @Override - public ItemCollection execute(ItemCollection document, ItemCollection event) throws AdapterException { - ... - // extract the data from a DataObject - String data = modelService.getDataObject(event, "MyObject"); - .... - } +public class DemoAdapter implements org.imixs.workflow.SignalAdapter { + // inject services... + @Inject + ModelService modelService; + ... + @Override + public ItemCollection execute(ItemCollection document, ItemCollection event) throws AdapterException { + ... + // extract the data from a DataObject + String data = modelService.getDataObject(event, "MyObject"); + .... } +} ``` This adapter example extracts the Data stored in a BPMN Data Object with the name 'MyObject' associated to an Event Element. The method 'getDataObject' returns null if no DataObject with the given name is associated with the event element. @@ -67,22 +67,22 @@ Data Object can be either associated with a Event or a Task element. To get the As an alternative you can access the DataObject directly from the Open-BPMN model instance. See the following example: ```java - public class DemoAdapter implements org.imixs.workflow.SignalAdapter { - // inject services... - @Inject - ModelService modelService; - ... - public ItemCollection execute(ItemCollection workitem, ItemCollection event) throws AdapterException { - ... - // fetch DataObjects from BPMN model - BPMNElementNode bpmnElementNode = modelService.getBPMNElementNode(workitem.getModelVersion(), - event.getItemValueString("id")); - - Assert.assertNotNull(bpmnElementNode); - Set dataObjects = bpmnElementNode.getDataObjects(); - // extract the data from a DataObject - .... - } +public class DemoAdapter implements org.imixs.workflow.SignalAdapter { + // inject services... + @Inject + ModelService modelService; + ... + public ItemCollection execute(ItemCollection workitem, ItemCollection event) throws AdapterException { + ... + // fetch DataObjects from BPMN model + BPMNElementNode bpmnElementNode = modelService.getBPMNElementNode(workitem.getModelVersion(), + event.getItemValueString("id")); + + Assert.assertNotNull(bpmnElementNode); + Set dataObjects = bpmnElementNode.getDataObjects(); + // extract the data from a DataObject + .... } +} ``` \ No newline at end of file diff --git a/src/site/markdown/modelling/deployment.md b/src/site/markdown/modelling/deployment.md index 9ba6be202..53ad283ac 100644 --- a/src/site/markdown/modelling/deployment.md +++ b/src/site/markdown/modelling/deployment.md @@ -38,22 +38,22 @@ To delete a specific model version the Imxis-Rest API provides a DELETE command You can also use the Imixs ModelService to deploy a BPMN model programmatically. In this case you call the Model Service EJB form your application to deploy a model. The following example demonstrates the API call: ```java - import org.imixs.workflow.bpmn.BPMNModel; - import org.imixs.workflow.bpmn.BPMNParser; - import org.imixs.workflow.jee.ejb.ModelService; - .... - - @Inject - protected ModelService modelService; - - ..... - // open a inputStream of the model file - InputStream inputStream = getClass().getResourceAsStream( - "/bpmn/ticket.bpmn"); - // parse and import the model.... - BPMNModel model = BPMNParser.parseModel(file.getData(), "UTF-8"); - modelService.importBPMNModel(model); - ... +import org.imixs.workflow.bpmn.BPMNModel; +import org.imixs.workflow.bpmn.BPMNParser; +import org.imixs.workflow.jee.ejb.ModelService; +.... + +@Inject +protected ModelService modelService; + +..... +// open a inputStream of the model file +InputStream inputStream = getClass().getResourceAsStream( + "/bpmn/ticket.bpmn"); +// parse and import the model.... +BPMNModel model = BPMNParser.parseModel(file.getData(), "UTF-8"); +modelService.importBPMNModel(model); +... ``` You can find more information about the Imixs-Workflow services in the [section Imixs-Workflow Engine](../engine/index.html). diff --git a/src/site/markdown/quickstart.md b/src/site/markdown/quickstart.md index e99095917..78a9d395c 100644 --- a/src/site/markdown/quickstart.md +++ b/src/site/markdown/quickstart.md @@ -58,15 +58,15 @@ From you code you can access the Imixs-Workflow engine by injection. Let's see what this looks like in your Java code: ```java - @Inject - private WorkflowService workflowService; - - ItemCollection workitem=new ItemCollection().model("1.0.0").task(1000).event(10); - // assign some business data... - workitem.setItemValue("_customer","M. Melman"); - workitem.setItemValue("_ordernumber",20051234); - // process the workitem - workitem = workflowService.processWorkItem(workitem); +@Inject +private WorkflowService workflowService; + +ItemCollection workitem=new ItemCollection().model("1.0.0").task(1000).event(10); +// assign some business data... +workitem.setItemValue("_customer","M. Melman"); +workitem.setItemValue("_ordernumber",20051234); +// process the workitem +workitem = workflowService.processWorkItem(workitem); ``` 1. You inject the Workflow Engine with the annotation @Inject. @@ -78,18 +78,18 @@ From now on the newly created **Process Instance** is under the control of your After you have created a new process instance you can use the _UniqueID_ to access the instance later: ```java - String uniqueID=workitem.getUnqiueID(); - .... - // load the instance - ItemCollection workitem=workflowService.getWorkItem(unqiueID); - .... +String uniqueID=workitem.getUnqiueID(); +.... +// load the instance +ItemCollection workitem=workflowService.getWorkItem(unqiueID); +.... ``` Depending on the design of your workflow model a process instance can be assigned to a team or a single process participant. E.g. the method _getWorkListByOwner_ can be used to select all process instances belonging to a specified participant: ```java - List result=workflowService.getWorkListByOwner("melman", "workitem", 30, 0,null,false); +List result=workflowService.getWorkListByOwner("melman", "workitem", 30, 0,null,false); ``` See the documentation of the [WorkflowService](engine/workflowservice.html) for more details. diff --git a/src/site/markdown/testing.md b/src/site/markdown/testing.md index 56bd1c15e..72de71fc0 100644 --- a/src/site/markdown/testing.md +++ b/src/site/markdown/testing.md @@ -8,12 +8,12 @@ The `WorkflowService` provides a method called `evalNextTask`. This method evalu ```java - try { - // simulate the processing life cycle of a given workitem - ItemCollection nextTaskEnity = workflowService.evalNextTask(workitem); - } catch (ModelException e) { - throw new PluginException(DocumentComposerPlugin.class.getSimpleName(), e.getErrorCode(), e.getMessage()); - } +try { + // simulate the processing life cycle of a given workitem + ItemCollection nextTaskEnity = workflowService.evalNextTask(workitem); +} catch (ModelException e) { + throw new PluginException(DocumentComposerPlugin.class.getSimpleName(), e.getErrorCode(), e.getMessage()); +} ``` **Note:** During the evaluation life-cycle more than one events can be evaluated. This depends on the model definition which can define follow-up-events, split-events and conditional events. The `evalNextTask` method did not persist the process instance or execute any plugin or adapter classes. @@ -93,12 +93,12 @@ public class TestTemplate { To setup a test case the Imixs `WorkflowMockEnvironment` provides a setup method to initialize the environment and a loadBPMNModel method to load a test model. To setup the environment it is recommended to call the setup() method in a `org.junit.jupiter.api.BeforeEach` annotated init method: ```java - @BeforeEach - public void setUp() throws PluginException, ModelException { - workflowEnvironment = new WorkflowMockEnvironment(); - workflowEnvironment.setUp(); - workflowEnvironment.loadBPMNModel("/bpmn/TestWorkflowService.bpmn"); - } +@BeforeEach +public void setUp() throws PluginException, ModelException { + workflowEnvironment = new WorkflowMockEnvironment(); + workflowEnvironment.setUp(); + workflowEnvironment.loadBPMNModel("/bpmn/TestWorkflowService.bpmn"); +} ``` @@ -106,16 +106,16 @@ To setup a test case the Imixs `WorkflowMockEnvironment` provides a setup meth The main goal of the `WorkflowMockEnvironment` is to test business logic of a specific workflow model. A workflow instance can be created form a empty ItemCollection and tested with any kind of data. ```java - // Load a test model - workflowEnvironment.loadBPMNModel("/bpmn/myModel.bpmn"); - // Create a workflow instance with some business data - ItemCollection workitem = new ItemCollection(); - workitem.replaceItemValue("_budget", 99); - // process the workflow instance.... - workitem.model("1.0.0").task(1000).event(10); - workitem = workflowEnvironment.workflowService.processWorkItem(workitem); - // evaluate the results.... - Assert.assertEquals(1200, workitem.getTaskID()); +// Load a test model +workflowEnvironment.loadBPMNModel("/bpmn/myModel.bpmn"); +// Create a workflow instance with some business data +ItemCollection workitem = new ItemCollection(); +workitem.replaceItemValue("_budget", 99); +// process the workflow instance.... +workitem.model("1.0.0").task(1000).event(10); +workitem = workflowEnvironment.workflowService.processWorkItem(workitem); +// evaluate the results.... +Assert.assertEquals(1200, workitem.getTaskID()); ``` diff --git a/src/site/markdown/webtools/resourcebundle.md b/src/site/markdown/webtools/resourcebundle.md index e91539ec0..fb123a996 100644 --- a/src/site/markdown/webtools/resourcebundle.md +++ b/src/site/markdown/webtools/resourcebundle.md @@ -17,11 +17,12 @@ The class searches for the resource bundles with the base names '*bundle.message In a CDI bean you can also use the resourceBundleHandler to lookup keys - @Inject - protected ResourceBundleHandler resourceBundleHandler = null; - ... - resourceBundleHandler.findMessage("space.manager")); - +```java +@Inject +protected ResourceBundleHandler resourceBundleHandler = null; +... +resourceBundleHandler.findMessage("space.manager")); +``` ## Priority diff --git a/src/site/site.xml b/src/site/site.xml index 379fdb0ee..bf34747c9 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -61,7 +61,6 @@ -