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

egonzalez 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 9d37dc2ff4 [incubator-kie-issues-1517] Add Transactional Rest 
endpoints to UserTasks (#3701)
9d37dc2ff4 is described below

commit 9d37dc2ff46afd8f244adfb4bf629aa6f6211725
Author: Enrique <[email protected]>
AuthorDate: Mon Oct 14 12:39:15 2024 +0200

    [incubator-kie-issues-1517] Add Transactional Rest endpoints to UserTasks 
(#3701)
---
 .../kie/kogito/codegen/process/ProcessCodegen.java |   9 +-
 .../codegen/process/ProcessResourceGenerator.java  |   5 -
 .../kogito/codegen/process/util/CodegenUtil.java   | 105 +++++++++++++++++++++
 .../kogito/codegen/usertask/UserTaskCodegen.java   |  21 +++--
 .../process/ProcessResourceGeneratorTest.java      |  81 ++++++++++++++++
 5 files changed, 201 insertions(+), 20 deletions(-)

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 86e6bd8053..528a9e081a 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
@@ -62,6 +62,7 @@ import 
org.kie.kogito.codegen.core.DashboardGeneratedFileUtils;
 import org.kie.kogito.codegen.process.config.ProcessConfigGenerator;
 import org.kie.kogito.codegen.process.events.ProcessCloudEventMeta;
 import 
org.kie.kogito.codegen.process.events.ProcessCloudEventMetaFactoryGenerator;
+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;
@@ -76,7 +77,6 @@ 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;
@@ -369,7 +369,7 @@ public class ProcessCodegen extends AbstractGenerator {
                         
.withWorkItems(processIdToWorkItemModel.get(workFlowProcess.getId()))
                         .withSignals(metaData.getSignals())
                         .withTriggers(metaData.isStartable(), 
metaData.isDynamic(), metaData.getTriggers())
-                        .withTransaction(isTransactionEnabled());
+                        
.withTransaction(CodegenUtil.isTransactionEnabled(this, context()));
 
                 rgs.add(processResourceGenerator);
             }
@@ -511,11 +511,6 @@ 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 3e2f8765a4..207af9e636 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
@@ -77,11 +77,6 @@ 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);
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
new file mode 100644
index 0000000000..658507ca1b
--- /dev/null
+++ 
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
@@ -0,0 +1,105 @@
+/*
+ * 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.process.util;
+
+import java.util.function.Function;
+
+import org.kie.kogito.codegen.api.Generator;
+import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class CodegenUtil {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(CodegenUtil.class);
+    /**
+     * Flag used to configure transaction enabling. Default to 
<code>true</code>
+     */
+    public static final String TRANSACTION_ENABLED = "transactionEnabled";
+
+    private CodegenUtil() {
+        // do nothing
+    }
+
+    /**
+     * Creates the property for a certain generator.
+     * 
+     * @param generator
+     * @param propertyName
+     * @return returns the property for certain generator
+     */
+    public static String generatorProperty(Generator generator, String 
propertyName) {
+        return String.format("kogito.%s.%s", generator.name(), propertyName);
+    }
+
+    /**
+     * Creates the property for global application
+     * 
+     * @param propertyName
+     * @return
+     */
+    public static String globalProperty(String propertyName) {
+        return String.format("kogito.%s", propertyName);
+    }
+
+    /**
+     * This computes the boolean value of the transaction being enabled based 
on the logic specified
+     * the property. Default value it is true
+     * 
+     * @see CodegenUtil#getProperty
+     */
+    public static boolean isTransactionEnabled(Generator generator, 
KogitoBuildContext context) {
+        boolean propertyValue = getProperty(generator, context, 
TRANSACTION_ENABLED, Boolean::parseBoolean, true);
+        LOG.info("trying to compute property {} for generator {} property with 
value {}", TRANSACTION_ENABLED, generator.name(), propertyValue);
+        return propertyValue;
+    }
+
+    /**
+     * This method is a generic method to compute certain property of the 
given type.
+     * 1. we compute the global property applicable for all the application.
+     * 2. we compute the property only applicable for certain generator.
+     * 
+     * @see CodegenUtil#getApplicationProperty
+     * @see CodegenUtil#globalProperty
+     * @see CodegenUtil#generatorProperty
+     */
+    public static <T> T getProperty(Generator generator, KogitoBuildContext 
context, String propertyName, Function<String, T> converter, T defaultValue) {
+
+        String generatorProperty = generatorProperty(generator, propertyName);
+        if (isApplicationPropertyDefined(context, generatorProperty)) {
+            return converter.apply(getApplicationProperty(context, 
generatorProperty));
+        }
+
+        String globalProperty = globalProperty(propertyName);
+
+        if (isApplicationPropertyDefined(context, globalProperty)) {
+            return converter.apply(getApplicationProperty(context, 
globalProperty));
+        }
+
+        return defaultValue;
+    }
+
+    private static boolean isApplicationPropertyDefined(KogitoBuildContext 
context, String property) {
+        return context.getApplicationProperty(property).isPresent();
+    }
+
+    private static String getApplicationProperty(KogitoBuildContext context, 
String property) {
+        return context.getApplicationProperty(property).orElseThrow(() -> new 
IllegalArgumentException("Property " + property + " defined but does not 
contain proper value"));
+    }
+}
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 bd10069d47..c145c332ee 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
@@ -51,6 +51,7 @@ import org.kie.kogito.codegen.api.template.TemplatedGenerator;
 import org.kie.kogito.codegen.core.AbstractGenerator;
 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;
@@ -62,6 +63,7 @@ import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.expr.CastExpr;
 import com.github.javaparser.ast.expr.Expression;
 import com.github.javaparser.ast.expr.IntegerLiteralExpr;
@@ -97,9 +99,9 @@ public class UserTaskCodegen extends AbstractGenerator {
         BPMN_SEMANTIC_MODULES.addSemanticModule(new BPMNDISemanticModule());
     }
 
-    public static final String SECTION_CLASS_NAME = "usertask";
+    public static final String SECTION_CLASS_NAME = "usertasks";
 
-    TemplatedGenerator templateGenerator;
+    private TemplatedGenerator templateGenerator;
     private List<Work> descriptors;
     private TemplatedGenerator producerTemplateGenerator;
     private TemplatedGenerator restTemplateGenerator;
@@ -158,25 +160,28 @@ public class UserTaskCodegen extends AbstractGenerator {
         return generatedFiles;
     }
 
-    private GeneratedFile generateRestEndpiont() {
+    public GeneratedFile generateRestEndpiont() {
         String packageName = context().getPackageName();
-        CompilationUnit compilationUnit = 
producerTemplateGenerator.compilationUnitOrThrow("Not rest endpoints template 
found for user tasks");
+        CompilationUnit compilationUnit = 
restTemplateGenerator.compilationUnitOrThrow("Not rest endpoints template found 
for user tasks");
         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();
         String urlBase = packageName.replaceAll("\\.", File.separator);
-        return new GeneratedFile(GeneratedFileType.SOURCE, 
Path.of(urlBase).resolve(className + ".java"), compilationUnit.toString());
+        return new GeneratedFile(GeneratedFileType.REST, 
Path.of(urlBase).resolve(className + ".java"), compilationUnit.toString());
     }
 
-    private GeneratedFile generateProducer() {
+    public GeneratedFile generateProducer() {
         String packageName = context().getPackageName();
-        CompilationUnit compilationUnit = 
restTemplateGenerator.compilationUnitOrThrow("No producer template found for 
user tasks");
+        CompilationUnit compilationUnit = 
producerTemplateGenerator.compilationUnitOrThrow("No producer template found 
for user tasks");
         compilationUnit.setPackageDeclaration(packageName);
         String className = 
compilationUnit.findFirst(ClassOrInterfaceDeclaration.class).get().getNameAsString();
         String urlBase = packageName.replaceAll("\\.", File.separator);
         return new GeneratedFile(GeneratedFileType.SOURCE, 
Path.of(urlBase).resolve(className + ".java"), compilationUnit.toString());
     }
 
-    private List<GeneratedFile> generateUserTask() {
+    public List<GeneratedFile> generateUserTask() {
         List<GeneratedFile> generatedFiles = new ArrayList<>();
         for (Work info : descriptors) {
             CompilationUnit unit = templateGenerator.compilationUnit().get();
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 52d1665166..551d5b48b5 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,6 +20,7 @@ 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;
@@ -35,6 +36,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.internal.process.runtime.KogitoWorkflowProcess;
 
 import com.github.javaparser.StaticJavaParser;
@@ -209,6 +212,84 @@ class ProcessResourceGeneratorTest {
         testTransaction(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();
+        }
+    }
+
+    @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();
+        }
+    }
+
+    @ParameterizedTest
+    
@MethodSource("org.kie.kogito.codegen.api.utils.KogitoContextTestUtils#restContextBuilders")
+    void 
testUserTaskManageTransactionalGeneratorDisabled(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();
+        }
+    }
+
+    @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();
+        }
+    }
+
+    @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();
+        for (MethodDeclaration method : restEndpoints) {
+            assertThat(findAnnotationExpr(method, 
context.getDependencyInjectionAnnotator().getTransactionalAnnotation())).isPresent();
+        }
+    }
+
+    Optional<AnnotationExpr> findAnnotationExpr(MethodDeclaration method, 
String fqn) {
+        for (AnnotationExpr expr : method.getAnnotations()) {
+            if (expr.getNameAsString().equals(fqn)) {
+                return Optional.of(expr);
+            }
+        }
+        return Optional.empty();
+    }
+
     void testTransaction(Collection<MethodDeclaration> restEndpoints,
             KogitoBuildContext kogitoBuildContext,
             boolean enabled) {


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

Reply via email to