This is an automated email from the ASF dual-hosted git repository.

pefernan pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git


The following commit(s) were added to refs/heads/main by this push:
     new 6294c3668e [incubator-kie-issues-1959] Process instance out of sync 
when completing usertasks in parallel gateway with async Service Tasks (#3919)
6294c3668e is described below

commit 6294c3668e704687ab2911e7085b3ec1d327ced6
Author: Pere Fernández <[email protected]>
AuthorDate: Mon May 19 11:33:49 2025 +0200

    [incubator-kie-issues-1959] Process instance out of sync when completing 
usertasks in parallel gateway with async Service Tasks (#3919)
    
    * [incubator-kie-issues-1959] Process instance out of sync when completing 
usertasks in parallel gateway with async Service Tasks
    
    * - restored legacyConfigRoot
    - fixed operation name on SB codegen
    
    * - added validation
---
 .../api/context/ContextAttributesConstants.java    |   2 +
 .../faultTolerance/FaultToleranceAnnotator.java}   |  17 ++-
 .../codegen/faultTolerance/FaultToleranceUtil.java |  45 ++++++
 .../impl/AbstractFaultToleranceAnnotator.java}     |  15 +-
 .../impl/QuarkusFaultToleranceAnnotator.java}      |  26 ++--
 .../impl/SpringBootFaultToleranceAnnotator.java    |  55 ++++++++
 .../kie/kogito/codegen/process/ProcessCodegen.java |   4 +-
 .../codegen/process/ProcessResourceGenerator.java  |  34 ++++-
 .../kogito/codegen/process/util/CodegenUtil.java   |  15 ++
 .../kogito/codegen/usertask/UserTaskCodegen.java   |  74 ++++++++--
 .../process/ProcessResourceGeneratorTest.java      | 139 ++++++++++---------
 .../codegen/usertask/UserTaskCodegenTest.java      | 154 +++++++++++++++++++++
 .../common/deployment/KogitoAssetsProcessor.java   |   8 ++
 .../kogito-quarkus-processes-deployment/pom.xml    |   4 +
 .../deployment/FaultToleranceProcessor.java        |  54 ++++++++
 .../kogito-quarkus-processes/pom.xml               |   4 +
 .../kogito-processes-spring-boot-starter/pom.xml   |   4 +
 17 files changed, 551 insertions(+), 103 deletions(-)

diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
 
b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
index 826317459e..ce08076802 100644
--- 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
+++ 
b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
@@ -27,6 +27,8 @@ public final class ContextAttributesConstants {
 
     public static final String PROCESS_AUTO_SVG_MAPPING = 
"processAutoSVGMapping";
 
+    public static final String KOGITO_FAULT_TOLERANCE_ENABLED = 
"kogito.faultToleranceEnabled";
+
     private ContextAttributesConstants() {
     }
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceAnnotator.java
similarity index 65%
copy from 
kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
copy to 
kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceAnnotator.java
index 826317459e..763a586f13 100644
--- 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceAnnotator.java
@@ -16,17 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.kie.kogito.codegen.api.context;
+package org.kie.kogito.codegen.faultTolerance;
 
-public final class ContextAttributesConstants {
+import com.github.javaparser.ast.body.MethodDeclaration;
 
-    /**
-     * OpenAPI Generator Descriptors with information of every REST client 
generated indexed by the spec resource file.
-     */
-    public static final String OPENAPI_DESCRIPTORS = "openApiDescriptor";
+/**
+ * Helper class to add FaultTolerance annotation
+ */
+public interface FaultToleranceAnnotator {
 
-    public static final String PROCESS_AUTO_SVG_MAPPING = 
"processAutoSVGMapping";
+    void addFaultToleranceAnnotations(MethodDeclaration methodDeclaration);
 
-    private ContextAttributesConstants() {
-    }
+    String getRetryAnnotationName();
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceUtil.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceUtil.java
new file mode 100644
index 0000000000..811d563925
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/FaultToleranceUtil.java
@@ -0,0 +1,45 @@
+/*
+ * 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.kie.kogito.codegen.faultTolerance;
+
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.kie.kogito.codegen.api.context.impl.QuarkusKogitoBuildContext;
+import org.kie.kogito.codegen.api.context.impl.SpringBootKogitoBuildContext;
+import 
org.kie.kogito.codegen.faultTolerance.impl.QuarkusFaultToleranceAnnotator;
+import 
org.kie.kogito.codegen.faultTolerance.impl.SpringBootFaultToleranceAnnotator;
+import org.kie.kogito.codegen.process.ProcessCodegenException;
+
+public class FaultToleranceUtil {
+
+    private FaultToleranceUtil() {
+        // This is a utility class and shouldn't be instantiated.
+    }
+
+    public static FaultToleranceAnnotator 
lookFaultToleranceAnnotatorForContext(KogitoBuildContext context) {
+        if (QuarkusKogitoBuildContext.CONTEXT_NAME.equals(context.name())) {
+            return new QuarkusFaultToleranceAnnotator(context);
+        } else if 
(SpringBootKogitoBuildContext.CONTEXT_NAME.equals(context.name())) {
+            return new SpringBootFaultToleranceAnnotator(context);
+        } else {
+            throw new ProcessCodegenException("Kogito Fault Tolerance not 
allowed for context: " + context.name());
+        }
+    }
+
+}
diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/AbstractFaultToleranceAnnotator.java
similarity index 65%
copy from 
kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
copy to 
kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/AbstractFaultToleranceAnnotator.java
index 826317459e..27de34111f 100644
--- 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/AbstractFaultToleranceAnnotator.java
@@ -16,17 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.kie.kogito.codegen.api.context;
+package org.kie.kogito.codegen.faultTolerance.impl;
 
-public final class ContextAttributesConstants {
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.kie.kogito.codegen.faultTolerance.FaultToleranceAnnotator;
 
-    /**
-     * OpenAPI Generator Descriptors with information of every REST client 
generated indexed by the spec resource file.
-     */
-    public static final String OPENAPI_DESCRIPTORS = "openApiDescriptor";
+public abstract class AbstractFaultToleranceAnnotator implements 
FaultToleranceAnnotator {
 
-    public static final String PROCESS_AUTO_SVG_MAPPING = 
"processAutoSVGMapping";
+    protected KogitoBuildContext context;
 
-    private ContextAttributesConstants() {
+    public AbstractFaultToleranceAnnotator(KogitoBuildContext context) {
+        this.context = context;
     }
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/QuarkusFaultToleranceAnnotator.java
similarity index 53%
copy from 
kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
copy to 
kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/QuarkusFaultToleranceAnnotator.java
index 826317459e..a4071863c9 100644
--- 
a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/ContextAttributesConstants.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/QuarkusFaultToleranceAnnotator.java
@@ -16,17 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.kie.kogito.codegen.api.context;
+package org.kie.kogito.codegen.faultTolerance.impl;
 
-public final class ContextAttributesConstants {
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
 
-    /**
-     * OpenAPI Generator Descriptors with information of every REST client 
generated indexed by the spec resource file.
-     */
-    public static final String OPENAPI_DESCRIPTORS = "openApiDescriptor";
+import com.github.javaparser.ast.body.MethodDeclaration;
 
-    public static final String PROCESS_AUTO_SVG_MAPPING = 
"processAutoSVGMapping";
+public class QuarkusFaultToleranceAnnotator extends 
AbstractFaultToleranceAnnotator {
 
-    private ContextAttributesConstants() {
+    public static final String RETRY_ANNOTATION = 
"org.eclipse.microprofile.faulttolerance.Retry";
+
+    public QuarkusFaultToleranceAnnotator(KogitoBuildContext context) {
+        super(context);
+    }
+
+    @Override
+    public String getRetryAnnotationName() {
+        return RETRY_ANNOTATION;
+    }
+
+    @Override
+    public void addFaultToleranceAnnotations(MethodDeclaration 
methodDeclaration) {
+        methodDeclaration.addAnnotation(RETRY_ANNOTATION);
     }
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/SpringBootFaultToleranceAnnotator.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/SpringBootFaultToleranceAnnotator.java
new file mode 100644
index 0000000000..7cff6a6556
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/faultTolerance/impl/SpringBootFaultToleranceAnnotator.java
@@ -0,0 +1,55 @@
+/*
+ * 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.kie.kogito.codegen.faultTolerance.impl;
+
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.*;
+
+public class SpringBootFaultToleranceAnnotator extends 
AbstractFaultToleranceAnnotator {
+    public static final String RETRY_ANNOTATION = 
"io.github.resilience4j.retry.annotation.Retry";
+
+    public SpringBootFaultToleranceAnnotator(KogitoBuildContext context) {
+        super(context);
+    }
+
+    @Override
+    public String getRetryAnnotationName() {
+        return RETRY_ANNOTATION;
+    }
+
+    @Override
+    public void addFaultToleranceAnnotations(MethodDeclaration 
methodDeclaration) {
+
+        String name = methodDeclaration.getNameAsString();
+
+        methodDeclaration
+                .addAnnotation(new NormalAnnotationExpr(new 
Name(RETRY_ANNOTATION), NodeList.nodeList(new MemberValuePair("name", new 
StringLiteralExpr(name)))));
+    }
+
+    private String getOperationName(AnnotationExpr annotationExpr) {
+        return annotationExpr.asNormalAnnotationExpr().getPairs().stream()
+                .filter(memberValuePair -> 
memberValuePair.getNameAsString().equals("summary"))
+                .findFirst()
+                .map(memberValuePair -> 
memberValuePair.getValue().asStringLiteralExpr().asString())
+                .orElse(null);
+    }
+}
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
index fdbb2541c3..c6f55b8fc7 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
@@ -73,6 +73,7 @@ import static java.util.stream.Collectors.toList;
 import static 
org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_PATH;
 import static 
org.kie.kogito.codegen.process.util.BusinessCalendarUtil.conditionallyAddCustomBusinessCalendar;
 import static 
org.kie.kogito.codegen.process.util.CodegenUtil.generatorProperty;
+import static 
org.kie.kogito.codegen.process.util.CodegenUtil.isFaultToleranceEnabled;
 import static 
org.kie.kogito.codegen.process.util.CodegenUtil.isTransactionEnabled;
 import static 
org.kie.kogito.grafana.GrafanaConfigurationWriter.buildDashboardName;
 import static 
org.kie.kogito.grafana.GrafanaConfigurationWriter.generateOperationalDashboard;
@@ -378,7 +379,8 @@ public class ProcessCodegen extends AbstractGenerator {
                         
.withWorkItems(processIdToWorkItemModel.get(workFlowProcess.getId()))
                         .withSignals(metaData.getSignals())
                         .withTriggers(metaData.isStartable(), 
metaData.isDynamic(), metaData.getTriggers())
-                        .withTransaction(isTransactionEnabled(this, 
context()));
+                        .withTransaction(isTransactionEnabled(this, context()))
+                        
.withFaultTolerance(isFaultToleranceEnabled(context()));
 
                 rgs.add(processResourceGenerator);
             }
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
index 207af9e636..67a7a7ca4d 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
@@ -44,6 +44,7 @@ import org.kie.kogito.codegen.api.template.TemplatedGenerator;
 import org.kie.kogito.codegen.core.BodyDeclarationComparator;
 import org.kie.kogito.codegen.core.CodegenUtils;
 import org.kie.kogito.codegen.core.GeneratorConfig;
+import org.kie.kogito.codegen.faultTolerance.FaultToleranceAnnotator;
 import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
 import org.kie.kogito.internal.utils.ConversionUtils;
 import org.slf4j.Logger;
@@ -69,6 +70,7 @@ import com.github.javaparser.ast.type.Type;
 
 import static com.github.javaparser.StaticJavaParser.parse;
 import static org.kie.kogito.codegen.core.CodegenUtils.interpolateTypes;
+import static 
org.kie.kogito.codegen.faultTolerance.FaultToleranceUtil.lookFaultToleranceAnnotatorForContext;
 import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeClassName;
 import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeJavaName;
 
@@ -102,6 +104,7 @@ public class ProcessResourceGenerator {
     private boolean startable;
     private boolean dynamic;
     private boolean transactionEnabled;
+    private boolean faultToleranceEnabled;
     private List<TriggerMetaData> triggers;
 
     private List<WorkItemModelMetaData> workItems;
@@ -151,6 +154,11 @@ public class ProcessResourceGenerator {
         return this;
     }
 
+    public ProcessResourceGenerator withFaultTolerance(boolean 
faultToleranceEnabled) {
+        this.faultToleranceEnabled = faultToleranceEnabled;
+        return this;
+    }
+
     public String getTaskModelFactory() {
         return taskModelFactoryUnit.toString();
     }
@@ -241,6 +249,8 @@ public class ProcessResourceGenerator {
 
         manageTransactional(toReturn);
 
+        manageFaultTolerance(toReturn);
+
         template.getMembers().sort(new BodyDeclarationComparator());
         return toReturn;
     }
@@ -402,6 +412,10 @@ public class ProcessResourceGenerator {
         }
     }
 
+    private boolean isTransactionEnabled() {
+        return transactionEnabled && context.hasDI() && !isServerless();
+    }
+
     /**
      * Conditionally add the <code>Transactional</code> annotation
      * 
@@ -409,7 +423,7 @@ public class ProcessResourceGenerator {
      *
      */
     protected void manageTransactional(CompilationUnit compilationUnit) {
-        if (transactionEnabled && context.hasDI() && !isServerless()) { // 
disabling transaction for serverless
+        if (isTransactionEnabled()) { // disabling transaction for serverless
             LOG.debug("Transaction is enabled, adding annotations...");
             DependencyInjectionAnnotator dependencyInjectionAnnotator = 
context.getDependencyInjectionAnnotator();
             getRestMethods(compilationUnit)
@@ -417,6 +431,24 @@ public class ProcessResourceGenerator {
         }
     }
 
+    /**
+     * Conditionally add the Fault Tolerance annotations
+     *
+     * @param compilationUnit
+     *
+     */
+    protected void manageFaultTolerance(CompilationUnit compilationUnit) {
+        if (faultToleranceEnabled && !isServerless()) {// disabling fault 
tolerance for serverless
+            if (!isTransactionEnabled()) {
+                throw new ProcessCodegenException("Fault tolerance is enabled, 
but transactions are disabled. Please enable transactions before fault 
tolerance.");
+            }
+            LOG.debug("Fault tolerance is enabled, adding annotations...");
+            FaultToleranceAnnotator annotator = 
lookFaultToleranceAnnotatorForContext(context);
+            getRestMethods(compilationUnit)
+                    .forEach(annotator::addFaultToleranceAnnotations);
+        }
+    }
+
     /**
      * Retrieves all the <b>Rest endpoint</b> <code>MethodDeclaration</code>s 
from the given
      * <code>CompilationUnit</code>
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
index 1e33a95861..c7c1d414f7 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
@@ -26,6 +26,8 @@ import 
org.kie.kogito.codegen.api.context.impl.JavaKogitoBuildContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static 
org.kie.kogito.codegen.api.context.ContextAttributesConstants.KOGITO_FAULT_TOLERANCE_ENABLED;
+
 public final class CodegenUtil {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(CodegenUtil.class);
@@ -34,6 +36,11 @@ public final class CodegenUtil {
      */
     public static final String TRANSACTION_ENABLED = "transactionEnabled";
 
+    /**
+     * Flag used to configure fault tolerance enabling. Default to 
<code>true</code>
+     */
+    public static final String FAULT_TOLERANCE_ENABLED = 
"faultToleranceEnabled";
+
     private CodegenUtil() {
         // do nothing
     }
@@ -108,4 +115,12 @@ public final class CodegenUtil {
     private static String getApplicationProperty(KogitoBuildContext context, 
String property) {
         return context.getApplicationProperty(property).orElseThrow(() -> new 
IllegalArgumentException("Property " + property + " defined but does not 
contain proper value"));
     }
+
+    public static boolean isFaultToleranceEnabled(KogitoBuildContext context) {
+        boolean isFaultToleranceEnabled = 
context.getApplicationProperty(KOGITO_FAULT_TOLERANCE_ENABLED)
+                .map(Boolean::parseBoolean)
+                .orElse(true);
+
+        return !JavaKogitoBuildContext.CONTEXT_NAME.equals(context.name()) && 
isFaultToleranceEnabled;
+    }
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
index 83a6c998f3..5afa147e1c 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
@@ -33,6 +33,7 @@ import java.util.function.Predicate;
 
 import org.drools.codegen.common.GeneratedFile;
 import org.drools.codegen.common.GeneratedFileType;
+import org.drools.codegen.common.rest.RestAnnotator;
 import org.jbpm.bpmn2.xml.BPMNDISemanticModule;
 import org.jbpm.bpmn2.xml.BPMNExtensionsSemanticModule;
 import org.jbpm.bpmn2.xml.BPMNSemanticModule;
@@ -48,9 +49,9 @@ import org.kie.kogito.codegen.api.context.KogitoBuildContext;
 import org.kie.kogito.codegen.api.io.CollectedResource;
 import org.kie.kogito.codegen.api.template.TemplatedGenerator;
 import org.kie.kogito.codegen.core.AbstractGenerator;
+import org.kie.kogito.codegen.faultTolerance.FaultToleranceAnnotator;
 import org.kie.kogito.codegen.process.ProcessCodegenException;
 import org.kie.kogito.codegen.process.ProcessParsingException;
-import org.kie.kogito.codegen.process.util.CodegenUtil;
 import org.kie.kogito.internal.SupportedExtensions;
 import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
 import org.kie.kogito.process.validation.ValidationException;
@@ -77,6 +78,9 @@ import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
 
 import static java.util.stream.Collectors.toList;
+import static 
org.kie.kogito.codegen.faultTolerance.FaultToleranceUtil.lookFaultToleranceAnnotatorForContext;
+import static 
org.kie.kogito.codegen.process.util.CodegenUtil.isFaultToleranceEnabled;
+import static 
org.kie.kogito.codegen.process.util.CodegenUtil.isTransactionEnabled;
 import static 
org.kie.kogito.serverless.workflow.utils.ServerlessWorkflowUtils.FAIL_ON_ERROR_PROPERTY;
 
 public class UserTaskCodegen extends AbstractGenerator {
@@ -157,24 +161,78 @@ public class UserTaskCodegen extends AbstractGenerator {
         }
 
         if (context().hasRESTForGenerator(this)) {
-            generatedFiles.add(generateRestEndpiont());
+            generatedFiles.add(generateRestEndpoint());
         }
 
         return generatedFiles;
     }
 
-    public GeneratedFile generateRestEndpiont() {
+    public GeneratedFile generateRestEndpoint() {
         String packageName = context().getPackageName();
-        CompilationUnit compilationUnit = 
restTemplateGenerator.compilationUnitOrThrow("Not rest endpoints template found 
for user tasks");
+        CompilationUnit compilationUnit = createRestEndpointCompilationUnit();
         compilationUnit.setPackageDeclaration(packageName);
-        if (CodegenUtil.isTransactionEnabled(this, context())) {
-            
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).forEach(context().getDependencyInjectionAnnotator()::withTransactional);
-        }
-        String className = 
compilationUnit.findFirst(ClassOrInterfaceDeclaration.class).get().getNameAsString();
+
+        manageTransactional(compilationUnit);
+
+        manageFaultTolerance(compilationUnit);
+
+        String className = 
compilationUnit.findFirst(ClassOrInterfaceDeclaration.class)
+                .orElseThrow(() -> new 
ProcessCodegenException("UserTaskResourceTemplate doesn't contain a class or 
interface declaration!"))
+                .getNameAsString();
+
         Path basePath = UserTaskCodegenHelper.path(packageName);
+
         return new GeneratedFile(GeneratedFileType.REST, 
basePath.resolve(className + ".java"), compilationUnit.toString());
     }
 
+    protected CompilationUnit createRestEndpointCompilationUnit() {
+        return restTemplateGenerator.compilationUnitOrThrow("Not rest 
endpoints template found for user tasks");
+    }
+
+    /**
+     * Conditionally add the <code>Transactional</code> annotation
+     *
+     * @param compilationUnit
+     *
+     */
+    protected void manageTransactional(CompilationUnit compilationUnit) {
+        if (isTransactionEnabled(this, context())) {
+            
getRestMethods(compilationUnit).forEach(context().getDependencyInjectionAnnotator()::withTransactional);
+        }
+    }
+
+    /**
+     * Conditionally add the Fault Tolerance annotations
+     *
+     * @param compilationUnit
+     *
+     */
+    protected void manageFaultTolerance(CompilationUnit compilationUnit) {
+        if (isFaultToleranceEnabled(context())) {
+            if (!isTransactionEnabled(this, context())) {
+                throw new ProcessCodegenException("Fault tolerance is enabled, 
but transactions are disabled. Please enable transactions before fault 
tolerance.");
+            }
+            FaultToleranceAnnotator annotator = 
lookFaultToleranceAnnotatorForContext(context());
+            getRestMethods(compilationUnit)
+                    .forEach(annotator::addFaultToleranceAnnotations);
+        }
+    }
+
+    /**
+     * Retrieves all the <b>Rest endpoint</b> <code>MethodDeclaration</code>s 
from the given
+     * <code>CompilationUnit</code>
+     *
+     * @param compilationUnit
+     * @return
+     */
+    protected Collection<MethodDeclaration> getRestMethods(CompilationUnit 
compilationUnit) {
+        RestAnnotator restAnnotator = context().getRestAnnotator();
+        return compilationUnit.findAll(MethodDeclaration.class)
+                .stream()
+                .filter(restAnnotator::isRestAnnotated)
+                .toList();
+    }
+
     public GeneratedFile generateProducer() {
         String packageName = context().getPackageName();
         CompilationUnit compilationUnit = 
producerTemplateGenerator.compilationUnitOrThrow("No producer template found 
for user tasks");
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/ProcessResourceGeneratorTest.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/ProcessResourceGeneratorTest.java
index 551d5b48b5..3babba7116 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/ProcessResourceGeneratorTest.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/ProcessResourceGeneratorTest.java
@@ -20,7 +20,6 @@ package org.kie.kogito.codegen.process;
 
 import java.io.File;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Predicate;
@@ -36,8 +35,8 @@ import org.kie.api.definition.process.Process;
 import org.kie.kogito.codegen.api.AddonsConfig;
 import org.kie.kogito.codegen.api.context.KogitoBuildContext;
 import org.kie.kogito.codegen.api.context.impl.JavaKogitoBuildContext;
-import org.kie.kogito.codegen.process.util.CodegenUtil;
-import org.kie.kogito.codegen.usertask.UserTaskCodegen;
+import org.kie.kogito.codegen.faultTolerance.FaultToleranceAnnotator;
+import org.kie.kogito.codegen.faultTolerance.FaultToleranceUtil;
 import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
 
 import com.github.javaparser.StaticJavaParser;
@@ -50,11 +49,10 @@ import com.github.javaparser.ast.expr.MemberValuePair;
 import com.github.javaparser.ast.expr.NormalAnnotationExpr;
 import com.github.javaparser.ast.expr.StringLiteralExpr;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.*;
 import static 
org.kie.kogito.codegen.process.ProcessResourceGenerator.INVALID_CONTEXT_TEMPLATE;
 
-class ProcessResourceGeneratorTest {
+public class ProcessResourceGeneratorTest {
 
     private static final String SIGNAL_METHOD = "signal_";
     private static final List<String> JAVA_AND_QUARKUS_REST_ANNOTATIONS = 
List.of("DELETE", "GET", "POST");
@@ -187,10 +185,10 @@ class ProcessResourceGeneratorTest {
         KogitoBuildContext kogitoBuildContext = contextBuilder.build();
         Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
         // before processResourceGenerator.manageTransactional, the annotation 
is not there
-        testTransaction(restEndpoints, kogitoBuildContext, false);
+        testTransactionAnnotationIsPresent(restEndpoints, kogitoBuildContext, 
false);
         processResourceGenerator.manageTransactional(compilationUnit);
-        // the annotation is (conditionally) add after 
processResourceGenerator.manageTransactional
-        testTransaction(restEndpoints, kogitoBuildContext, transactionEnabled);
+        // the annotation is (conditionally) added after 
processResourceGenerator.manageTransactional
+        testTransactionAnnotationIsPresent(restEndpoints, kogitoBuildContext, 
transactionEnabled);
     }
 
     @ParameterizedTest
@@ -206,82 +204,80 @@ class ProcessResourceGeneratorTest {
         KogitoBuildContext kogitoBuildContext = contextBuilder.build();
         Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
         // before processResourceGenerator.manageTransactional, the annotation 
is not there
-        testTransaction(restEndpoints, kogitoBuildContext, false);
+        testTransactionAnnotationIsPresent(restEndpoints, kogitoBuildContext, 
false);
         processResourceGenerator.manageTransactional(compilationUnit);
-        // the annotation is (conditionally) add after 
processResourceGenerator.manageTransactional
-        testTransaction(restEndpoints, kogitoBuildContext, transactionEnabled);
+        // the annotation is (conditionally) added after 
processResourceGenerator.manageTransactional
+        testTransactionAnnotationIsPresent(restEndpoints, kogitoBuildContext, 
transactionEnabled);
     }
 
     @ParameterizedTest
     
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
-    void 
testUserTaskManageTransactionalEnabledByDefault(KogitoBuildContext.Builder 
contextBuilder) {
-        KogitoBuildContext context = contextBuilder.build();
-        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
-        CompilationUnit compilationUnit = StaticJavaParser.parse(new 
String(userTaskCodegen.generateRestEndpiont().contents()));
-        List<MethodDeclaration> restEndpoints = 
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).toList();
-        assertThat(restEndpoints).isNotEmpty();
-        for (MethodDeclaration method : restEndpoints) {
-            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isPresent();
-        }
-    }
+    void 
testProcessRestResourceGenerationWithFaultToleranceDisabled(KogitoBuildContext.Builder
 contextBuilder) {
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, fileName, false, false);
+        CompilationUnit compilationUnit =
+                
processResourceGenerator.createCompilationUnit(processResourceGenerator.createTemplatedGeneratorBuilder());
+        assertThat(compilationUnit).isNotNull();
 
-    @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
-    void testUserTaskManageTransactionalDisabled(KogitoBuildContext.Builder 
contextBuilder) {
         KogitoBuildContext context = contextBuilder.build();
-        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
-        
context.setApplicationProperty(CodegenUtil.generatorProperty(userTaskCodegen, 
CodegenUtil.TRANSACTION_ENABLED), "false");
-        CompilationUnit compilationUnit = StaticJavaParser.parse(new 
String(userTaskCodegen.generateRestEndpiont().contents()));
-        List<MethodDeclaration> restEndpoints = 
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).toList();
-        assertThat(restEndpoints).isNotEmpty();
-        for (MethodDeclaration method : restEndpoints) {
-            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isEmpty();
-        }
+        Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
+
+        // before processResourceGenerator.manageFaultTolerance, the 
annotation is not there
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
+
+        processResourceGenerator.manageFaultTolerance(compilationUnit);
+        // the annotation is (conditionally) added after 
processResourceGenerator.manageFaultTolerance
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
     }
 
     @ParameterizedTest
     
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
-    void 
testUserTaskManageTransactionalGeneratorDisabled(KogitoBuildContext.Builder 
contextBuilder) {
+    void 
testProcessRestResourceGenerationWithFaultToleranceEnabled(KogitoBuildContext.Builder
 contextBuilder) {
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, fileName, true, true);
+        CompilationUnit compilationUnit =
+                
processResourceGenerator.createCompilationUnit(processResourceGenerator.createTemplatedGeneratorBuilder());
+        assertThat(compilationUnit).isNotNull();
+
         KogitoBuildContext context = contextBuilder.build();
-        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
-        
context.setApplicationProperty(CodegenUtil.generatorProperty(userTaskCodegen, 
CodegenUtil.TRANSACTION_ENABLED), "false");
-        CompilationUnit compilationUnit = StaticJavaParser.parse(new 
String(userTaskCodegen.generateRestEndpiont().contents()));
-        List<MethodDeclaration> restEndpoints = 
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).toList();
-        assertThat(restEndpoints).isNotEmpty();
-        for (MethodDeclaration method : restEndpoints) {
-            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isEmpty();
-        }
+        Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
+
+        // before processResourceGenerator.manageFaultTolerance, the 
annotation is not there
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
+
+        processResourceGenerator.manageFaultTolerance(compilationUnit);
+        // the annotation is (conditionally) added after 
processResourceGenerator.manageFaultTolerance
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, true);
     }
 
     @ParameterizedTest
     
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
-    void testUserTaskManageTransactionalEnabled(KogitoBuildContext.Builder 
contextBuilder) {
-        KogitoBuildContext context = contextBuilder.build();
-        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
-        
context.setApplicationProperty(CodegenUtil.generatorProperty(userTaskCodegen, 
CodegenUtil.TRANSACTION_ENABLED), "true");
-        CompilationUnit compilationUnit = StaticJavaParser.parse(new 
String(userTaskCodegen.generateRestEndpiont().contents()));
-        List<MethodDeclaration> restEndpoints = 
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).toList();
-        assertThat(restEndpoints).isNotEmpty();
-        for (MethodDeclaration method : restEndpoints) {
-            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isPresent();
-        }
+    void 
testProcessRestResourceGenerationWithFaultToleranceEnabledWithTransactionsDisabled(KogitoBuildContext.Builder
 contextBuilder) {
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, fileName, false, true);
+        CompilationUnit compilationUnit =
+                
processResourceGenerator.createCompilationUnit(processResourceGenerator.createTemplatedGeneratorBuilder());
+        assertThat(compilationUnit).isNotNull();
+
+        assertThatThrownBy(() -> {
+            processResourceGenerator.manageFaultTolerance(compilationUnit);
+        }).isInstanceOf(ProcessCodegenException.class)
+                .hasMessageContaining("Fault tolerance is enabled, but 
transactions are disabled. Please enable transactions before fault tolerance.");
     }
 
-    @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
-    void 
testUserTaskManageTransactionalGeneratorEnabled(KogitoBuildContext.Builder 
contextBuilder) {
-        KogitoBuildContext context = contextBuilder.build();
-        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
-        
context.setApplicationProperty(CodegenUtil.generatorProperty(userTaskCodegen, 
CodegenUtil.TRANSACTION_ENABLED), "true");
-        CompilationUnit compilationUnit = StaticJavaParser.parse(new 
String(userTaskCodegen.generateRestEndpiont().contents()));
-        List<MethodDeclaration> restEndpoints = 
compilationUnit.findAll(MethodDeclaration.class).stream().filter(MethodDeclaration::isPublic).toList();
-        assertThat(restEndpoints).isNotEmpty();
+    public static void 
testFaultToleranceAnnotationIsPresent(Collection<MethodDeclaration> 
restEndpoints, KogitoBuildContext context, boolean shouldAnnotationBeThere) {
+        FaultToleranceAnnotator faultToleranceAnnotator = 
FaultToleranceUtil.lookFaultToleranceAnnotatorForContext(context);
+
         for (MethodDeclaration method : restEndpoints) {
-            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isPresent();
+            if (shouldAnnotationBeThere) {
+                assertThat(findAnnotationExpr(method, 
faultToleranceAnnotator.getRetryAnnotationName())).isPresent();
+            } else {
+                assertThat(findAnnotationExpr(method, 
faultToleranceAnnotator.getRetryAnnotationName())).isNotPresent();
+            }
         }
     }
 
-    Optional<AnnotationExpr> findAnnotationExpr(MethodDeclaration method, 
String fqn) {
+    public static Optional<AnnotationExpr> 
findAnnotationExpr(MethodDeclaration method, String fqn) {
         for (AnnotationExpr expr : method.getAnnotations()) {
             if (expr.getNameAsString().equals(fqn)) {
                 return Optional.of(expr);
@@ -290,7 +286,7 @@ class ProcessResourceGeneratorTest {
         return Optional.empty();
     }
 
-    void testTransaction(Collection<MethodDeclaration> restEndpoints,
+    public static void 
testTransactionAnnotationIsPresent(Collection<MethodDeclaration> restEndpoints,
             KogitoBuildContext kogitoBuildContext,
             boolean enabled) {
         String transactionalAnnotation =
@@ -331,18 +327,24 @@ class ProcessResourceGeneratorTest {
 
     private CompilationUnit getCompilationUnit(KogitoBuildContext.Builder 
contextBuilder,
             KogitoWorkflowProcess process) {
-        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, process, true);
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, process, true, false);
         return StaticJavaParser.parse(processResourceGenerator.generate());
     }
 
     private ProcessResourceGenerator 
getProcessResourceGenerator(KogitoBuildContext.Builder contextBuilder,
             String fileName, boolean withTransaction) {
-        return getProcessResourceGenerator(contextBuilder, 
parseProcess(fileName), withTransaction);
+        return getProcessResourceGenerator(contextBuilder, 
parseProcess(fileName), withTransaction, false);
+    }
+
+    private ProcessResourceGenerator 
getProcessResourceGenerator(KogitoBuildContext.Builder contextBuilder,
+            String fileName, boolean withTransaction, boolean 
wihtFaultTolerance) {
+        return getProcessResourceGenerator(contextBuilder, 
parseProcess(fileName), withTransaction, wihtFaultTolerance);
     }
 
     private ProcessResourceGenerator 
getProcessResourceGenerator(KogitoBuildContext.Builder contextBuilder,
             KogitoWorkflowProcess process,
-            boolean withTransaction) {
+            boolean withTransaction,
+            boolean withFaultTolerance) {
         KogitoBuildContext context = createContext(contextBuilder);
 
         ProcessExecutableModelGenerator execModelGen =
@@ -361,7 +363,8 @@ class ProcessResourceGeneratorTest {
         toReturn
                 .withSignals(metaData.getSignals())
                 .withTriggers(metaData.isStartable(), metaData.isDynamic(), 
metaData.getTriggers())
-                .withTransaction(withTransaction);
+                .withTransaction(withTransaction)
+                .withFaultTolerance(withFaultTolerance);
         return toReturn;
     }
 
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/usertask/UserTaskCodegenTest.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/usertask/UserTaskCodegenTest.java
new file mode 100644
index 0000000000..2aa3ad45e4
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/usertask/UserTaskCodegenTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.kie.kogito.codegen.usertask;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import org.drools.codegen.common.rest.RestAnnotator;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.kie.kogito.codegen.process.ProcessCodegenException;
+import org.kie.kogito.codegen.process.util.CodegenUtil;
+
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.MethodDeclaration;
+
+import static java.util.Collections.emptyList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.kie.kogito.codegen.process.ProcessResourceGeneratorTest.*;
+
+public class UserTaskCodegenTest {
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void 
testUserTaskManageTransactionalEnabledByDefault(KogitoBuildContext.Builder 
contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        Collection<MethodDeclaration> restEndpoints = 
getRestMethods(compilationUnit, context);
+        assertThat(restEndpoints).isNotEmpty();
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, false);
+
+        userTaskCodegen.manageTransactional(compilationUnit);
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, true);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testUserTaskManageTransactionalDisabled(KogitoBuildContext.Builder 
contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+        
context.setApplicationProperty(CodegenUtil.globalProperty(CodegenUtil.TRANSACTION_ENABLED),
 "false");
+
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        Collection<MethodDeclaration> restEndpoints = 
getRestMethods(compilationUnit, context);
+        assertThat(restEndpoints).isNotEmpty();
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, false);
+
+        userTaskCodegen.manageTransactional(compilationUnit);
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, false);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testUserTaskManageTransactionalEnabled(KogitoBuildContext.Builder 
contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+        
context.setApplicationProperty(CodegenUtil.globalProperty(CodegenUtil.TRANSACTION_ENABLED),
 "true");
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        Collection<MethodDeclaration> restEndpoints = 
getRestMethods(compilationUnit, context);
+        assertThat(restEndpoints).isNotEmpty();
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, false);
+
+        userTaskCodegen.manageTransactional(compilationUnit);
+
+        testTransactionAnnotationIsPresent(restEndpoints, context, true);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testUserTaskFaultToleranceDisabled(KogitoBuildContext.Builder 
contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+        
context.setApplicationProperty(CodegenUtil.globalProperty(CodegenUtil.FAULT_TOLERANCE_ENABLED),
 "false");
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        Collection<MethodDeclaration> restEndpoints = 
getRestMethods(compilationUnit, context);
+        assertThat(restEndpoints).isNotEmpty();
+
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
+
+        userTaskCodegen.manageFaultTolerance(compilationUnit);
+
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testUserTaskFaultToleranceEnabled(KogitoBuildContext.Builder 
contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        Collection<MethodDeclaration> restEndpoints = 
getRestMethods(compilationUnit, context);
+        assertThat(restEndpoints).isNotEmpty();
+
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, false);
+
+        userTaskCodegen.manageFaultTolerance(compilationUnit);
+
+        testFaultToleranceAnnotationIsPresent(restEndpoints, context, true);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void 
testUserTaskFaultToleranceEnabledWithTransactionsDisabled(KogitoBuildContext.Builder
 contextBuilder) {
+        KogitoBuildContext context = contextBuilder.build();
+        
context.setApplicationProperty(CodegenUtil.globalProperty(CodegenUtil.TRANSACTION_ENABLED),
 "false");
+
+        UserTaskCodegen userTaskCodegen = new UserTaskCodegen(context, 
Collections.emptyList());
+
+        CompilationUnit compilationUnit = 
userTaskCodegen.createRestEndpointCompilationUnit();
+
+        assertThatThrownBy(() -> {
+            userTaskCodegen.manageFaultTolerance(compilationUnit);
+        }).isInstanceOf(ProcessCodegenException.class)
+                .hasMessageContaining("Fault tolerance is enabled, but 
transactions are disabled. Please enable transactions before fault tolerance.");
+    }
+
+    protected Collection<MethodDeclaration> getRestMethods(CompilationUnit 
compilationUnit, KogitoBuildContext context) {
+        RestAnnotator restAnnotator = context.getRestAnnotator();
+        return compilationUnit.findAll(MethodDeclaration.class).stream()
+                .filter(restAnnotator::isRestAnnotated)
+                .collect(Collectors.toList());
+    }
+}
diff --git 
a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java
 
b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java
index 346a0f5a40..8dd96912d9 100644
--- 
a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java
+++ 
b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java
@@ -80,6 +80,7 @@ import static 
org.drools.codegen.common.GeneratedFileType.COMPILED_CLASS;
 import static 
org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils.compileGeneratedSources;
 import static 
org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils.makeBuildItems;
 import static 
org.kie.efesto.common.api.constants.Constants.INDEXFILE_DIRECTORY_PROPERTY;
+import static 
org.kie.kogito.codegen.api.context.ContextAttributesConstants.KOGITO_FAULT_TOLERANCE_ENABLED;
 import static 
org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.HOT_RELOAD_SUPPORT_PATH;
 import static 
org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.dumpFilesToDisk;
 import static 
org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.getHotReloadSupportSource;
@@ -278,6 +279,13 @@ public class KogitoAssetsProcessor {
         if (!hasRestCapabilities && kogitoGenerateRest(context).orElse(true)) {
             throw new MissingRestCapabilityException();
         }
+
+        // disable Fault Tolerance if SmallRye Fault Tolerance extension is 
not available (user can override via property)
+        if (!capabilities.isPresent(Capability.SMALLRYE_FAULT_TOLERANCE)) {
+            context.setApplicationProperty(KOGITO_FAULT_TOLERANCE_ENABLED, 
"false");
+            LOGGER.info("Disabling Kogito Fault Tolerance because SmallRye 
Fault Tolerance extension is not available");
+        }
+
     }
 
     private Optional<Boolean> kogitoGenerateRest(KogitoBuildContext context) {
diff --git 
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/pom.xml
 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/pom.xml
index b1f2fef2c0..0ec1d2bfc4 100644
--- 
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/pom.xml
+++ 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/pom.xml
@@ -49,6 +49,10 @@
       <groupId>io.quarkus</groupId>
       <artifactId>quarkus-narayana-jta-deployment</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-smallrye-fault-tolerance-deployment</artifactId>
+    </dependency>
     <!-- test -->
     <dependency>
       <groupId>io.quarkus</groupId>
diff --git 
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/FaultToleranceProcessor.java
 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/FaultToleranceProcessor.java
new file mode 100644
index 0000000000..c3a1d49d34
--- /dev/null
+++ 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/FaultToleranceProcessor.java
@@ -0,0 +1,54 @@
+/*
+ * 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.kie.kogito.quarkus.processes.deployment;
+
+import java.util.function.BooleanSupplier;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+
+import io.quarkus.deployment.Capabilities;
+import io.quarkus.deployment.Capability;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
+
+import jakarta.interceptor.Interceptor;
+
+import static 
org.kie.kogito.codegen.api.context.ContextAttributesConstants.KOGITO_FAULT_TOLERANCE_ENABLED;
+
+public class FaultToleranceProcessor {
+
+    public static class IsFaultToleranceEnabled implements BooleanSupplier {
+        @Override
+        public boolean getAsBoolean() {
+            return 
ConfigProvider.getConfig().getOptionalValue(KOGITO_FAULT_TOLERANCE_ENABLED, 
Boolean.class).orElse(true);
+        }
+    }
+
+    @BuildStep(onlyIf = IsFaultToleranceEnabled.class)
+    public void setupKogitoFaultTolerance(
+            BuildProducer<SystemPropertyBuildItem> systemProperties,
+            Capabilities capabilities) {
+
+        if (capabilities.isPresent(Capability.SMALLRYE_FAULT_TOLERANCE)) {
+            systemProperties.produce(new 
SystemPropertyBuildItem("mp.fault.tolerance.interceptor.priority", 
String.valueOf(Interceptor.Priority.PLATFORM_BEFORE + 100)));
+        }
+    }
+}
diff --git 
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/pom.xml
 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/pom.xml
index 94220228ad..e3aaeb3909 100644
--- 
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/pom.xml
+++ 
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/pom.xml
@@ -60,6 +60,10 @@
       <groupId>org.eclipse.microprofile.openapi</groupId>
       <artifactId>microprofile-openapi-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-smallrye-fault-tolerance</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml 
b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
index cd9817e03e..637e0f6f9c 100644
--- a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
+++ b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
@@ -60,6 +60,10 @@
       <groupId>org.springframework</groupId>
       <artifactId>spring-tx</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.github.resilience4j</groupId>
+      <artifactId>resilience4j-spring-boot3</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to