Issue notifying globally when a new task(BPM) was created

Hello

We are using GlobalEvents to publish a notification when a new task (through BPM) was created by another user in the platform.

So basically, when a new task is created and it involves current user logged in, the “inbox” menu item from side menu should update the badge accordingly (“1 New”)

We have extended BpmActivitiListener to publish our custom global event when a new task is created (on TASK_CREATED).

The issue is that the inbox is not updated and the reason for that, I believe, is that the event is caught before transaction ends and task gets commited.
Found through debugging that the newly created task is not retrieved from db on event handling, even though we are using the annotation
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)

How can we make this work? Is there another way to real-time globally notify after a new Task is created?

@UiController("customMainScreen")
@UiDescriptor("custom-main-screen.xml")
public class CustomMainScreen extends MainScreen { 

    @Inject
    private SideMenu sideMenu;
    @Inject
    private ProcTaskService procTaskService;


    @EventListener(ProcTaskGlobalEvent.class)
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onProcTaskGlobalEvent(ProcTaskGlobalEvent procTaskGlobalEvent) {
        SideMenu.MenuItem inboxMenuItem = sideMenu.getMenuItem("inbox-screen");

        int numberOfProcTask = procTaskService.getProcTasksForUser(userSession.getAttribute("userId")).size();
        String badgeText = numberOfProcTask > 0 ? numberOfProcTask + " New" : "";

        if (inboxMenuItem != null) {
            inboxMenuItem.setBadgeText(badgeText);
        }
    }
}



public class ProcTaskGlobalEvent extends GlobalApplicationEvent implements GlobalUiEvent {

    private String name;

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public ProcTaskGlobalEvent(Object source, String name) {
        super(source);
        this.name = name;
    }

    public String getName() {
        return name;
    }
}



public class CustomBpmActivitiListener extends BpmActivitiListener {

    protected Events events = AppBeans.get(Events.class);

    @Override
    public void onEvent(ActivitiEvent event) {
        super.onEvent(event);

        switch (event.getType()) {
            case TASK_CREATED:
                events.publish(new ProcTaskGlobalEvent(this, "created"));
                break;
        }
    }
}
1 Like

Hi,

Which version of the BPM Add-on do you use? Please note that the previous BPM version is deprecated.

Regarding your case - creating @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) doesn’t make any sense in the screen’s methods since there are no transactions in the CUBA UI layer.

Is your event published at all? Maybe it is worth trying the TASK_ASSIGNED Activiti event type.

Hello again.

BPM version is v7.2.7. I believe is the latest version.

Sorry for putting all those tree classes together in the same block of code. They are not actually in the same file. I followed the guidelines for Global Events.
CustomMainScreen is in web module, ProcTaskGlobalEvent is in the global module and CustomBpmActivitiListener is the core module where all our listeners resides.
Unfortunately I cannot share our enterprise project.

The event is published alright and handled accordingly, the code is executed.

The issue is that the task (ProcTask), even tough is created, is not yet persisted in db or the transaction is not closed when the event is triggered.
So, this line of code procTaskService.getProcTasksForUser(userSession.getAttribute("userId")).size(); does not retrieve the newly created task as well among the others already stored in db.

We need to get the event to get handled after commit, hence the annotation @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)

Thanks!

Do you use BPM or BProc plugin? I guess this is BPM

.

This listener DOES NOT know anything about transactions because it is a part of the web module. And there are no transactions in this module, so there is no point using @TransactionalEventListener here.

Did you try to listen to another event type? E.g.

switch (event.getType()) {
            case TASK_ASSIGNED:
                events.publish(new ProcTaskGlobalEvent(this, "created"));
                break;
        }

In addition to this, did you try to extract some more information from the ActivitiEvent instance? You can try something like this:

            case TASK_ASSIGNED:
                task = (TaskEntity) ((ActivitiEntityEvent) event).getEntity();
                String assignee = task.getAssignee();
                events.publish(new ProcTaskGlobalEvent(this, assignee)); //Pass username to a global event

And then update the label in your menu based on the username passed.

What do you think?

Hi,

It worked on TASK_ASSIGNED event type.
Thank you very much.

Have a great day!

1 Like