Hi Lukas ,
I threw together a quick demo on how an implementation using system events could look like.
Implement an AbstractProcessStartEventBean you can use with a Program Start element. The start event bean creates and registers an ISystemEventListener which starts the process whenever the system event is triggered.
The SystemEvent instance received by the listener comes with parameters you can pass to the process as needed. For example, a system event of type WorkflowSystemEvent#TASK_CREATED provides the task IDs of the tasks created that triggered the event. You can use them to get and manipulate the tasks, for example.
package system.events.demo;
import java.util.EnumSet;
import java.util.List;
import ch.ivyteam.ivy.event.ISystemEventListener;
import ch.ivyteam.ivy.event.SystemEvent;
import ch.ivyteam.ivy.event.SystemEventCategory;
import ch.ivyteam.ivy.process.eventstart.AbstractProcessStartEventBean;
import ch.ivyteam.ivy.process.eventstart.IProcessStartEventBeanRuntime;
import ch.ivyteam.ivy.process.extension.ProgramConfig;
import ch.ivyteam.ivy.service.ServiceException;
import ch.ivyteam.ivy.workflow.WorkflowSystemEvent;
import ch.ivyteam.ivy.workflow.WorkflowSystemEventParameter;
public class TaskCreatedListenerBean extends AbstractProcessStartEventBean {
private TaskCreatedListener listener;
public TaskCreatedListenerBean() {
super("TaskCreatedListenerBean", "Listens for task creation events across all PMVs");
}
@Override
public void initialize(IProcessStartEventBeanRuntime eventRuntime, ProgramConfig programConfig) {
super.initialize(eventRuntime, programConfig);
// Disable polling as we don't need it. Otherwise, the process will be started every minute by default.
eventRuntime.poll().disable();
}
@Override
public void start() throws ServiceException {
// Create and add the system event listener to the application when the bean is started.
super.start();
var eventRuntime = getEventBeanRuntime();
this.listener = new TaskCreatedListener(eventRuntime);
eventRuntime.getProcessModelVersion().getApplication()
.addSystemEventListener(EnumSet.of(SystemEventCategory.WORKFLOW), this.listener);
}
@Override
public void stop() throws ServiceException {
// Don't forget to remove the listener when the bean is stopped.
getEventBeanRuntime().getProcessModelVersion().getApplication()
.removeSystemEventListener(EnumSet.of(SystemEventCategory.WORKFLOW), this.listener);
super.stop();
}
private static class TaskCreatedListener implements ISystemEventListener {
IProcessStartEventBeanRuntime eventRuntime;
private TaskCreatedListener(IProcessStartEventBeanRuntime eventRuntime) {
this.eventRuntime = eventRuntime;
}
@Override
public void handleSystemEvent(SystemEvent<?> event) {
// The listener starts the process where the Program Start element is used with the bean.
// The process is only started if the event is of type `WorkflowSystemEvent#TASK_CREATED`
if (!WorkflowSystemEvent.TASK_CREATED.equals(event.getName())) {
return;
}
// We can get the task IDs from the event parameters and pass them to the process for later use.
List<Long> taskIds = ((WorkflowSystemEventParameter) event.getParameter()).getIds();
eventRuntime.processStarter()
.withReason("Tasks created: " + taskIds)
.withParameter("taskIds", taskIds)
.startAsync();
}
}
}
Here's a picture of my working setup. The process starts with a Program Start element with the bean configured. The corresponding Data Class has the attribute taskIds which gets automatically mapped via the parameters we provided in the listener (they need to match). In the following script element, I simply log the task ids and you can see in the runtime log on the bottom left, that it works.

Note, however, that this is not a 1 to 1 representation of your past implementation. The process will get triggered on every task creation (e.g. also system tasks) and does not care about whether New Task Mails are sent. New Task Mails could, for example, be suppressed in the configuration of the task itself. You might also need to implement this for the task changed event and maybe check whether the responsibles actually changed to achieve the same behavior as before. Therefore, there might be better approaches to your use case.
If you can give me more information about what you actually want to achieve, I could give my opinion on that. Is your use case actually even tied to the New Task Mails or did you just use that process to execute logic whenever a task was assigned to someone?
The approach suggested by you would mean adding a custom mail call for all process steps?
If I understand correctly, you don't need to do that. The New Task Mails will be sent independently, so no need for a custom mail step. Depending on what you actually want to do, you could, for example, also work with other workflow elements which you might then have to add wherever you want your logic to happen.
Kind regards,
Lukas