Skip to content

Commit

Permalink
RHPAM-4779: SLA due date value in ProcessInstanceLog table is not upd… (
Browse files Browse the repository at this point in the history
#2396)

* RHPAM-4779: SLA due date value in ProcessInstanceLog table is not updated after updating process SLA

* Add test for coverage

---------

Co-authored-by: gmunozfe <gmunozfe@redhat.com>
  • Loading branch information
nmirasch and gmunozfe authored Aug 5, 2024
1 parent 553217c commit c6c78ba
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public abstract class AbstractAuditLogger implements ProcessEventListener {
public static final int BEFORE_VAR_CHANGE_EVENT_TYPE = 8;
public static final int AFTER_VAR_CHANGE_EVENT_TYPE = 9;
public static final int ON_ASYNC_NODE_EVENT_TYPE = 10;

public static final int ON_DATA_CHANGE_EVENT_TYPE = 11;

protected AuditEventBuilder builder = new DefaultAuditEventBuilderImpl();

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jbpm.process.instance.impl.ProcessInstanceImpl;
import org.jbpm.workflow.instance.impl.NodeInstanceImpl;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
Expand Down Expand Up @@ -145,4 +146,10 @@ public void afterSLAViolated(SLAViolatedEvent event) {

protected abstract void slaProcessInstanceViolated(SLAViolatedEvent event);

@Override
public void onProcessDataChangedEvent(ProcessDataChangedEvent event){
processDataChanged(event);
}

protected abstract void processDataChanged(ProcessDataChangedEvent event);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.jbpm.process.core.impl.ProcessImpl;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessEventListener;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
Expand Down Expand Up @@ -181,6 +182,27 @@ protected void processStarted(ProcessStartedEvent event) {
persist(log, event);
}

@Override
protected void processDataChanged(ProcessDataChangedEvent event) {
EntityManager em = getEntityManager(event);
Object tx = joinTransaction(em);
long processInstanceId = event.getProcessInstance().getId();
ProcessInstanceLog log = (ProcessInstanceLog) getProcessInstanceMetadata(event.getProcessInstance(), METADATA_PROCESSINTANCE_LOG);
if (log == null) {
List<ProcessInstanceLog> result = em.createQuery("from ProcessInstanceLog as log where log.processInstanceId = :piId and log.end is null")
.setParameter("piId", processInstanceId).getResultList();
if (result != null && !result.isEmpty()) {
log = result.get(result.size() - 1);
}
}
if (log != null) {
log.setSlaCompliance(((ProcessInstance) event.getProcessInstance()).getSlaCompliance());
log.setSlaDueDate(((ProcessInstance) event.getProcessInstance()).getSlaDueDate());
setProcessInstanceMetadata(event.getProcessInstance(), METADATA_PROCESSINTANCE_LOG, log);
em.merge(log);
}
leaveTransaction(em, tx);
}

@Override
protected void processCompleted(ProcessCompletedEvent event) {
Expand Down Expand Up @@ -227,6 +249,7 @@ protected void slaProcessInstanceViolated(SLAViolatedEvent event) {
}
if (log != null) {
log.setSlaCompliance(((ProcessInstance) event.getProcessInstance()).getSlaCompliance());
log.setSlaDueDate(((ProcessInstance) event.getProcessInstance()).getSlaDueDate());
setProcessInstanceMetadata(event.getProcessInstance(), METADATA_PROCESSINTANCE_LOG, log);
em.merge(log);
}
Expand All @@ -252,6 +275,7 @@ protected void slaNodeInstanceViolated(SLAViolatedEvent event) {
}
if (log != null) {
log.setSlaCompliance(((NodeInstance) event.getNodeInstance()).getSlaCompliance());
log.setSlaDueDate(((ProcessInstance) event.getProcessInstance()).getSlaDueDate());
setNodeInstanceMetadata(event.getNodeInstance(), METADATA_NODEINSTANCE_LOG, log);
((NodeInstanceImpl) event.getNodeInstance()).getMetaData().put(METADATA_NODEINSTANCE_LOG, log);
em.merge(log);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.jbpm.process.audit.event;

import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
Expand All @@ -38,4 +39,6 @@ public interface AuditEventBuilder {
AuditEvent buildEvent(ProcessAsyncNodeScheduledEvent pnle);

AuditEvent buildEvent(ProcessVariableChangedEvent pvce);

AuditEvent buildEvent(ProcessDataChangedEvent pdce);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
import org.kie.api.event.process.ProcessStartedEvent;
import org.kie.api.event.process.ProcessVariableChangedEvent;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.process.NodeInstance;
import org.kie.api.runtime.process.ProcessInstance;
Expand Down Expand Up @@ -256,6 +257,28 @@ public AuditEvent buildEvent(ProcessVariableChangedEvent pvce) {
return log;
}

@Override
public AuditEvent buildEvent(ProcessDataChangedEvent pdce) {
ProcessInstanceImpl pi = (ProcessInstanceImpl) pdce.getProcessInstance();
ProcessInstanceLog logEvent = new ProcessInstanceLog(pi.getId(), pi.getProcessId());
logEvent.setOutcome(pi.getOutcome());
logEvent.setStatus(pi.getState());
logEvent.setProcessInstanceDescription( pi.getDescription() );
logEvent.setSlaCompliance(pi.getSlaCompliance());
logEvent.setSlaDueDate(pi.getSlaDueDate());
logEvent.setProcessName(pi.getProcess().getName());
logEvent.setProcessVersion(pi.getProcess().getVersion());
logEvent.setProcessType(((WorkflowProcess)pi.getProcess()).getProcessType());
// store correlation key in its external form
CorrelationKey correlationKey = (CorrelationKey) pi.getMetaData().get("CorrelationKey");
if (correlationKey != null) {
logEvent.setCorrelationKey(correlationKey.toExternalForm());
}
long parentProcessInstanceId = (Long) pi.getMetaData().getOrDefault("ParentProcessInstanceId", -1L);
logEvent.setParentProcessInstanceId(parentProcessInstanceId);
return logEvent;
}

protected String getNodeContainerId(NodeContainer nodeContainer) {
if (nodeContainer instanceof Node) {
return (String) ((Node) nodeContainer).getMetaData().get("UniqueId");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.jbpm.process.audit.variable.ProcessIndexerManager;
import org.jbpm.workflow.instance.impl.NodeInstanceImpl;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
Expand Down Expand Up @@ -185,7 +186,13 @@ public void afterProcessStarted(ProcessStartedEvent event) {
@Override
public void beforeProcessCompleted(ProcessCompletedEvent event) {
}


@Override
public void onProcessDataChangedEvent(ProcessDataChangedEvent event) {
ProcessInstanceLog log = (ProcessInstanceLog) builder.buildEvent(event);
sendMessage(log, ON_DATA_CHANGE_EVENT_TYPE, 9);
}

protected void sendMessage(Object messageContent, Integer eventType, int priority) {
if (connectionFactory == null && queue == null) {
throw new IllegalStateException("ConnectionFactory and Queue cannot be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@

import org.drools.core.command.SingleSessionCommandService;
import org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession;
import org.drools.core.common.InternalKnowledgeRuntime;
import org.drools.core.impl.StatefulKnowledgeSessionImpl;
import org.jbpm.process.instance.InternalProcessRuntime;
import org.jbpm.process.instance.ProcessInstance;
import org.jbpm.process.instance.timer.TimerInstance;
import org.jbpm.process.instance.timer.TimerManager;
import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
Expand Down Expand Up @@ -135,6 +137,7 @@ public Void execute(Context context ) {
if (newTimer != null) {
wfp.internalSetSlaTimerId(newTimer.getId());
wfp.internalSetSlaDueDate(new Date(System.currentTimeMillis() + newTimer.getDelay()));
fireProcessInstanceDataChangedEvent(wfp);
return null;
}

Expand Down Expand Up @@ -239,4 +242,10 @@ protected TimerInstance rescheduleTimer(TimerInstance timer, TimerManager tm) {

return newTimer;
}

private void fireProcessInstanceDataChangedEvent(ProcessInstance processInstance){
InternalKnowledgeRuntime kruntime = processInstance.getKnowledgeRuntime();
InternalProcessRuntime processRuntime = (InternalProcessRuntime) kruntime.getProcessRuntime();
processRuntime.getProcessEventSupport().fireAfterProcessDataChanged(processInstance, kruntime);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright 2023 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jbpm.process.instance.command;

import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.impl.KnowledgeBaseFactory;
import org.drools.core.runtime.process.ProcessRuntimeFactory;
import org.kie.api.event.process.*;

import org.jbpm.process.instance.InternalProcessRuntime;
import org.jbpm.process.instance.ProcessRuntimeFactoryServiceImpl;
import org.jbpm.process.instance.timer.TimerInstance;
import org.jbpm.process.instance.timer.TimerManager;
import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
import org.jbpm.test.util.AbstractBaseTest;
import org.junit.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;

import org.kie.internal.command.RegistryContext;
import org.mockito.Mockito;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

public class UpdateTimerCommandTest extends AbstractBaseTest {

public void addLogger() {
logger = LoggerFactory.getLogger(this.getClass());
}

static {
ProcessRuntimeFactory.setProcessRuntimeFactoryService(new ProcessRuntimeFactoryServiceImpl());
}

@Test
public void testUpdateTimerCommand() throws Exception {
long processInstanceId = 1234;
KieBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
final KieSession workingMemory = kbase.newKieSession();
InternalProcessRuntime processRuntime = ((InternalProcessRuntime) ((InternalWorkingMemory) workingMemory).getProcessRuntime());
final List<ProcessEvent> processEventList = new ArrayList<ProcessEvent>();

final ProcessEventListener processEventListener = new ProcessEventListener() {
@Override
public void beforeProcessStarted(ProcessStartedEvent event) {
processEventList.add(event);
}

@Override
public void afterProcessStarted(ProcessStartedEvent event) {
processEventList.add(event);
}

@Override
public void beforeProcessCompleted(ProcessCompletedEvent event) {
processEventList.add(event);
}

@Override
public void afterProcessCompleted(ProcessCompletedEvent event) {
processEventList.add(event);
}

@Override
public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) {
processEventList.add(event);
}

@Override
public void afterNodeTriggered(ProcessNodeTriggeredEvent event) {
processEventList.add(event);
}

@Override
public void beforeNodeLeft(ProcessNodeLeftEvent event) {
processEventList.add(event);
}

@Override
public void afterNodeLeft(ProcessNodeLeftEvent event) {
processEventList.add(event);
}

@Override
public void beforeVariableChanged(ProcessVariableChangedEvent event) {
processEventList.add(event);
}

@Override
public void afterVariableChanged(ProcessVariableChangedEvent event) {
processEventList.add(event);
}

public void onProcessDataChangedEvent(ProcessDataChangedEvent event) {
processEventList.add(event);
}

};
workingMemory.addEventListener(processEventListener);

RuleFlowProcessInstance processInstance = new RuleFlowProcessInstance() ;
processInstance.setKnowledgeRuntime(((InternalWorkingMemory) workingMemory).getKnowledgeRuntime());
processInstance.setId(processInstanceId);

TimerManager timerManager = ((InternalProcessRuntime) ((InternalWorkingMemory) workingMemory).getProcessRuntime()).getTimerManager();
TimerInstance timer = new TimerInstance();
timer.setDelay(100000);
timerManager.registerTimer(timer, processInstance);

processInstance.internalSetSlaTimerId(timer.getId());
processRuntime.getProcessInstanceManager().internalAddProcessInstance(processInstance);
RegistryContext mockContext = Mockito.mock(RegistryContext.class);
when(mockContext.lookup(KieSession.class)).thenReturn(workingMemory);

UpdateTimerCommand command = new UpdateTimerCommand(processInstance.getId(), timer.getId(),
timer.getDelay(), timer.getPeriod(), timer.getRepeatLimit());
command.execute(mockContext);

assertEquals(1, processEventList.size());
assertTrue(processEventList.get(0) instanceof ProcessDataChangedEvent);
assertEquals(processInstanceId, ((ProcessDataChangedEvent) processEventList.get(0)).getProcessInstance().getId());

timerManager.cancelTimer(processInstanceId, timer.getId());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.jbpm.process.audit.VariableInstanceLog;
import org.jbpm.process.audit.event.AuditEvent;
import org.jbpm.process.audit.event.DefaultAuditEventBuilderImpl;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
Expand Down Expand Up @@ -77,6 +78,13 @@ public AuditEvent buildEvent(ProcessAsyncNodeScheduledEvent pnse) {
return nodeInstanceLog;
}

@Override
public AuditEvent buildEvent(ProcessDataChangedEvent pdce) {
ProcessInstanceLog instanceLog = (ProcessInstanceLog) super.buildEvent(pdce);
instanceLog.setExternalId(ownerId);
return instanceLog;
}

public String getOwnerId() {
return ownerId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.instance.ProcessInstance;
import org.jbpm.process.instance.context.variable.VariableScopeInstance;
import org.kie.api.event.process.ProcessDataChangedEvent;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessNodeLeftEvent;
import org.kie.api.event.process.ProcessAsyncNodeScheduledEvent;
Expand Down Expand Up @@ -96,6 +97,13 @@ public AuditEvent buildEvent(ProcessVariableChangedEvent pvce) {
return variableLog;
}

@Override
public AuditEvent buildEvent(ProcessDataChangedEvent pdce) {
ProcessInstanceLog instanceLog = (ProcessInstanceLog) super.buildEvent(pdce);
instanceLog.setExternalId(deploymentUnitId);
return instanceLog;
}

public String getDeploymentUnitId() {
return deploymentUnitId;
}
Expand Down
Loading

0 comments on commit c6c78ba

Please sign in to comment.