diff --git a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/BaseWorkItemHandlerConfig.java b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/BaseWorkItemHandlerConfig.java index ab82bcc7cc..9b9d6ad92e 100644 --- a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/BaseWorkItemHandlerConfig.java +++ b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/BaseWorkItemHandlerConfig.java @@ -31,7 +31,7 @@ import org.kie.kogito.addons.k8s.LocalEndpointDiscovery; import org.kie.kogito.addons.quarkus.k8s.workitems.QuarkusDiscoveredEndpointCaller; import org.kie.kogito.examples.onboarding.DecisionTaskWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig; import jakarta.annotation.PostConstruct; diff --git a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java index 25ffb1aa04..8ddf1cd26f 100644 --- a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java +++ b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java @@ -19,15 +19,18 @@ package org.kie.kogito.examples.onboarding; import java.util.Map; +import java.util.Optional; import org.kie.kogito.addons.quarkus.k8s.workitems.QuarkusDiscoveredEndpointCaller; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; import jakarta.ws.rs.HttpMethod; -public class DecisionTaskWorkItemHandler implements KogitoWorkItemHandler { +public class DecisionTaskWorkItemHandler extends DefaultKogitoWorkItemHandler { private QuarkusDiscoveredEndpointCaller endpointCaller; @@ -36,14 +39,9 @@ public DecisionTaskWorkItemHandler(QuarkusDiscoveredEndpointCaller endpointCalle } @Override - public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { + public Optional activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { Map results = endpointCaller.discoverAndCall(workItem, System.getenv("NAMESPACE"), "Decision", HttpMethod.POST); - manager.completeWorkItem(workItem.getStringId(), results); - } - - @Override - public void abortWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { - + return Optional.of(handler.completeTransition(workItem.getPhaseStatus(), results)); } @Override diff --git a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/WorkItemHandlerConfig.java b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/WorkItemHandlerConfig.java index 98dc9a2482..77926dd050 100644 --- a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/WorkItemHandlerConfig.java +++ b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/WorkItemHandlerConfig.java @@ -19,7 +19,7 @@ package org.kie.kogito.examples; import org.kie.kogito.examples.test.RecordedOutputWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; public class WorkItemHandlerConfig extends BaseWorkItemHandlerConfig { diff --git a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java index d640de590d..70d1de4b0e 100644 --- a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java +++ b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java @@ -28,8 +28,8 @@ import org.junit.jupiter.api.Test; import org.kie.kogito.examples.test.RecordedOutputWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.ProcessConfig; import org.kie.kogito.testcontainers.quarkus.InfinispanQuarkusTestResource; diff --git a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java index 05a6799916..f7559da0d9 100644 --- a/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java +++ b/kogito-quarkus-examples/onboarding-example/onboarding-quarkus/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java @@ -20,26 +20,23 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.Function; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; -public class RecordedOutputWorkItemHandler implements KogitoWorkItemHandler { +public class RecordedOutputWorkItemHandler extends DefaultKogitoWorkItemHandler { private Map>> recorded = new HashMap<>(); @Override - public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { + public Optional activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { Map results = recorded.remove(workItem.getParameter("TaskName")).apply(workItem); - - manager.completeWorkItem(workItem.getStringId(), results); - } - - @Override - public void abortWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { - + return Optional.of(handler.completeTransition(workItem.getPhaseStatus(), results)); } public void record(String name, Function> item) { diff --git a/kogito-quarkus-examples/process-error-handling/src/main/java/org/acme/wih/CustomTaskWorkItemHandler.java b/kogito-quarkus-examples/process-error-handling/src/main/java/org/acme/wih/CustomTaskWorkItemHandler.java index ee6309cd6b..aba8a9730e 100644 --- a/kogito-quarkus-examples/process-error-handling/src/main/java/org/acme/wih/CustomTaskWorkItemHandler.java +++ b/kogito-quarkus-examples/process-error-handling/src/main/java/org/acme/wih/CustomTaskWorkItemHandler.java @@ -20,20 +20,23 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.kie.api.runtime.process.ProcessWorkItemHandlerException; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class CustomTaskWorkItemHandler implements KogitoWorkItemHandler { +public class CustomTaskWorkItemHandler extends DefaultKogitoWorkItemHandler { private static final Logger LOG = LoggerFactory.getLogger(CustomTaskWorkItemHandler.class); @Override - public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { + public Optional activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { LOG.debug("start"); LOG.debug("Passed parameters:"); @@ -51,15 +54,22 @@ public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manag if (input.matches("(RETRY|COMPLETE|RETHROW)")) { handleError(input); } else if (input.contentEquals("ABORT")) { - manager.abortWorkItem(workItem.getStringId()); + return Optional.of(handler.abortTransition(workItem.getPhaseStatus())); } else { // Don’t forget to finish the work item otherwise the process // will be active infinitely and never will pass the flow // to the next node. - manager.completeWorkItem(workItem.getStringId(), results); + return Optional.of(handler.completeTransition(workItem.getPhaseStatus(), results)); } LOG.debug("end"); + return Optional.empty(); + } + + @Override + public Optional abortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) { + LOG.debug("ABORT!"); + return Optional.empty(); } private void handleError(String strategy) { @@ -68,9 +78,4 @@ private void handleError(String strategy) { new IllegalStateException(strategy + " strategy test")); } - @Override - public void abortWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { - LOG.debug("ABORT!"); - manager.abortWorkItem(workItem.getStringId()); - } } \ No newline at end of file diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java index 2e973282b8..745f9f2e06 100644 --- a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java +++ b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java @@ -18,8 +18,7 @@ */ package org.acme.travels.config; -import org.acme.travels.usertasks.CustomHumanTaskLifeCycle; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemHandler; +import org.acme.travels.usertasks.CustomHumanTaskWorkItemHandler; import org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig; import jakarta.enterprise.context.ApplicationScoped; @@ -37,6 +36,6 @@ @ApplicationScoped public class CustomWorkItemHandlerConfig extends DefaultWorkItemHandlerConfig { { - register("Human Task", new HumanTaskWorkItemHandler(new CustomHumanTaskLifeCycle())); + register("Human Task", new CustomHumanTaskWorkItemHandler()); } } diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java deleted file mode 100644 index 7465bf0a4f..0000000000 --- a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Arrays; -import java.util.List; - -import org.jbpm.process.instance.impl.workitem.Complete; -import org.kie.kogito.process.workitem.LifeCyclePhase; - -/** - * Extension to Complete life cycle phase that applies to any human task. - * It will set the status to "Completed" - * - * This phase will only allow to complete tasks that are in started phase. - * - * It can transition from - *
    - *
  • Start
  • - *
- * - * This is a terminating (final) phase. - */ -public class CompleteStartedOnly extends Complete { - - private List allowedTransitions = Arrays.asList(Start.ID); - - @Override - public boolean canTransition(LifeCyclePhase phase) { - return allowedTransitions.contains(phase.id()); - } - -} diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java deleted file mode 100644 index c83b80302c..0000000000 --- a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.jbpm.process.instance.impl.humantask.BaseHumanTaskLifeCycle; -import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.humantask.phases.Release; -import org.jbpm.process.instance.impl.humantask.phases.Skip; -import org.jbpm.process.instance.impl.workitem.Abort; -import org.jbpm.process.instance.impl.workitem.Active; -import org.jbpm.process.instance.impl.workitem.Complete; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; -import org.kie.kogito.process.workitem.InvalidLifeCyclePhaseException; -import org.kie.kogito.process.workitem.InvalidTransitionException; -import org.kie.kogito.process.workitem.LifeCycle; -import org.kie.kogito.process.workitem.LifeCyclePhase; -import org.kie.kogito.process.workitem.NotAuthorizedException; -import org.kie.kogito.process.workitem.Policy; -import org.kie.kogito.process.workitem.Transition; -import org.kie.kogito.process.workitems.InternalKogitoWorkItemManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Custom life cycle definition for human tasks. It comes with following phases - * - *
    - *
  • Active
  • - *
  • Claim
  • - *
  • Release
  • - *
  • Start
  • - *
  • Complete - extended one that allows to only complete started tasks
  • - *
  • Skip
  • - *
  • Abort
  • - *
- * At the beginning human task enters - * - *
- * Active
- * 
- * - * phase. From there it can go to - * - *
    - *
  • Claim
  • - *
  • Skip
  • - *
  • Abort
  • - *
- * - * at any time. At each phase data can be associated and by that set on work item. - * - * Completion can only be performed on started tasks. - */ -public class CustomHumanTaskLifeCycle implements LifeCycle> { - - private static final Logger logger = LoggerFactory.getLogger(BaseHumanTaskLifeCycle.class); - - private Map phases = new LinkedHashMap<>(); - - public CustomHumanTaskLifeCycle() { - phases.put(Claim.ID, new Claim()); - phases.put(Release.ID, new Release()); - phases.put(Start.ID, new Start()); - phases.put(Complete.ID, new CompleteStartedOnly()); - phases.put(Skip.ID, new Skip()); - phases.put(Active.ID, new Active()); - phases.put(Abort.ID, new Abort()); - } - - @Override - public LifeCyclePhase phaseById(String phaseId) { - return phases.get(phaseId); - } - - @Override - public Collection phases() { - return phases.values(); - } - - @Override - public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemManager manager, Transition> transition) { - logger.debug("Transition method invoked for work item {} to transition to {}, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), - workItem.getPhaseStatus()); - - InternalHumanTaskWorkItem humanTaskWorkItem = (InternalHumanTaskWorkItem) workItem; - - LifeCyclePhase targetPhase = phases.get(transition.phase()); - if (targetPhase == null) { - logger.debug("Target life cycle phase '{}' does not exist in {}", transition.phase(), this.getClass().getSimpleName()); - throw new InvalidLifeCyclePhaseException(transition.phase()); - } - - LifeCyclePhase currentPhase = phases.get(humanTaskWorkItem.getPhaseId()); - - if (!targetPhase.canTransition(currentPhase)) { - logger.debug("Target life cycle phase '{}' cannot transition from current state '{}'", targetPhase.id(), currentPhase.id()); - throw new InvalidTransitionException("Cannot transition from " + humanTaskWorkItem.getPhaseId() + " to " + targetPhase.id()); - } - - if (!targetPhase.id().equals(Active.ID) && !targetPhase.id().equals(Abort.ID) && !humanTaskWorkItem.enforce(transition.policies().toArray(new Policy[transition.policies().size()]))) { - throw new NotAuthorizedException("User is not authorized to access task instance with id " + humanTaskWorkItem.getStringId()); - } - - humanTaskWorkItem.setPhaseId(targetPhase.id()); - humanTaskWorkItem.setPhaseStatus(targetPhase.status()); - - targetPhase.apply(humanTaskWorkItem, transition); - if (transition.data() != null) { - logger.debug("Updating data for phase {} and work item {}", targetPhase.id(), humanTaskWorkItem.getStringId()); - humanTaskWorkItem.getResults().putAll(transition.data()); - } - logger.debug("Transition for work item {} to {} done, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), workItem.getPhaseStatus()); - - if (targetPhase.isTerminating()) { - logger.debug("Target life cycle phase '{}' is terminiating, completing work item {}", targetPhase.id(), humanTaskWorkItem.getStringId()); - // since target life cycle phase is terminating completing work item - ((InternalKogitoWorkItemManager) manager).internalCompleteWorkItem(humanTaskWorkItem); - } - - return data(humanTaskWorkItem); - } - - @Override - public Map data(KogitoWorkItem workItem) { - return ((InternalHumanTaskWorkItem) workItem).getResults(); - } -} diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java new file mode 100644 index 0000000000..0a3fa0eabb --- /dev/null +++ b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.acme.travels.usertasks; + +import java.util.Optional; + +import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemLifeCycle; +import org.kie.kogito.internal.process.workitem.WorkItemPhaseState; +import org.kie.kogito.internal.process.workitem.WorkItemTerminationType; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; +import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCycle; +import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCyclePhase; + +public class CustomHumanTaskWorkItemHandler extends DefaultKogitoWorkItemHandler { + + public static final String TRANSITION_COMPLETE = "complete"; + public static final String TRANSITION_ABORT = "abort"; + public static final String TRANSITION_ACTIVATE = "activate"; + public static final String TRANSITION_START = "start"; + public static final String TRANSITION_SKIP = "skip"; + + @Override + public WorkItemLifeCycle initialize() { + WorkItemPhaseState initialized = WorkItemPhaseState.initialized(); + WorkItemPhaseState completed = WorkItemPhaseState.of("Completed", WorkItemTerminationType.COMPLETE); + WorkItemPhaseState aborted = WorkItemPhaseState.of("Aborted", WorkItemTerminationType.ABORT); + WorkItemPhaseState activated = WorkItemPhaseState.of("Activated"); + WorkItemPhaseState started = WorkItemPhaseState.of("Started"); + + DefaultWorkItemLifeCyclePhase active = new DefaultWorkItemLifeCyclePhase(TRANSITION_ACTIVATE, initialized, activated, this::activateWorkItemHandler); + DefaultWorkItemLifeCyclePhase start = new DefaultWorkItemLifeCyclePhase(TRANSITION_START, activated, started, this::activateWorkItemHandler); + DefaultWorkItemLifeCyclePhase complete = new DefaultWorkItemLifeCyclePhase(TRANSITION_COMPLETE, started, completed, this::completeWorkItemHandler); + DefaultWorkItemLifeCyclePhase abort = new DefaultWorkItemLifeCyclePhase(TRANSITION_ABORT, started, aborted, this::abortWorkItemHandler); + + return new DefaultWorkItemLifeCycle(active, start, abort, complete); + } + + @Override + public Optional completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) { + getUserFromTransition(transition).ifPresent(e -> workitem.setOutput("ActorId", e)); + return Optional.empty(); + } + + private Optional getUserFromTransition(WorkItemTransition transition) { + Optional securityPolicy = transition.policies().stream().filter(SecurityPolicy.class::isInstance).map(SecurityPolicy.class::cast).findAny(); + if (securityPolicy.isPresent()) { + return Optional.ofNullable(securityPolicy.get().getUser()); + } + return Optional.empty(); + } +} diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/Start.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/Start.java deleted file mode 100644 index 7a5199de1c..0000000000 --- a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/main/java/org/acme/travels/usertasks/Start.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Arrays; -import java.util.List; - -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.humantask.phases.Release; -import org.jbpm.process.instance.impl.workitem.Active; -import org.kie.kogito.process.workitem.LifeCyclePhase; - -/** - * Start life cycle phase that applies to any human task. - * It will set the status to "Started" - * - * It can transition from - *
    - *
  • Active
  • - *
  • Claim
  • - *
  • Release
  • - *
- * - */ -public class Start implements LifeCyclePhase { - - public static final String ID = "start"; - public static final String STATUS = "Started"; - - private List allowedTransitions = Arrays.asList(Active.ID, Claim.ID, Release.ID); - - @Override - public String id() { - return ID; - } - - @Override - public String status() { - return STATUS; - } - - @Override - public boolean isTerminating() { - return false; - } - - @Override - public boolean canTransition(LifeCyclePhase phase) { - return allowedTransitions.contains(phase.id()); - } -} diff --git a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/test/java/org/acme/travels/custom/lifecycle/quarkus/ApprovalsProcessTest.java b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/test/java/org/acme/travels/custom/lifecycle/quarkus/ApprovalsProcessTest.java index 573ab8f193..59af5b65fb 100644 --- a/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/test/java/org/acme/travels/custom/lifecycle/quarkus/ApprovalsProcessTest.java +++ b/kogito-quarkus-examples/process-usertasks-custom-lifecycle-quarkus/src/test/java/org/acme/travels/custom/lifecycle/quarkus/ApprovalsProcessTest.java @@ -25,25 +25,23 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.acme.travels.usertasks.Start; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProvider; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.InvalidTransitionException; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; -import org.kie.kogito.process.workitem.InvalidTransitionException; import io.quarkus.test.junit.QuarkusTest; import jakarta.inject.Inject; import jakarta.inject.Named; +import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -78,9 +76,12 @@ public void testApprovalProcess() { assertEquals(1, workItems.size()); Map results = new HashMap<>(); results.put("approved", true); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -93,7 +94,8 @@ public void testApprovalProcess() { assertEquals(1, workItems.size()); results.put("approved", false); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); @@ -129,15 +131,17 @@ public void testApprovalProcessViaPhases() { final String wiId = workItems.get(0).getId(); // test to make sure you can't complete if the task is not in started state - assertThrows(InvalidTransitionException.class, () -> processInstance.transitionWorkItem(wiId, new HumanTaskTransition(Complete.ID, + assertThrows(InvalidTransitionException.class, () -> processInstance.completeWorkItem(wiId, Collections.singletonMap("approved", true), - SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers")))))); + SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))))); // now test going through phases - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -149,9 +153,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - // test that claim can be skipped - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-quarkus-examples/process-usertasks-quarkus/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java b/kogito-quarkus-examples/process-usertasks-quarkus/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java index a5a41285c3..289bd19767 100644 --- a/kogito-quarkus-examples/process-usertasks-quarkus/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java +++ b/kogito-quarkus-examples/process-usertasks-quarkus/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java @@ -25,25 +25,23 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; import io.quarkus.test.junit.QuarkusTest; -import jakarta.inject.Inject; -import jakarta.inject.Named; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import jakarta.inject.Inject; +import jakarta.inject.Named; + @QuarkusTest public class ApprovalsProcessTest { @@ -75,6 +73,7 @@ public void testApprovalProcess() { results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -117,9 +116,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -130,8 +132,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-quarkus-examples/process-usertasks-with-security-oidc-quarkus/src/test/java/org/acme/travels/ApprovalsProcessIT.java b/kogito-quarkus-examples/process-usertasks-with-security-oidc-quarkus/src/test/java/org/acme/travels/ApprovalsProcessIT.java index 2d4660efd7..5485991eaf 100644 --- a/kogito-quarkus-examples/process-usertasks-with-security-oidc-quarkus/src/test/java/org/acme/travels/ApprovalsProcessIT.java +++ b/kogito-quarkus-examples/process-usertasks-with-security-oidc-quarkus/src/test/java/org/acme/travels/ApprovalsProcessIT.java @@ -19,18 +19,15 @@ package org.acme.travels; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; @@ -42,6 +39,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -77,6 +76,7 @@ public void testApprovalProcess() { results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Arrays.asList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -118,9 +118,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Arrays.asList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -131,8 +134,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-quarkus-examples/process-usertasks-with-security-quarkus/src/test/java/org/acme/travels/security/quarkus/ApprovalsProcessTest.java b/kogito-quarkus-examples/process-usertasks-with-security-quarkus/src/test/java/org/acme/travels/security/quarkus/ApprovalsProcessTest.java index fffafa26b6..7faa81a290 100644 --- a/kogito-quarkus-examples/process-usertasks-with-security-quarkus/src/test/java/org/acme/travels/security/quarkus/ApprovalsProcessTest.java +++ b/kogito-quarkus-examples/process-usertasks-with-security-quarkus/src/test/java/org/acme/travels/security/quarkus/ApprovalsProcessTest.java @@ -25,13 +25,11 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; @@ -41,6 +39,8 @@ import jakarta.inject.Inject; import jakarta.inject.Named; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -75,6 +75,7 @@ public void testApprovalProcess() { results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -117,9 +118,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -130,8 +134,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/WorkItemHandlerConfig.java b/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/WorkItemHandlerConfig.java index fc2f30843a..52a809ca0f 100644 --- a/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/WorkItemHandlerConfig.java +++ b/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/WorkItemHandlerConfig.java @@ -30,7 +30,7 @@ import org.kie.kogito.addons.k8s.LocalEndpointDiscovery; import org.kie.kogito.addons.springboot.k8s.workitems.SpringDiscoveredEndpointCaller; import org.kie.kogito.examples.onboarding.DecisionTaskWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java b/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java index f958f4591a..81be4f66a2 100644 --- a/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java +++ b/kogito-springboot-examples/onboarding-springboot/src/main/java/org/kie/kogito/examples/onboarding/DecisionTaskWorkItemHandler.java @@ -19,14 +19,17 @@ package org.kie.kogito.examples.onboarding; import java.util.Map; +import java.util.Optional; import org.kie.kogito.addons.springboot.k8s.workitems.SpringDiscoveredEndpointCaller; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; import org.springframework.http.HttpMethod; -public class DecisionTaskWorkItemHandler implements KogitoWorkItemHandler { +public class DecisionTaskWorkItemHandler extends DefaultKogitoWorkItemHandler { private SpringDiscoveredEndpointCaller endpointCaller; @@ -35,15 +38,9 @@ public DecisionTaskWorkItemHandler(SpringDiscoveredEndpointCaller endpointCaller } @Override - public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { + public Optional activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { Map results = this.endpointCaller.discoverAndCall(workItem, System.getenv("NAMESPACE"), "Decision", HttpMethod.POST.toString()); - - manager.completeWorkItem(workItem.getStringId(), results); - } - - @Override - public void abortWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { - + return Optional.of(handler.completeTransition(workItem.getPhaseStatus(), results)); } @Override diff --git a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java index 3cb334537e..920a89545a 100644 --- a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java +++ b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/onboarding/OnboardingEndpointIT.java @@ -31,8 +31,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.kie.kogito.examples.KogitoOnboardingApplication; import org.kie.kogito.examples.test.RecordedOutputWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.ProcessConfig; import org.kie.kogito.testcontainers.springboot.InfinispanSpringBootTestResource; import org.springframework.beans.factory.annotation.Autowired; diff --git a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java index 05a6799916..f7559da0d9 100644 --- a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java +++ b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedOutputWorkItemHandler.java @@ -20,26 +20,23 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.Function; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; -public class RecordedOutputWorkItemHandler implements KogitoWorkItemHandler { +public class RecordedOutputWorkItemHandler extends DefaultKogitoWorkItemHandler { private Map>> recorded = new HashMap<>(); @Override - public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { + public Optional activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { Map results = recorded.remove(workItem.getParameter("TaskName")).apply(workItem); - - manager.completeWorkItem(workItem.getStringId(), results); - } - - @Override - public void abortWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manager) { - + return Optional.of(handler.completeTransition(workItem.getPhaseStatus(), results)); } public void record(String name, Function> item) { diff --git a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedWorkItemHandlerConfig.java b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedWorkItemHandlerConfig.java index 26b40467a3..ea4983a3ab 100644 --- a/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedWorkItemHandlerConfig.java +++ b/kogito-springboot-examples/onboarding-springboot/src/test/java/org/kie/kogito/examples/test/RecordedWorkItemHandlerConfig.java @@ -23,7 +23,7 @@ import java.util.Collection; import java.util.List; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java index 3021d7685b..7727ba2c44 100644 --- a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java +++ b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/config/CustomWorkItemHandlerConfig.java @@ -18,8 +18,7 @@ */ package org.acme.travels.config; -import org.acme.travels.usertasks.CustomHumanTaskLifeCycle; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemHandler; +import org.acme.travels.usertasks.CustomHumanTaskWorkItemHandler; import org.kie.kogito.process.impl.DefaultWorkItemHandlerConfig; import org.springframework.stereotype.Component; @@ -36,6 +35,6 @@ @Component public class CustomWorkItemHandlerConfig extends DefaultWorkItemHandlerConfig { { - register("Human Task", new HumanTaskWorkItemHandler(new CustomHumanTaskLifeCycle())); + register("Human Task", new CustomHumanTaskWorkItemHandler()); } } \ No newline at end of file diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java deleted file mode 100644 index 7465bf0a4f..0000000000 --- a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CompleteStartedOnly.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Arrays; -import java.util.List; - -import org.jbpm.process.instance.impl.workitem.Complete; -import org.kie.kogito.process.workitem.LifeCyclePhase; - -/** - * Extension to Complete life cycle phase that applies to any human task. - * It will set the status to "Completed" - * - * This phase will only allow to complete tasks that are in started phase. - * - * It can transition from - *
    - *
  • Start
  • - *
- * - * This is a terminating (final) phase. - */ -public class CompleteStartedOnly extends Complete { - - private List allowedTransitions = Arrays.asList(Start.ID); - - @Override - public boolean canTransition(LifeCyclePhase phase) { - return allowedTransitions.contains(phase.id()); - } - -} diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java deleted file mode 100644 index d5c0715617..0000000000 --- a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskLifeCycle.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.jbpm.process.instance.impl.humantask.BaseHumanTaskLifeCycle; -import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.humantask.phases.Release; -import org.jbpm.process.instance.impl.humantask.phases.Skip; -import org.jbpm.process.instance.impl.workitem.Abort; -import org.jbpm.process.instance.impl.workitem.Active; -import org.jbpm.process.instance.impl.workitem.Complete; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; -import org.kie.kogito.process.workitem.InvalidLifeCyclePhaseException; -import org.kie.kogito.process.workitem.InvalidTransitionException; -import org.kie.kogito.process.workitem.LifeCycle; -import org.kie.kogito.process.workitem.LifeCyclePhase; -import org.kie.kogito.process.workitem.NotAuthorizedException; -import org.kie.kogito.process.workitem.Policy; -import org.kie.kogito.process.workitem.Transition; -import org.kie.kogito.process.workitems.InternalKogitoWorkItemManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Custom life cycle definition for human tasks. It comes with following phases - * - *
    - *
  • Active
  • - *
  • Claim
  • - *
  • Release
  • - *
  • Start
  • - *
  • Complete - extended one that allows to only complete started tasks
  • - *
  • Skip
  • - *
  • Abort
  • - *
- * At the beginning human task enters - * - *
- * Active
- * 
- * - * phase. From there it can go to - * - *
    - *
  • Claim
  • - *
  • Skip
  • - *
  • Abort
  • - *
- * - * at any time. At each phase data can be associated and by that set on work item. - * - * Completion can only be performed on started tasks. - */ -public class CustomHumanTaskLifeCycle implements LifeCycle> { - - private static final Logger logger = LoggerFactory.getLogger(BaseHumanTaskLifeCycle.class); - - private Map phases = new LinkedHashMap<>(); - - public CustomHumanTaskLifeCycle() { - phases.put(Claim.ID, new Claim()); - phases.put(Release.ID, new Release()); - phases.put(Start.ID, new Start()); - phases.put(Complete.ID, new CompleteStartedOnly()); - phases.put(Skip.ID, new Skip()); - phases.put(Active.ID, new Active()); - phases.put(Abort.ID, new Abort()); - } - - @Override - public LifeCyclePhase phaseById(String phaseId) { - return phases.get(phaseId); - } - - @Override - public Collection phases() { - return phases.values(); - } - - @Override - public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemManager manager, Transition> transition) { - logger.debug("Transition method invoked for work item {} to transition to {}, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), - workItem.getPhaseStatus()); - - InternalHumanTaskWorkItem humanTaskWorkItem = (InternalHumanTaskWorkItem) workItem; - - LifeCyclePhase targetPhase = phases.get(transition.phase()); - if (targetPhase == null) { - logger.debug("Target life cycle phase '{}' does not exist in {}", transition.phase(), this.getClass().getSimpleName()); - throw new InvalidLifeCyclePhaseException(transition.phase()); - } - - LifeCyclePhase currentPhase = phases.get(humanTaskWorkItem.getPhaseId()); - - if (!targetPhase.canTransition(currentPhase)) { - logger.debug("Target life cycle phase '{}' cannot transition from current state '{}'", targetPhase.id(), currentPhase.id()); - throw new InvalidTransitionException("Cannot transition from " + humanTaskWorkItem.getPhaseId() + " to " + targetPhase.id()); - } - - if (!targetPhase.id().equals(Active.ID) && !targetPhase.id().equals(Abort.ID) && !humanTaskWorkItem.enforce(transition.policies().toArray(new Policy[transition.policies().size()]))) { - throw new NotAuthorizedException("User is not authorized to access task instance with id " + humanTaskWorkItem.getStringId()); - } - - humanTaskWorkItem.setPhaseId(targetPhase.id()); - humanTaskWorkItem.setPhaseStatus(targetPhase.status()); - - targetPhase.apply(humanTaskWorkItem, transition); - if (transition.data() != null) { - logger.debug("Updating data for work item {}", targetPhase.id(), humanTaskWorkItem.getStringId()); - humanTaskWorkItem.getResults().putAll(transition.data()); - } - logger.debug("Transition for work item {} to {} done, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), workItem.getPhaseStatus()); - - if (targetPhase.isTerminating()) { - logger.debug("Target life cycle phase '{}' is terminiating, completing work item {}", targetPhase.id(), humanTaskWorkItem.getStringId()); - // since target life cycle phase is terminating completing work item - ((InternalKogitoWorkItemManager) manager).internalCompleteWorkItem(humanTaskWorkItem); - } - - return data(humanTaskWorkItem); - } - - @Override - public Map data(KogitoWorkItem workItem) { - return ((InternalHumanTaskWorkItem) workItem).getResults(); - } -} diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java new file mode 100644 index 0000000000..aa22513441 --- /dev/null +++ b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/CustomHumanTaskWorkItemHandler.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.acme.travels.usertasks; + +import java.util.Optional; + +import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager; +import org.kie.kogito.internal.process.workitem.WorkItemLifeCycle; +import org.kie.kogito.internal.process.workitem.WorkItemPhaseState; +import org.kie.kogito.internal.process.workitem.WorkItemTerminationType; +import org.kie.kogito.internal.process.workitem.WorkItemTransition; +import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler; +import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCycle; +import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCyclePhase; + +public class CustomHumanTaskWorkItemHandler extends DefaultKogitoWorkItemHandler { + + public static final String TRANSITION_COMPLETE = "complete"; + public static final String TRANSITION_ABORT = "abort"; + public static final String TRANSITION_ACTIVATE = "activate"; + public static final String TRANSITION_START = "start"; + public static final String TRANSITION_SKIP = "skip"; + + @Override + public WorkItemLifeCycle initialize() { + WorkItemPhaseState initialized = WorkItemPhaseState.initialized(); + WorkItemPhaseState completed = WorkItemPhaseState.of("Completed", WorkItemTerminationType.COMPLETE); + WorkItemPhaseState aborted = WorkItemPhaseState.of("Aborted", WorkItemTerminationType.ABORT); + WorkItemPhaseState activated = WorkItemPhaseState.of("Activated"); + WorkItemPhaseState started = WorkItemPhaseState.of("Started"); + + DefaultWorkItemLifeCyclePhase active = new DefaultWorkItemLifeCyclePhase(TRANSITION_ACTIVATE, initialized, activated, this::activateWorkItemHandler); + DefaultWorkItemLifeCyclePhase start = new DefaultWorkItemLifeCyclePhase(TRANSITION_START, activated, started, this::activateWorkItemHandler); + DefaultWorkItemLifeCyclePhase complete = new DefaultWorkItemLifeCyclePhase(TRANSITION_COMPLETE, started, completed, this::completeWorkItemHandler); + DefaultWorkItemLifeCyclePhase abort = new DefaultWorkItemLifeCyclePhase(TRANSITION_ABORT, started, aborted, this::abortWorkItemHandler); + + return new DefaultWorkItemLifeCycle(active, start, abort, complete); + } + + @Override + public Optional completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) { + getUserFromTransition(transition).ifPresent(e -> workitem.setOutput("ActorId", e)); + return Optional.empty(); + } + + private Optional getUserFromTransition(WorkItemTransition transition) { + Optional securityPolicy = transition.policies().stream().filter(SecurityPolicy.class::isInstance).map(SecurityPolicy.class::cast).findAny(); + if (securityPolicy.isPresent()) { + return Optional.ofNullable(securityPolicy.get().getUser()); + } + return Optional.empty(); + } +} diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/Start.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/Start.java deleted file mode 100644 index 7a5199de1c..0000000000 --- a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/main/java/org/acme/travels/usertasks/Start.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.acme.travels.usertasks; - -import java.util.Arrays; -import java.util.List; - -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.humantask.phases.Release; -import org.jbpm.process.instance.impl.workitem.Active; -import org.kie.kogito.process.workitem.LifeCyclePhase; - -/** - * Start life cycle phase that applies to any human task. - * It will set the status to "Started" - * - * It can transition from - *
    - *
  • Active
  • - *
  • Claim
  • - *
  • Release
  • - *
- * - */ -public class Start implements LifeCyclePhase { - - public static final String ID = "start"; - public static final String STATUS = "Started"; - - private List allowedTransitions = Arrays.asList(Active.ID, Claim.ID, Release.ID); - - @Override - public String id() { - return ID; - } - - @Override - public String status() { - return STATUS; - } - - @Override - public boolean isTerminating() { - return false; - } - - @Override - public boolean canTransition(LifeCyclePhase phase) { - return allowedTransitions.contains(phase.id()); - } -} diff --git a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/test/java/org/acme/travels/custom/lifecycle/springboot/ApprovalsProcessTest.java b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/test/java/org/acme/travels/custom/lifecycle/springboot/ApprovalsProcessTest.java index 4b5af8bfd8..e761d10a67 100644 --- a/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/test/java/org/acme/travels/custom/lifecycle/springboot/ApprovalsProcessTest.java +++ b/kogito-springboot-examples/process-usertasks-custom-lifecycle-springboot/src/test/java/org/acme/travels/custom/lifecycle/springboot/ApprovalsProcessTest.java @@ -25,19 +25,16 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.acme.travels.usertasks.Start; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.InvalidTransitionException; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; -import org.kie.kogito.process.workitem.InvalidTransitionException; import org.kie.kogito.tests.KogitoInfinispanSpringbootApplication; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -46,6 +43,8 @@ import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit.jupiter.SpringExtension; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; @@ -73,7 +72,7 @@ public void testApprovalProcess() { processInstance.start(); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status()); - SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))); + SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("managers"))); processInstance.workItems(policy); @@ -81,13 +80,15 @@ public void testApprovalProcess() { assertEquals(1, workItems.size()); Map results = new HashMap<>(); results.put("approved", true); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); - policy = SecurityPolicy.of(IdentityProviders.of("john", Collections.singletonList("managers"))); + policy = SecurityPolicy.of(IdentityProviders.of("john", singletonList("managers"))); processInstance.workItems(policy); @@ -95,7 +96,7 @@ public void testApprovalProcess() { assertEquals(1, workItems.size()); results.put("approved", false); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); @@ -120,7 +121,7 @@ public void testApprovalProcessViaPhases() { processInstance.start(); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status()); - SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))); + SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("managers"))); List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); @@ -128,24 +129,26 @@ public void testApprovalProcessViaPhases() { final String wiId = workItems.get(0).getId(); // test to make sure you can't complete if the task is not in started state + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + try { - processInstance.transitionWorkItem(wiId, new HumanTaskTransition(Complete.ID, - Collections.singletonMap("approved", true), - SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))))); + processInstance.transitionWorkItem(wiId, handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), + SecurityPolicy.of(IdentityProviders.of("admin", singletonList("managers"))))); fail("It's not possible to complete non started tasks"); } catch (InvalidTransitionException e) { // expected } // now test going through phases - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); - policy = SecurityPolicy.of(IdentityProviders.of("john", Collections.singletonList("managers"))); + policy = SecurityPolicy.of(IdentityProviders.of("john", singletonList("managers"))); processInstance.workItems(policy); @@ -153,8 +156,9 @@ public void testApprovalProcessViaPhases() { assertEquals(1, workItems.size()); // test that claim can be skipped - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Start.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("start", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-springboot-examples/process-usertasks-springboot/src/test/java/org/acme/travels/springboot/ApprovalsProcessTest.java b/kogito-springboot-examples/process-usertasks-springboot/src/test/java/org/acme/travels/springboot/ApprovalsProcessTest.java index 9ec367111b..4258f6a1da 100644 --- a/kogito-springboot-examples/process-usertasks-springboot/src/test/java/org/acme/travels/springboot/ApprovalsProcessTest.java +++ b/kogito-springboot-examples/process-usertasks-springboot/src/test/java/org/acme/travels/springboot/ApprovalsProcessTest.java @@ -25,14 +25,12 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; @@ -72,21 +70,18 @@ public void testApprovalProcess() { SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))); - processInstance.workItems(policy); - List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); Map results = new HashMap<>(); results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); policy = SecurityPolicy.of(IdentityProviders.of("john", Collections.singletonList("managers"))); - processInstance.workItems(policy); - workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); @@ -122,9 +117,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -135,8 +133,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), Collections.emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), Collections.singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-springboot-examples/process-usertasks-with-security-oidc-springboot/src/test/java/org/acme/travels/security/oidc/springboot/ApprovalsProcessTest.java b/kogito-springboot-examples/process-usertasks-with-security-oidc-springboot/src/test/java/org/acme/travels/security/oidc/springboot/ApprovalsProcessTest.java index fa25b9e3d3..8ac6708233 100644 --- a/kogito-springboot-examples/process-usertasks-with-security-oidc-springboot/src/test/java/org/acme/travels/security/oidc/springboot/ApprovalsProcessTest.java +++ b/kogito-springboot-examples/process-usertasks-with-security-oidc-springboot/src/test/java/org/acme/travels/security/oidc/springboot/ApprovalsProcessTest.java @@ -25,14 +25,12 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; @@ -44,6 +42,8 @@ import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit.jupiter.SpringExtension; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -80,6 +80,7 @@ public void testApprovalProcess() { results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -122,9 +123,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -135,8 +139,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/kogito-springboot-examples/process-usertasks-with-security-springboot/src/test/java/org/acme/travels/security/springboot/ApprovalsProcessTest.java b/kogito-springboot-examples/process-usertasks-with-security-springboot/src/test/java/org/acme/travels/security/springboot/ApprovalsProcessTest.java index 2a1467f4d8..5f56251379 100644 --- a/kogito-springboot-examples/process-usertasks-with-security-springboot/src/test/java/org/acme/travels/security/springboot/ApprovalsProcessTest.java +++ b/kogito-springboot-examples/process-usertasks-with-security-springboot/src/test/java/org/acme/travels/security/springboot/ApprovalsProcessTest.java @@ -25,14 +25,12 @@ import org.acme.travels.Address; import org.acme.travels.Traveller; -import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; -import org.jbpm.process.instance.impl.humantask.phases.Claim; -import org.jbpm.process.instance.impl.workitem.Complete; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kie.kogito.Model; import org.kie.kogito.auth.IdentityProviders; import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.WorkItem; @@ -44,6 +42,8 @@ import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit.jupiter.SpringExtension; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -80,6 +80,7 @@ public void testApprovalProcess() { results.put("approved", true); processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -122,9 +123,12 @@ public void testApprovalProcessViaPhases() { List workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + KogitoWorkItemHandler handler = approvalsProcess.getKogitoWorkItemHandler(workItems.get(0).getWorkItemHandlerName()); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", true), policy)); + policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("mgmt"))); workItems = processInstance.workItems(policy); assertEquals(0, workItems.size()); @@ -135,8 +139,9 @@ public void testApprovalProcessViaPhases() { workItems = processInstance.workItems(policy); assertEquals(1, workItems.size()); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); - processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("claim", workItems.get(0).getPhaseStatus(), emptyMap(), policy)); + workItems = processInstance.workItems(policy); + processInstance.transitionWorkItem(workItems.get(0).getId(), handler.newTransition("complete", workItems.get(0).getPhaseStatus(), singletonMap("approved", false), policy)); assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); diff --git a/serverless-workflow-examples/serverless-workflow-custom-type/serverless-workflow-custom-rpc/src/main/java/org/kie/kogito/examples/sw/custom/RPCCustomWorkItemHandler.java b/serverless-workflow-examples/serverless-workflow-custom-type/serverless-workflow-custom-rpc/src/main/java/org/kie/kogito/examples/sw/custom/RPCCustomWorkItemHandler.java index 64beded70a..87dc724411 100644 --- a/serverless-workflow-examples/serverless-workflow-custom-type/serverless-workflow-custom-rpc/src/main/java/org/kie/kogito/examples/sw/custom/RPCCustomWorkItemHandler.java +++ b/serverless-workflow-examples/serverless-workflow-custom-type/serverless-workflow-custom-rpc/src/main/java/org/kie/kogito/examples/sw/custom/RPCCustomWorkItemHandler.java @@ -26,10 +26,9 @@ import jakarta.enterprise.context.ApplicationScoped; import org.kie.kogito.examples.sw.custom.CalculatorClient.OperationId; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; +import org.kie.kogito.internal.process.workitem.KogitoWorkItem; import org.kie.kogito.serverless.workflow.WorkflowWorkItemHandler; - @ApplicationScoped public class RPCCustomWorkItemHandler extends WorkflowWorkItemHandler { @@ -37,23 +36,23 @@ public class RPCCustomWorkItemHandler extends WorkflowWorkItemHandler { public static final String HOST = "host"; public static final String PORT = "port"; public static final String OPERATION = "operation"; - + @Override - protected Object internalExecute(KogitoWorkItem workItem, Map parameters) { + protected Object internalExecute(KogitoWorkItem workItem, Map parameters) { try { Iterator iter = parameters.values().iterator(); Map metadata = workItem.getNodeInstance().getNode().getMetaData(); String operationId = (String) metadata.get(OPERATION); if (operationId == null) { - throw new IllegalArgumentException ("Operation is a mandatory parameter"); + throw new IllegalArgumentException("Operation is a mandatory parameter"); } - return CalculatorClient.invokeOperation((String)metadata.getOrDefault(HOST,"localhost"), (int) metadata.getOrDefault(PORT, 8082), - OperationId.valueOf(operationId.toUpperCase()), (Integer)iter.next(), (Integer)iter.next()); - } catch (IOException io ) { + return CalculatorClient.invokeOperation((String) metadata.getOrDefault(HOST, "localhost"), (int) metadata.getOrDefault(PORT, 8082), + OperationId.valueOf(operationId.toUpperCase()), (Integer) iter.next(), (Integer) iter.next()); + } catch (IOException io) { throw new UncheckedIOException(io); } } - + @Override public String getName() { return NAME;