Wait Program Intermediate Event

image0 The Wait Program Intermediate Event element is located in the Event & Gateway drawer of the process editor palette.

Element Details

This element is one of Axon Ivy facilities to integrate custom-made software, legacy systems, proprietary applications or any other external system through an Axon Ivy Java interface. At an Intermediate Event element the process execution is interrupted and waits for an external event to occur. Technically spoken the current task will be ended and a new system task is created that waits for the intermediate event. If the intermediate event is fired the new task and therefore the process after the intermediate event will be executed.

Inscription

Name Tab

The Name Tab is included in the mask of all process elements and contains the name and a description of the element.

Event Tab

On this tab you define the Java class that the IntermediateEvent should instantiate, the identifier of the event, and the timeout behavior.

image2

Java Class

Fully qualified name of the Java class that implements the IProcessIntermediateEventBean interface. Use the New Bean Class Wizard image3 to create a new Java source file with an example implementation of the bean class.

Event ID

Because multiple cases (process instances) can wait on the same intermediate event you must specify which event belongs to which waiting case. Here, you specify the identifier of the event the current case should wait for.

Warning

The event identifier as a String must be unique. Do not use a static string like "myID". A good practice is to integrate the case identifier (ivy.case.getId()) into the event id.

Timeout

You can specify how long the current case should wait for an intermediate event, and what will happen if no event has been received after this time. You may optionally start an exception process, delete the waiting task, or continue the waiting task without receiving an intermediate event.

Editor Tab

The custom editor UI provided by the implementation of IProcessIntermediateEventBean allows to configure its execution.

Editor Tab

A custom editor example

Task Tab

On this tab you configure the task which is created when this element is executed by the awaited event. This task will not appear in any user task list and is exclusively handled by the system. The values on this tab are therefore only relevant for analyzing the finished tasks and not for the task list itself.

../../../_images/waitIntermediateEvent_taskTab.png
Custom fields

The values set on this table are only informational and have no effect on how this task is treated by Axon Ivy. See Custom Fields.

Code

This is a post construct code block for the Task that is defined in this tab. The created Task is provided as variable called task. See Code.

Output Tab

On Output Tab you can configure the output of the element (i.e. the data that leaves the element).

Implementation

To initiate a custom bean implementation for your third party system, you start most conveniently by using the New Class image3 button on the Event Tab. The wizard will create a minimal sample implementation that works already. You can then adjust it to your needs.

API reference

The Intermediate Event consumes a Java class that implements the IProcessIntermediateEventBean interface. This implementation is responsible to continue the process by calling the method fireProcessIntermediateEventEx of IProcessIntermediateEventBeanRuntime. The common way to implement an Intermediate Event Bean is to extend from AbstractProcessIntermediateEventBean.

If you use an Axon Ivy Cluster, you may mark your implementation with the IMultiNodeCapable interface. This will enable your Intermediate Event to be processed not only on the master node, but on all available nodes.

Custom configuration

Very likely your Intermediate Event implementation will accept configuration parameters defining the local environment. For instance, a system specific file path to look for files being produced by a legacy system.

We help you with these configurations by providing an accessor for static element configuration via getConfiguration().

Custom editor

To define your custom configuration on the process inscription mask, you must supply an inner Editor class implementation. We recommend to extend your implementation from UiEditorExtension.

This editor class is responsible for two things: Firstly, to create UI widgets, which display configuration values. And secondly, to map configuration data onto these widgets:

1. The initUiFields method supports you in creating widgets for the editor. Currently labels, scriptEditors and textEditors are supported.

2. The ConfigurableExtensionEditor provides methods to read and write configurations, in order to bind them to previously created ui widgets.

Example implementation

 1package com.axonivy.wf.custom;
 2
 3import java.io.File;
 4import java.io.IOException;
 5import java.nio.file.Files;
 6import java.nio.file.Path;
 7import java.util.List;
 8import java.util.Properties;
 9import java.util.concurrent.TimeUnit;
10import java.util.stream.Collectors;
11import java.util.stream.Stream;
12
13import org.apache.commons.lang3.StringUtils;
14
15import ch.ivyteam.ivy.persistence.PersistencyException;
16import ch.ivyteam.ivy.process.extension.ui.ExtensionUiBuilder;
17import ch.ivyteam.ivy.process.extension.ui.IUiFieldEditor;
18import ch.ivyteam.ivy.process.extension.ui.UiEditorExtension;
19import ch.ivyteam.ivy.process.intermediateevent.AbstractProcessIntermediateEventBean;
20import ch.ivyteam.util.PropertiesUtil;
21
22public class ErpPrintJob extends AbstractProcessIntermediateEventBean {
23
24  public ErpPrintJob() {
25    super("ErpPrintJob", "Waits for ERP reports", File.class);
26  }
27
28  @Override
29  public void poll() {
30    Properties configs = PropertiesUtil.createProperties(getConfiguration());
31    int seconds = Integer.parseInt(configs.getProperty(Config.INTERVAL, "60"));
32    getEventBeanRuntime().setPollTimeInterval(TimeUnit.SECONDS.toMillis(seconds));
33
34    String path = configs.getProperty(Config.PATH, "");
35    try (Stream<Path> csv = Files.list(Path.of(path)).filter(f -> f.startsWith("erp-print"))) {
36      List<Path> reports = csv.collect(Collectors.toList());
37      for(Path report : reports) {
38        String fileName = report.getFileName().toString();
39        String eventId = StringUtils.substringBefore(fileName, ".pdf");
40        continueProcess(report.toFile(), eventId);
41      }
42    } catch (IOException ex) {
43      getEventBeanRuntime().getRuntimeLogLogger().error("Failed to check ERP for updates", ex);
44    }
45  }
46
47  private void continueProcess(File report, String eventId) {
48    try {
49      getEventBeanRuntime().fireProcessIntermediateEventEx(eventId, report, "");
50    } catch (PersistencyException ex) {
51      getEventBeanRuntime().getRuntimeLogLogger().error("Failed to resume process with event"+ eventId, ex);
52    }
53  }
54
55  public static class Editor extends UiEditorExtension {
56
57    private IUiFieldEditor path;
58    private IUiFieldEditor interval;
59
60    @Override
61    public void initUiFields(ExtensionUiBuilder ui) {
62      ui.label("Path to read produced PDF files from:").create();
63      path = ui.textField().create();
64
65      ui.label("Interval in seconds to check for changes:").create();
66      interval = ui.scriptField().requireType(Integer.class).create();
67    }
68
69    @Override
70    protected void loadUiDataFromConfiguration() {
71      path.setText(getBeanConfigurationProperty(Config.PATH));
72      interval.setText(getBeanConfigurationProperty(Config.INTERVAL));
73    }
74
75    @Override
76    protected boolean saveUiDataToConfiguration() {
77      clearBeanConfiguration();
78      setBeanConfigurationProperty(Config.PATH, path.getText());
79      setBeanConfigurationProperty(Config.INTERVAL, interval.getText());
80      return true;
81    }
82  }
83
84  private interface Config {
85    String PATH = "path";
86    String INTERVAL = "interval";
87  }
88
89}