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

gitgabrio 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 070876ffdf [incubator-kie-issues#1473] Introduce Transactional 
annotation, conditionally deleted (#3671)
070876ffdf is described below

commit 070876ffdf3be21c4f158925fc6c16f20b0476ab
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Thu Oct 3 12:04:33 2024 +0200

    [incubator-kie-issues#1473] Introduce Transactional annotation, 
conditionally deleted (#3671)
    
    * [incubator-kie-issues#1473] WIP - Implemented transactional imports and 
annotations with optional removal. Add unit tests. Small refactoring to allow 
unit testing/ TDD
    
    * [incubator-kie-issues#1473] Simplified following suggestions.
    Now the annotation is conditionally add during code generation.
    
    * [incubator-kie-issues#1473] Implemented 
KogitoContextTestUtils#restContextBuilders for rest-specific tests.
    Enforced exclusion of "Java" context from processes' rest generation.
    
    * [incubator-kie-issues#1473] Set log level to debug inside 
manageTransactional
    
    * [incubator-kie-issues#1473] Add spring-tx dependency to 
jbpm-spring-boot-starter to be always available for springboot projects
    
    * [incubator-kie-issues#1473] Add quarkus-narayana-jta dependency to 
kogito-quarkus-workflow-common to be always available for quarkus projects
    
    * [incubator-kie-issues#1473] Add quarkus-narayana-jta-deployment dependency
    
    * [incubator-kie-issues#1473] Introduce nasty workaround (delay) to avoid 
ARJUNA issues with nested threads
    
    * [incubator-kie-issues#1473] Disabling transaction for 
sonataflow-quarkus-integration-test
    
    * [incubator-kie-issues#1473] Conditionally add the thread sleep. Fix 
kogito.processes.transactionEnabled variable
    
    * [incubator-kie-issues#1473] Importing new wait strategy.
    
    * [incubator-kie-issues#1473] WIP - Experimenting Thread.join inside 
transaction (instead of Thread.sleep)
    
    * [incubator-kie-issues#1473] WIP - fix formatting
    
    * [incubator-kie-issues#1473] WIP - commented out conditionally excluded 
serverless transaction. Disable transaction workaround.
    
    * [incubator-kie-issues#1473] WIP - commented out conditionally excluded 
serverless transaction. Disable transaction workaround.
    
    * [incubator-kie-issues#1473] Disabling transaction for serverless
    
    * [incubator-kie-issues#1473] Fix formatting
    
    * [incubator-kie-issues#1473] Fix test
    
    * [incubator-kie-issues#1473] Fixed as per PR suggestion. Using 
context.hasRest() instead of name.equals("Java") to check for rest endpoint 
creation. Implemented MockQuarkusKogitoBuildContext and 
MockSpringBootKogitoBuildContext to override the hasRest method during tests.
    
    ---------
    
    Co-authored-by: Gabriele-Cardosi <[email protected]>
---
 .../impl/MockQuarkusKogitoBuildContext.java        |  51 ++++++
 .../impl/MockSpringBootKogitoBuildContext.java     |  50 ++++++
 .../codegen/api/utils/KogitoContextTestUtils.java  |  12 ++
 .../kie/kogito/codegen/process/ProcessCodegen.java |  21 ++-
 .../codegen/process/ProcessResourceGenerator.java  | 199 +++++++++++++++------
 .../RestResourceSpringTemplate.java                |   3 +-
 .../process/ProcessResourceGeneratorTest.java      | 116 ++++++++++--
 .../events/CodegenMessageStartEventTest.java       |   4 +-
 .../process/events/CodegenUserTaskTest.java        |   2 +-
 .../kogito-quarkus-processes-deployment/pom.xml    |   4 +
 .../pom.xml                                        |   4 +
 .../kogito-quarkus-workflow-common/pom.xml         |   4 +
 .../kogito-processes-spring-boot-starter/pom.xml   |   4 +
 13 files changed, 397 insertions(+), 77 deletions(-)

diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockQuarkusKogitoBuildContext.java
 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockQuarkusKogitoBuildContext.java
new file mode 100644
index 0000000000..9972c2d7f0
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockQuarkusKogitoBuildContext.java
@@ -0,0 +1,51 @@
+/*
+ * 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.api.context.impl;
+
+/**
+ * Mocked <code>QuarkusKogitoBuildContext</code> to provide <code>hasRest() = 
true</code>
+ * during test
+ */
+public class MockQuarkusKogitoBuildContext extends QuarkusKogitoBuildContext {
+
+    protected 
MockQuarkusKogitoBuildContext(MockQuarkusKogitoBuildContextBuilder builder) {
+        super(builder);
+    }
+
+    public static Builder builder() {
+        return new MockQuarkusKogitoBuildContextBuilder();
+    }
+
+    @Override
+    public boolean hasRest() {
+        return true;
+    }
+
+    protected static class MockQuarkusKogitoBuildContextBuilder extends 
QuarkusKogitoBuildContextBuilder {
+
+        protected MockQuarkusKogitoBuildContextBuilder() {
+        }
+
+        @Override
+        public MockQuarkusKogitoBuildContext build() {
+            return new MockQuarkusKogitoBuildContext(this);
+        }
+
+    }
+}
\ No newline at end of file
diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockSpringBootKogitoBuildContext.java
 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockSpringBootKogitoBuildContext.java
new file mode 100644
index 0000000000..32a865ebd1
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/MockSpringBootKogitoBuildContext.java
@@ -0,0 +1,50 @@
+/*
+ * 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.api.context.impl;
+
+/**
+ * Mocked <code>SpringBootKogitoBuildContext</code> to provide <code>hasRest() 
= true</code>
+ * during test
+ */
+public class MockSpringBootKogitoBuildContext extends 
SpringBootKogitoBuildContext {
+
+    protected 
MockSpringBootKogitoBuildContext(MockSpringBootKogitoBuildContextBuilder 
builder) {
+        super(builder);
+    }
+
+    public static Builder builder() {
+        return new MockSpringBootKogitoBuildContextBuilder();
+    }
+
+    @Override
+    public boolean hasRest() {
+        return true;
+    }
+
+    protected static class MockSpringBootKogitoBuildContextBuilder extends 
SpringBootKogitoBuildContextBuilder {
+
+        protected MockSpringBootKogitoBuildContextBuilder() {
+        }
+
+        @Override
+        public MockSpringBootKogitoBuildContext build() {
+            return new MockSpringBootKogitoBuildContext(this);
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/utils/KogitoContextTestUtils.java
 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/utils/KogitoContextTestUtils.java
index e96c2c7a34..3c7a273ea1 100644
--- 
a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/utils/KogitoContextTestUtils.java
+++ 
b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/utils/KogitoContextTestUtils.java
@@ -25,6 +25,8 @@ import java.util.stream.Stream;
 import org.junit.jupiter.params.provider.Arguments;
 import org.kie.kogito.codegen.api.context.KogitoBuildContext;
 import org.kie.kogito.codegen.api.context.impl.JavaKogitoBuildContext;
+import org.kie.kogito.codegen.api.context.impl.MockQuarkusKogitoBuildContext;
+import 
org.kie.kogito.codegen.api.context.impl.MockSpringBootKogitoBuildContext;
 import org.kie.kogito.codegen.api.context.impl.QuarkusKogitoBuildContext;
 import org.kie.kogito.codegen.api.context.impl.SpringBootKogitoBuildContext;
 
@@ -44,6 +46,16 @@ public class KogitoContextTestUtils {
                 Arguments.of(SpringBootKogitoBuildContext.builder()));
     }
 
+    /**
+     *
+     * @return <b>Mocked</b> <code>QuarkusKogitoBuildContext</code> and 
<code>SpringBootKogitoBuildContext</code> providing <code>hasRest() = 
true</code>
+     */
+    public static Stream<Arguments> restContextBuilders() {
+        return Stream.of(
+                Arguments.of(MockQuarkusKogitoBuildContext.builder()),
+                Arguments.of(MockSpringBootKogitoBuildContext.builder()));
+    }
+
     public static Predicate<String> 
mockClassAvailabilityResolver(Collection<String> includedClasses, 
Collection<String> excludedClasses) {
         return mockClassAvailabilityResolver(includedClasses, excludedClasses, 
KogitoContextTestUtils.class.getClassLoader());
     }
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 6f5ba05f7a..c360ec5e8c 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
@@ -76,6 +76,7 @@ import 
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 
 import static java.lang.String.format;
 import static java.util.stream.Collectors.toList;
+import static 
org.kie.kogito.codegen.process.ProcessResourceGenerator.TRANSACTION_ENABLED;
 import static 
org.kie.kogito.grafana.GrafanaConfigurationWriter.buildDashboardName;
 import static 
org.kie.kogito.grafana.GrafanaConfigurationWriter.generateOperationalDashboard;
 import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeClassName;
@@ -352,20 +353,23 @@ public class ProcessCodegen extends AbstractGenerator {
 
             ProcessMetaData metaData = 
processIdToMetadata.get(workFlowProcess.getId());
 
-            //Creating and adding the ResourceGenerator
-            ProcessResourceGenerator processResourceGenerator = new 
ProcessResourceGenerator(
+            //Creating and adding the ResourceGenerator for REST generation
+            if (context().hasRest()) {
+                ProcessResourceGenerator processResourceGenerator = new 
ProcessResourceGenerator(
                     context(),
                     workFlowProcess,
                     modelClassGenerator.className(),
                     execModelGen.className(),
                     applicationCanonicalName());
 
-            processResourceGenerator
+                processResourceGenerator
                     
.withUserTasks(processIdToUserTaskModel.get(workFlowProcess.getId()))
                     .withSignals(metaData.getSignals())
-                    .withTriggers(metaData.isStartable(), 
metaData.isDynamic(), metaData.getTriggers());
+                    .withTriggers(metaData.isStartable(), 
metaData.isDynamic(), metaData.getTriggers())
+                    .withTransaction(isTransactionEnabled());
 
-            rgs.add(processResourceGenerator);
+                rgs.add(processResourceGenerator);
+            }
 
             if (metaData.getTriggers() != null) {
 
@@ -468,7 +472,7 @@ public class ProcessCodegen extends AbstractGenerator {
             svgs.keySet().stream().forEach(key -> 
storeFile(GeneratedFileType.INTERNAL_RESOURCE, "META-INF/processSVG/" + key + 
".svg", svgs.get(key)));
         }
 
-        if (context().hasRESTForGenerator(this)) {
+        if (context().hasRest() && context().hasRESTForGenerator(this)) {
             final ProcessCloudEventMetaFactoryGenerator topicsGenerator =
                     new ProcessCloudEventMetaFactoryGenerator(context(), 
processExecutableModelGenerators);
             storeFile(REST_TYPE, topicsGenerator.generatedFilePath(), 
topicsGenerator.generate());
@@ -504,6 +508,11 @@ public class ProcessCodegen extends AbstractGenerator {
         return generatedFiles;
     }
 
+    protected boolean isTransactionEnabled() {
+        String processTransactionProperty = String.format("kogito.%s.%s", 
GENERATOR_NAME, TRANSACTION_ENABLED);
+        return 
"true".equalsIgnoreCase(context().getApplicationProperty(processTransactionProperty).orElse("true"));
+    }
+
     private void storeFile(GeneratedFileType type, String path, String source) 
{
         if (generatedFiles.stream().anyMatch(f -> 
path.equals(f.relativePath()))) {
             LOGGER.warn("There's already a generated file named {} to be 
compiled. Ignoring.", path);
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 90ab0277b0..165477103f 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
@@ -29,6 +29,8 @@ import java.util.Optional;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
+import org.drools.codegen.common.di.DependencyInjectionAnnotator;
+import org.drools.codegen.common.rest.RestAnnotator;
 import org.drools.util.StringUtils;
 import org.jbpm.compiler.canonical.ProcessToExecModelGenerator;
 import org.jbpm.compiler.canonical.TriggerMetaData;
@@ -44,6 +46,8 @@ import org.kie.kogito.codegen.core.CodegenUtils;
 import org.kie.kogito.codegen.core.GeneratorConfig;
 import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
 import org.kie.kogito.internal.utils.ConversionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.Modifier.Keyword;
@@ -73,6 +77,15 @@ import static 
org.kie.kogito.internal.utils.ConversionUtils.sanitizeJavaName;
  */
 public class ProcessResourceGenerator {
 
+    /**
+     * Flag used to configure transaction enablement. Default to 
<code>true</code>
+     */
+    public static final String TRANSACTION_ENABLED = "transactionEnabled";
+
+    static final String INVALID_CONTEXT_TEMPLATE = "ProcessResourceGenerator 
can't be used for context without Rest %s";
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ProcessResourceGenerator.class);
+
     private static final String REST_TEMPLATE_NAME = "RestResource";
     private static final String REACTIVE_REST_TEMPLATE_NAME = 
"ReactiveRestResource";
     private static final String REST_USER_TASK_TEMPLATE_NAME = 
"RestResourceUserTask";
@@ -93,6 +106,7 @@ public class ProcessResourceGenerator {
 
     private boolean startable;
     private boolean dynamic;
+    private boolean transactionEnabled;
     private List<TriggerMetaData> triggers;
 
     private List<UserTaskModelMetaData> userTasks;
@@ -106,6 +120,9 @@ public class ProcessResourceGenerator {
             String modelfqcn,
             String processfqcn,
             String appCanonicalName) {
+        if (!context.hasRest()) {
+            throw new 
IllegalArgumentException(String.format(INVALID_CONTEXT_TEMPLATE, 
context.name()));
+        }
         this.context = context;
         this.process = process;
         this.processId = process.getId();
@@ -134,6 +151,11 @@ public class ProcessResourceGenerator {
         return this;
     }
 
+    public ProcessResourceGenerator withTransaction(boolean 
transactionEnabled) {
+        this.transactionEnabled = transactionEnabled;
+        return this;
+    }
+
     public String getTaskModelFactory() {
         return taskModelFactoryUnit.toString();
     }
@@ -149,27 +171,104 @@ public class ProcessResourceGenerator {
     protected String getRestTemplateName() {
         boolean isReactiveGenerator = 
"reactive".equals(context.getApplicationProperty(GeneratorConfig.KOGITO_REST_RESOURCE_TYPE_PROP)
                 .orElse(""));
-        boolean isQuarkus = 
context.name().equals(QuarkusKogitoBuildContext.CONTEXT_NAME);
+        return isQuarkus() && isReactiveGenerator ? 
REACTIVE_REST_TEMPLATE_NAME : REST_TEMPLATE_NAME;
+    }
 
-        return isQuarkus && isReactiveGenerator ? REACTIVE_REST_TEMPLATE_NAME 
: REST_TEMPLATE_NAME;
+    protected boolean isQuarkus() {
+        return context.name().equals(QuarkusKogitoBuildContext.CONTEXT_NAME);
     }
 
     public String generate() {
-        TemplatedGenerator.Builder templateBuilder = 
TemplatedGenerator.builder()
-                .withFallbackContext(QuarkusKogitoBuildContext.CONTEXT_NAME);
-        CompilationUnit clazz = templateBuilder.build(context, 
getRestTemplateName())
-                .compilationUnitOrThrow();
-        clazz.setPackageDeclaration(process.getPackageName());
-        clazz.addImport(modelfqcn);
-        clazz.addImport(modelfqcn + "Output");
-        clazz.addImport(modelfqcn + "Input");
-        ClassOrInterfaceDeclaration template = clazz
+        return getCompilationUnit().toString();
+    }
+
+    protected CompilationUnit getCompilationUnit() {
+        TemplatedGenerator.Builder templateBuilder = 
createTemplatedGeneratorBuilder();
+        CompilationUnit toReturn = createCompilationUnit(templateBuilder);
+        addPackageAndImports(toReturn);
+        ClassOrInterfaceDeclaration template = toReturn
                 .findFirst(ClassOrInterfaceDeclaration.class)
                 .orElseThrow(() -> new NoSuchElementException("Compilation 
unit doesn't contain a class or interface declaration!"));
 
         template.setName(resourceClazzName);
         AtomicInteger index = new AtomicInteger(0);
         //Generate signals endpoints
+        generateSignalsEndpoints(templateBuilder, template, index);
+
+        // security must be applied before user tasks are added to make sure 
that user task
+        // endpoints are not security annotated as they should restrict access 
based on user assignments
+        securityAnnotated(template);
+
+        Map<String, String> typeInterpolations = new HashMap<>();
+        taskModelFactoryUnit = 
parse(this.getClass().getResourceAsStream("/class-templates/TaskModelFactoryTemplate"
 +
+                ".java"));
+        String taskModelFactorySimpleClassName =
+                
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ "TaskModelFactory");
+        taskModelFactoryUnit.setPackageDeclaration(process.getPackageName());
+        taskModelFactoryClassName = process.getPackageName() + "." + 
taskModelFactorySimpleClassName;
+        ClassOrInterfaceDeclaration taskModelFactoryClass =
+                
taskModelFactoryUnit.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(IllegalStateException::new);
+        taskModelFactoryClass.setName(taskModelFactorySimpleClassName);
+        typeInterpolations.put("$TaskModelFactory$", 
taskModelFactoryClassName);
+
+        manageUserTasks(templateBuilder, template, taskModelFactoryClass, 
index);
+
+        typeInterpolations.put("$Clazz$", resourceClazzName);
+        typeInterpolations.put("$Type$", dataClazzName);
+        
template.findAll(StringLiteralExpr.class).forEach(this::interpolateStrings);
+        template.findAll(ClassOrInterfaceType.class).forEach(cls -> 
interpolateTypes(cls, typeInterpolations));
+
+        TagResourceGenerator.addTags(toReturn, process, context);
+
+        
template.findAll(MethodDeclaration.class).forEach(this::interpolateMethods);
+
+        if (context.hasDI()) {
+            template.findAll(FieldDeclaration.class,
+                    CodegenUtils::isProcessField).forEach(fd -> 
context.getDependencyInjectionAnnotator().withNamedInjection(fd, processId));
+        } else {
+            template.findAll(FieldDeclaration.class,
+                    
CodegenUtils::isProcessField).forEach(this::initializeProcessField);
+        }
+
+        // if triggers are not empty remove createResource method as there is 
another trigger to start process instances
+        if ((!startable && !dynamic) || !isPublic()) {
+            Optional<MethodDeclaration> createResourceMethod =
+                    template.findFirst(MethodDeclaration.class).filter(md -> 
md.getNameAsString().equals(
+                            "createResource_" + processName));
+            createResourceMethod.ifPresent(template::remove);
+        }
+
+        if (context.hasDI()) {
+            
context.getDependencyInjectionAnnotator().withApplicationComponent(template);
+        }
+
+        enableValidation(template);
+
+        manageTransactional(toReturn);
+
+        template.getMembers().sort(new BodyDeclarationComparator());
+        return toReturn;
+    }
+
+    protected TemplatedGenerator.Builder createTemplatedGeneratorBuilder() {
+        return TemplatedGenerator.builder()
+                .withFallbackContext(QuarkusKogitoBuildContext.CONTEXT_NAME);
+    }
+
+    protected CompilationUnit createCompilationUnit(TemplatedGenerator.Builder 
templateBuilder) {
+        return templateBuilder.build(context, getRestTemplateName())
+                .compilationUnitOrThrow();
+    }
+
+    protected void addPackageAndImports(CompilationUnit compilationUnit) {
+        compilationUnit.setPackageDeclaration(process.getPackageName());
+        compilationUnit.addImport(modelfqcn);
+        compilationUnit.addImport(modelfqcn + "Output");
+        compilationUnit.addImport(modelfqcn + "Input");
+    }
+
+    protected void generateSignalsEndpoints(TemplatedGenerator.Builder 
templateBuilder,
+            ClassOrInterfaceDeclaration template, AtomicInteger index) {
         Optional.ofNullable(signals)
                 .ifPresent(signalsMap -> {
                     //using template class to the endpoints generation
@@ -265,20 +364,10 @@ public class ProcessResourceGenerator {
                                 });
                             });
                 });
+    }
 
-        // security must be applied before user tasks are added to make sure 
that user task
-        // endpoints are not security annotated as they should restrict access 
based on user assignments
-        securityAnnotated(template);
-
-        Map<String, String> typeInterpolations = new HashMap<>();
-        taskModelFactoryUnit = 
parse(this.getClass().getResourceAsStream("/class-templates/TaskModelFactoryTemplate.java"));
-        String taskModelFactorySimpleClassName = 
sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" 
+ "TaskModelFactory");
-        taskModelFactoryUnit.setPackageDeclaration(process.getPackageName());
-        taskModelFactoryClassName = process.getPackageName() + "." + 
taskModelFactorySimpleClassName;
-        ClassOrInterfaceDeclaration taskModelFactoryClass = 
taskModelFactoryUnit.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(IllegalStateException::new);
-        taskModelFactoryClass.setName(taskModelFactorySimpleClassName);
-        typeInterpolations.put("$TaskModelFactory$", 
taskModelFactoryClassName);
-
+    protected void manageUserTasks(TemplatedGenerator.Builder templateBuilder, 
ClassOrInterfaceDeclaration template,
+            ClassOrInterfaceDeclaration taskModelFactoryClass, AtomicInteger 
index) {
         if (userTasks != null && !userTasks.isEmpty()) {
 
             CompilationUnit userTaskClazz = templateBuilder.build(context, 
REST_USER_TASK_TEMPLATE_NAME).compilationUnitOrThrow();
@@ -310,44 +399,42 @@ public class ProcessResourceGenerator {
                     template.findAll(MethodDeclaration.class)
                             .stream()
                             .filter(md -> 
md.getNameAsString().equals(SIGNAL_METHOD_PREFFIX + methodSuffix))
-                            
.collect(Collectors.toList()).forEach(template::remove);
+                            .forEach(template::remove);
                 }
                 switchExpr.getEntries().add(0, userTask.getModelSwitchEntry());
             }
 
         }
+    }
 
-        typeInterpolations.put("$Clazz$", resourceClazzName);
-        typeInterpolations.put("$Type$", dataClazzName);
-        
template.findAll(StringLiteralExpr.class).forEach(this::interpolateStrings);
-        template.findAll(ClassOrInterfaceType.class).forEach(cls -> 
interpolateTypes(cls, typeInterpolations));
-
-        TagResourceGenerator.addTags(clazz, process, context);
-
-        
template.findAll(MethodDeclaration.class).forEach(this::interpolateMethods);
-
-        if (context.hasDI()) {
-            template.findAll(FieldDeclaration.class,
-                    CodegenUtils::isProcessField).forEach(fd -> 
context.getDependencyInjectionAnnotator().withNamedInjection(fd, processId));
-        } else {
-            template.findAll(FieldDeclaration.class,
-                    
CodegenUtils::isProcessField).forEach(this::initializeProcessField);
-        }
-
-        // if triggers are not empty remove createResource method as there is 
another trigger to start process instances
-        if ((!startable && !dynamic) || !isPublic()) {
-            Optional<MethodDeclaration> createResourceMethod = 
template.findFirst(MethodDeclaration.class).filter(md -> 
md.getNameAsString().equals("createResource_" + processName));
-            createResourceMethod.ifPresent(template::remove);
-        }
-
-        if (context.hasDI()) {
-            
context.getDependencyInjectionAnnotator().withApplicationComponent(template);
+    /**
+     * Conditionally add the <code>Transactional</code> annotation
+     * 
+     * @param compilationUnit
+     *
+     */
+    protected void manageTransactional(CompilationUnit compilationUnit) {
+        if (transactionEnabled && context.hasDI() && !isServerless()) { // 
disabling transaction for serverless
+            LOG.debug("Transaction is enabled, adding annotations...");
+            DependencyInjectionAnnotator dependencyInjectionAnnotator = 
context.getDependencyInjectionAnnotator();
+            getRestMethods(compilationUnit)
+                    .forEach(dependencyInjectionAnnotator::withTransactional);
         }
+    }
 
-        enableValidation(template);
-
-        template.getMembers().sort(new BodyDeclarationComparator());
-        return clazz.toString();
+    /**
+     * 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();
     }
 
     private void securityAnnotated(ClassOrInterfaceDeclaration template) {
@@ -468,4 +555,8 @@ public class ProcessResourceGenerator {
     protected boolean isPublic() {
         return 
KogitoWorkflowProcess.PUBLIC_VISIBILITY.equalsIgnoreCase(process.getVisibility());
     }
+
+    protected boolean isServerless() {
+        return 
KogitoWorkflowProcess.SW_TYPE.equalsIgnoreCase(process.getType());
+    }
 }
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceSpringTemplate.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceSpringTemplate.java
index 9c15e01b47..190a38af3b 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceSpringTemplate.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceSpringTemplate.java
@@ -43,6 +43,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -55,8 +56,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.server.ResponseStatusException;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.HttpStatus;
 import org.springframework.web.util.UriComponents;
 import org.springframework.web.util.UriComponentsBuilder;
 
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 57b4fa9a49..52d1665166 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
@@ -24,14 +24,17 @@ import java.util.List;
 import java.util.Optional;
 import java.util.function.Predicate;
 
+import org.assertj.core.api.ListAssert;
 import org.drools.io.FileSystemResource;
 import org.jbpm.compiler.canonical.ProcessMetaData;
 import org.jbpm.compiler.canonical.ProcessToExecModelGenerator;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 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.internal.process.runtime.KogitoWorkflowProcess;
 
 import com.github.javaparser.StaticJavaParser;
@@ -45,14 +48,29 @@ 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.kie.kogito.codegen.process.ProcessResourceGenerator.INVALID_CONTEXT_TEMPLATE;
 
 class ProcessResourceGeneratorTest {
+
     private static final String SIGNAL_METHOD = "signal_";
     private static final List<String> JAVA_AND_QUARKUS_REST_ANNOTATIONS = 
List.of("DELETE", "GET", "POST");
     private static final List<String> SPRING_BOOT_REST_ANNOTATIONS = 
List.of("DeleteMapping", "GetMapping", "PostMapping");
 
+    @Test
+    void testProcessResourceGeneratorForJava() {
+        KogitoBuildContext.Builder contextBuilder = 
JavaKogitoBuildContext.builder();
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2"; // not 
relevant
+        boolean transactionEnabled = true; // not relevant
+        String expectedMessage = String.format(INVALID_CONTEXT_TEMPLATE, 
JavaKogitoBuildContext.CONTEXT_NAME);
+        assertThatThrownBy(() -> getProcessResourceGenerator(contextBuilder, 
fileName,
+                transactionEnabled))
+                        .isInstanceOf(IllegalArgumentException.class)
+                        .hasMessageContaining(expectedMessage);
+    }
+
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     void testGenerateProcessWithDocumentation(KogitoBuildContext.Builder 
contextBuilder) {
         String fileName = "src/test/resources/ProcessWithDocumentation.bpmn";
         String expectedSummary = "This is the documentation";
@@ -62,7 +80,7 @@ class ProcessResourceGeneratorTest {
     }
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     void testGenerateProcessWithoutDocumentation(KogitoBuildContext.Builder 
contextBuilder) {
         String fileName = 
"src/test/resources/ProcessWithoutDocumentation.bpmn";
         String expectedSummary = "ProcessWithoutDocumentation";
@@ -72,7 +90,7 @@ class ProcessResourceGeneratorTest {
     }
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     void testGenerateBoundarySignalEventOnTask(KogitoBuildContext.Builder 
contextBuilder) {
         String fileName = 
"src/test/resources/signalevent/BoundarySignalEventOnTask.bpmn2";
 
@@ -88,7 +106,7 @@ class ProcessResourceGeneratorTest {
     }
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     void testGenerateStartSignalEventStringPayload(KogitoBuildContext.Builder 
contextBuilder) {
         String fileName = 
"src/test/resources/startsignal/StartSignalEventStringPayload.bpmn2";
         String signalName = "start";
@@ -121,7 +139,7 @@ class ProcessResourceGeneratorTest {
     }
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     void testGenerateStartSignalEventNoPayload(KogitoBuildContext.Builder 
contextBuilder) {
         String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
         String signalName = "start";
@@ -152,6 +170,68 @@ class ProcessResourceGeneratorTest {
                 .forEach(method -> assertMethodOutputModelType(method, 
outputType));
     }
 
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testManageTransactionalEnabled(KogitoBuildContext.Builder 
contextBuilder) {
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
+
+        boolean transactionEnabled = true;
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, fileName,
+                transactionEnabled);
+        CompilationUnit compilationUnit =
+                
processResourceGenerator.createCompilationUnit(processResourceGenerator.createTemplatedGeneratorBuilder());
+        assertThat(compilationUnit).isNotNull();
+        KogitoBuildContext kogitoBuildContext = contextBuilder.build();
+        Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
+        // before processResourceGenerator.manageTransactional, the annotation 
is not there
+        testTransaction(restEndpoints, kogitoBuildContext, false);
+        processResourceGenerator.manageTransactional(compilationUnit);
+        // the annotation is (conditionally) add after 
processResourceGenerator.manageTransactional
+        testTransaction(restEndpoints, kogitoBuildContext, transactionEnabled);
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void testManageTransactionalDisabled(KogitoBuildContext.Builder 
contextBuilder) {
+        String fileName = 
"src/test/resources/startsignal/StartSignalEventNoPayload.bpmn2";
+        boolean transactionEnabled = false;
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, fileName,
+                transactionEnabled);
+        CompilationUnit compilationUnit =
+                
processResourceGenerator.createCompilationUnit(processResourceGenerator.createTemplatedGeneratorBuilder());
+        assertThat(compilationUnit).isNotNull();
+        KogitoBuildContext kogitoBuildContext = contextBuilder.build();
+        Collection<MethodDeclaration> restEndpoints = 
processResourceGenerator.getRestMethods(compilationUnit);
+        // before processResourceGenerator.manageTransactional, the annotation 
is not there
+        testTransaction(restEndpoints, kogitoBuildContext, false);
+        processResourceGenerator.manageTransactional(compilationUnit);
+        // the annotation is (conditionally) add after 
processResourceGenerator.manageTransactional
+        testTransaction(restEndpoints, kogitoBuildContext, transactionEnabled);
+    }
+
+    void testTransaction(Collection<MethodDeclaration> restEndpoints,
+            KogitoBuildContext kogitoBuildContext,
+            boolean enabled) {
+        String transactionalAnnotation =
+                
kogitoBuildContext.getDependencyInjectionAnnotator().getTransactionalAnnotation();
+        restEndpoints.forEach(methodDeclaration -> {
+            ListAssert<?> transactionAnnotationAssert = assertThat(
+                    
methodDeclaration.getAnnotations().stream().filter(annotationExpr -> 
annotationExpr.getNameAsString().equals(transactionalAnnotation)));
+            if (enabled) {
+                transactionAnnotationAssert.hasSize(1);
+            } else {
+                transactionAnnotationAssert.isEmpty();
+            }
+            if 
(methodDeclaration.getName().toString().startsWith("createResource_")) {
+                ListAssert<?> stmtsAsserts = assertThat(
+                        methodDeclaration.getBody()
+                                .get()
+                                .getStatements());
+                stmtsAsserts.hasSize(2);
+            }
+        });
+    }
+
     void testOpenApiDocumentation(KogitoBuildContext.Builder contextBuilder, 
String fileName, String expectedSummary, String expectedDescription) {
         ClassOrInterfaceDeclaration classDeclaration = 
getResourceClassDeclaration(contextBuilder, fileName);
 
@@ -168,15 +248,27 @@ class ProcessResourceGeneratorTest {
         return classDeclaration.orElseThrow();
     }
 
-    private CompilationUnit getCompilationUnit(KogitoBuildContext.Builder 
contextBuilder, KogitoWorkflowProcess process) {
+    private CompilationUnit getCompilationUnit(KogitoBuildContext.Builder 
contextBuilder,
+            KogitoWorkflowProcess process) {
+        ProcessResourceGenerator processResourceGenerator = 
getProcessResourceGenerator(contextBuilder, process, true);
+        return StaticJavaParser.parse(processResourceGenerator.generate());
+    }
+
+    private ProcessResourceGenerator 
getProcessResourceGenerator(KogitoBuildContext.Builder contextBuilder,
+            String fileName, boolean withTransaction) {
+        return getProcessResourceGenerator(contextBuilder, 
parseProcess(fileName), withTransaction);
+    }
+
+    private ProcessResourceGenerator 
getProcessResourceGenerator(KogitoBuildContext.Builder contextBuilder,
+            KogitoWorkflowProcess process,
+            boolean withTransaction) {
         KogitoBuildContext context = createContext(contextBuilder);
 
         ProcessExecutableModelGenerator execModelGen =
                 new ProcessExecutableModelGenerator(process, new 
ProcessToExecModelGenerator(context.getClassLoader()));
 
         KogitoWorkflowProcess workFlowProcess = execModelGen.process();
-
-        ProcessResourceGenerator processResourceGenerator = new 
ProcessResourceGenerator(
+        ProcessResourceGenerator toReturn = new ProcessResourceGenerator(
                 context,
                 workFlowProcess,
                 new ModelClassGenerator(context, workFlowProcess).className(),
@@ -185,11 +277,11 @@ class ProcessResourceGeneratorTest {
 
         ProcessMetaData metaData = execModelGen.generate();
 
-        processResourceGenerator
+        toReturn
                 .withSignals(metaData.getSignals())
-                .withTriggers(metaData.isStartable(), metaData.isDynamic(), 
metaData.getTriggers());
-
-        return StaticJavaParser.parse(processResourceGenerator.generate());
+                .withTriggers(metaData.isStartable(), metaData.isDynamic(), 
metaData.getTriggers())
+                .withTransaction(withTransaction);
+        return toReturn;
     }
 
     private void assertThatMethodHasOpenApiDocumentation(MethodDeclaration 
method, String summary, String description) {
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenMessageStartEventTest.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenMessageStartEventTest.java
index 6badf99806..f8c540a242 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenMessageStartEventTest.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenMessageStartEventTest.java
@@ -49,7 +49,7 @@ public class CodegenMessageStartEventTest {
     private static final Path MESSAGE_START_END_EVENT_SOURCE_FULL_SOURCE = 
BASE_PATH.resolve(MESSAGE_START_END_EVENT_SOURCE);
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     public void testRESTApiForMessageStartEvent(KogitoBuildContext.Builder 
contextBuilder) {
 
         KogitoBuildContext context = contextBuilder.build();
@@ -80,7 +80,7 @@ public class CodegenMessageStartEventTest {
     }
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     public void testRESTApiForMessageEndEvent(KogitoBuildContext.Builder 
contextBuilder) {
 
         KogitoBuildContext context = contextBuilder.build();
diff --git 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenUserTaskTest.java
 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenUserTaskTest.java
index 271f9c897f..24f875c2a0 100644
--- 
a/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenUserTaskTest.java
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/test/java/org/kie/kogito/codegen/process/events/CodegenUserTaskTest.java
@@ -43,7 +43,7 @@ public class CodegenUserTaskTest {
     private static final Path MESSAGE_USERTASK_SOURCE_FULL_SOURCE = 
BASE_PATH.resolve(MESSAGE_USERTASK_SOURCE);
 
     @ParameterizedTest
-    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#contextBuilders")
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
     public void testRESTApiForMessageStartEvent(KogitoBuildContext.Builder 
contextBuilder) {
 
         KogitoBuildContext context = contextBuilder.build();
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 9acc49370f..6053372826 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
@@ -45,6 +45,10 @@
       <groupId>org.jbpm</groupId>
       <artifactId>jbpm-quarkus</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-narayana-jta-deployment</artifactId>
+    </dependency>
     <!-- test -->
     <dependency>
       <groupId>io.quarkus</groupId>
diff --git 
a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/pom.xml
 
b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/pom.xml
index e74b1c102b..5caf3a85a6 100644
--- 
a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/pom.xml
+++ 
b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/pom.xml
@@ -68,6 +68,10 @@
       <groupId>io.quarkiverse.jackson-jq</groupId>
       <artifactId>quarkus-jackson-jq-deployment</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-narayana-jta-deployment</artifactId>
+    </dependency>
 
     <!-- Quarkus Deployment Extensions Dependencies -->
     <dependency>
diff --git 
a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/pom.xml
 
b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/pom.xml
index 6911874239..736a415858 100644
--- 
a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/pom.xml
+++ 
b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/pom.xml
@@ -45,6 +45,10 @@
       <groupId>io.smallrye.reactive</groupId>
       <artifactId>smallrye-mutiny-vertx-web-client</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.quarkus</groupId>
+      <artifactId>quarkus-narayana-jta</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.kie.kogito</groupId>
       <artifactId>jbpm-deps-group-engine</artifactId>
diff --git a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml 
b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
index c29c25ebe1..cd9817e03e 100644
--- a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
+++ b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
@@ -56,6 +56,10 @@
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-core</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-tx</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