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 482470a571 [incubator-kie-issues#2253] Replace instantiation of
streams inside generated DecisionModels with creation of modelPaths.txt file
that is parsed at DMNRuntime instantiation (#4229)
482470a571 is described below
commit 482470a57149234588f6e1c5bd6c4026d93f4dde
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Tue May 5 06:43:50 2026 +0000
[incubator-kie-issues#2253] Replace instantiation of streams inside
generated DecisionModels with creation of modelPaths.txt file that is parsed at
DMNRuntime instantiation (#4229)
* [incubator-kie-issues#2253] Replace instantiation of streams inside
generated DecisionModels with creation of modelPaths.txt file that is parsed at
DMNRuntime instantiation
* [incubator-kie-issues#2253] Change modelPaths.txt retrieval to use URL
* [incubator-kie-issues#2253] Change dmnmodel stream retrieval
* [incubator-kie-issues#2253] Fix broken tests modifying the TestClassLoader
* [incubator-kie-issues#2253] Fix as per PR suggestion
* [incubator-kie-issues#2253] Rename generated model file as per PR
suggestion
* [incubator-kie-issues#2253] Fix as per PR suggestion
* [incubator-kie-issues#2253] Fix impsort
* [incubator-kie-issues#2253] Fix format
---------
Co-authored-by: Gabriele-Cardosi <[email protected]>
---
.../explainability/ExplainabilityServiceTest.java | 5 +-
.../org/kie/kogito/dmn/AbstractDecisionModels.java | 39 +++++++-
.../main/java/org/kie/kogito/dmn/DMNKogito.java | 103 ++++++++++++++++++---
.../org/kie/kogito/dmn/DMNKogitoCallbacks.java | 27 +++---
.../java/org/kie/kogito/dmn/DMNKogitoTest.java | 4 +-
.../codegen/decision/DecisionCodegenUtils.java | 46 +++++++++
.../decision/DecisionContainerGenerator.java | 45 +++------
.../kogito/codegen/decision/ReadResourceUtil.java | 13 ++-
...DecisionCloudEventMetaFactoryGeneratorTest.java | 4 +-
.../codegen/decision/DecisionCodegenUtilsTest.java | 29 +++++-
.../org/kie/kogito/codegen/AbstractCodegenIT.java | 57 ++++++++++--
.../src/test/resources/application.properties | 3 +-
.../kie/kogito/explainability/ApplicationMock.java | 6 +-
.../BaseSpringBootDecisionTracingTest.java | 4 +-
14 files changed, 299 insertions(+), 86 deletions(-)
diff --git
a/addons/common/explainability/src/test/java/org/kie/kogito/explainability/ExplainabilityServiceTest.java
b/addons/common/explainability/src/test/java/org/kie/kogito/explainability/ExplainabilityServiceTest.java
index c9bee01cbd..5da5c6a676 100644
---
a/addons/common/explainability/src/test/java/org/kie/kogito/explainability/ExplainabilityServiceTest.java
+++
b/addons/common/explainability/src/test/java/org/kie/kogito/explainability/ExplainabilityServiceTest.java
@@ -18,7 +18,7 @@
*/
package org.kie.kogito.explainability;
-import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -44,8 +44,7 @@ public class ExplainabilityServiceTest {
public static final String MODEL_NAME = "Traffic Violation";
final static String TEST_EXECUTION_ID = "test";
- final static DMNRuntime genericDMNRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false, new
InputStreamReader(
-
ExplainabilityServiceTest.class.getResourceAsStream(MODEL_RESOURCE)));
+ final static DMNRuntime genericDMNRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false,
Map.of(MODEL_RESOURCE, StandardCharsets.UTF_8.name()));
final static DmnDecisionModelSpy decisionModel = new
DmnDecisionModelSpy(genericDMNRuntime, MODEL_NAMESPACE, MODEL_NAME, () ->
TEST_EXECUTION_ID);
@Test
diff --git
a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java
b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java
index 9908c1cd94..4cf558397d 100644
---
a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java
+++
b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java
@@ -18,11 +18,16 @@
*/
package org.kie.kogito.dmn;
-import java.io.Reader;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
+import java.net.URL;
import java.nio.charset.Charset;
+import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
+import java.util.stream.Collectors;
import org.kie.dmn.api.core.DMNRuntime;
import org.kie.dmn.core.compiler.DMNProfile;
@@ -38,6 +43,7 @@ import org.slf4j.LoggerFactory;
public abstract class AbstractDecisionModels implements DecisionModels {
+ public static final String DMN_MODEL_PATHS_FILE = "dmnModelPaths.txt";
private static final Logger LOG =
LoggerFactory.getLogger(AbstractDecisionModels.class);
private static final boolean CAN_PLATFORM_CLASSLOAD =
org.kie.dmn.feel.util.ClassLoaderUtil.CAN_PLATFORM_CLASSLOAD;
private static DMNRuntime dmnRuntime = null;
@@ -45,13 +51,21 @@ public abstract class AbstractDecisionModels implements
DecisionModels {
private static BiFunction<DecisionModel, KogitoGAV, DecisionModel>
decisionModelTransformer = null;
private KogitoGAV gav = KogitoGAV.EMPTY_GAV;
+ /**
+ *
+ * @param executionIdSupplier
+ * @param decisionModelTransformerInit
+ * @param customDMNProfiles
+ * @param enableRuntimeTypeCheckOption
+ */
protected static void init(ExecutionIdSupplier executionIdSupplier,
BiFunction<DecisionModel, KogitoGAV, DecisionModel>
decisionModelTransformerInit,
Set<DMNProfile> customDMNProfiles,
boolean enableRuntimeTypeCheckOption,
- Reader... readers) {
-
DMNKogitoCallbacks.beforeAbstractDecisionModelsInit(executionIdSupplier,
decisionModelTransformerInit, readers);
- dmnRuntime = DMNKogito.createGenericDMNRuntime(customDMNProfiles,
enableRuntimeTypeCheckOption, readers);
+ URL modelPathsUrl) {
+ DMNKogitoCallbacks.beforeAbstractDecisionModelsInit();
+ Map<String, String> modelPaths = getModelPaths(modelPathsUrl);
+ dmnRuntime = DMNKogito.createGenericDMNRuntime(customDMNProfiles,
enableRuntimeTypeCheckOption, modelPaths);
execIdSupplier = executionIdSupplier;
decisionModelTransformer = decisionModelTransformerInit;
DMNKogitoCallbacks.afterAbstractDecisionModelsInit(dmnRuntime);
@@ -87,7 +101,6 @@ public abstract class AbstractDecisionModels implements
DecisionModels {
if (CAN_PLATFORM_CLASSLOAD) {
return isrWithEncodingOrFallback(stream, encoding);
}
-
try {
byte[] bytes =
org.drools.util.IoUtils.readBytesFromInputStream(stream);
java.io.ByteArrayInputStream byteArrayInputStream = new
java.io.ByteArrayInputStream(bytes);
@@ -97,6 +110,22 @@ public abstract class AbstractDecisionModels implements
DecisionModels {
}
}
+ static Map<String, String> getModelPaths(URL modelPathsUrl) {
+ LOG.trace("getModelPaths {}", modelPathsUrl);
+ if (modelPathsUrl == null) {
+ String error = String.format("No URL provided for %s",
DMN_MODEL_PATHS_FILE);
+ LOG.error(error);
+ throw new IllegalStateException(error);
+ }
+ try (BufferedReader reader = new BufferedReader(new
InputStreamReader(modelPathsUrl.openStream()))) {
+ return reader.lines().collect(Collectors.toMap(
+ line -> line.substring(0, line.indexOf(':')),
+ line -> line.substring(line.indexOf(':') + 1)));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/**
* Create an InputStreamReader using the supplied encoding, or otherwise
fallback to the default constructor using the default encoding.
*/
diff --git a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogito.java
b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogito.java
index 9fa72e4307..0ff562ae28 100644
--- a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogito.java
+++ b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogito.java
@@ -18,9 +18,11 @@
*/
package org.kie.kogito.dmn;
+import java.io.InputStream;
import java.io.Reader;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -38,6 +40,10 @@ import org.kie.dmn.core.internal.utils.DMNRuntimeBuilder;
import org.kie.dmn.feel.util.EvalHelper;
import org.kie.kogito.Application;
import org.kie.kogito.dmn.rest.KogitoDMNResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.kie.kogito.dmn.AbstractDecisionModels.readResource;
/**
* Internal Utility class.<br/>
@@ -46,6 +52,8 @@ import org.kie.kogito.dmn.rest.KogitoDMNResult;
*/
public class DMNKogito {
+ private static final Logger logger =
LoggerFactory.getLogger(DMNKogito.class.getName());
+
private DMNKogito() {
// intentionally private.
}
@@ -58,17 +66,36 @@ public class DMNKogito {
public static DMNRuntime createGenericDMNRuntime(Set<DMNProfile>
customDMNProfiles, boolean enableRuntimeTypeCheckOption, Reader... readers) {
DMNKogitoCallbacks.beforeCreateGenericDMNRuntime(readers);
List<Resource> resources =
Stream.of(readers).map(ReaderResource::new).collect(Collectors.toList());
- EvalHelper.clearGenericAccessorCache(); // KOGITO-3325 DMN hot reload
manage accessor cache when stronglytyped
- DMNRuntimeBuilder dmnRuntimeBuilder = DMNRuntimeBuilder.fromDefaults();
- customDMNProfiles.forEach(dmnRuntimeBuilder::addProfile);
- DMNRuntime dmnRuntime = dmnRuntimeBuilder
- .buildConfiguration()
- .fromResources(resources)
- .getOrElseThrow(e -> new RuntimeException("Error initializing
DMNRuntime", e));
- RuntimeTypeCheckOption runtimeTypeCheckOption = new
RuntimeTypeCheckOption(enableRuntimeTypeCheckOption);
- ((DMNRuntimeImpl) dmnRuntime).setOption(runtimeTypeCheckOption);
- DMNKogitoCallbacks.afterCreateGenericDMNRuntime(dmnRuntime);
- return dmnRuntime;
+ return createGenericDMNRuntime(customDMNProfiles,
enableRuntimeTypeCheckOption, resources);
+ }
+
+ /**
+ * Internal Utility class.<br/>
+ * Use {@link Application#decisionModels()} of Kogito API to
programmatically access DMN assets and evaluate DMN
+ * decisions.
+ *
+ * @param customDMNProfiles
+ * @param enableRuntimeTypeCheckOption
+ * @param modelPaths A Map of model path to model encoding
+ * @return
+ */
+ public static DMNRuntime createGenericDMNRuntime(Set<DMNProfile>
customDMNProfiles, boolean enableRuntimeTypeCheckOption,
+ Map<String, String> modelPaths) {
+ DMNKogitoCallbacks.beforeCreateGenericDMNRuntime(modelPaths);
+ List<Resource> resources = modelPaths.entrySet()
+ .stream()
+ .map(modelPathEntry -> {
+ Optional<InputStream> modelStream =
getDMNModelStream(modelPathEntry.getKey());
+ if (modelStream.isPresent()) {
+ return readResource(modelStream.get(),
modelPathEntry.getValue());
+ } else {
+ String errorMessage = String.format("DMN model stream
not found for path: %s", modelPathEntry.getKey());
+ logger.error(errorMessage);
+ throw new IllegalStateException(errorMessage);
+ }
+ })
+ .map(ReaderResource::new).collect(Collectors.toList());
+ return createGenericDMNRuntime(customDMNProfiles,
enableRuntimeTypeCheckOption, resources);
}
public static DMNModel modelByName(DMNRuntime dmnRuntime, String
modelName) {
@@ -96,4 +123,58 @@ public class DMNKogito {
return new KogitoDMNResult(modelNamespace, modelName,
evaluationResult.result);
}
+ static Optional<InputStream> getDMNModelStream(String path) {
+ logger.debug("getDMNModelStream for {}", path);
+ InputStream toReturn = Application.class.getResourceAsStream(path);
+ if (toReturn != null) {
+ return Optional.of(toReturn);
+ } else {
+ logger.debug("DMN model stream not found in
Application.class.getResourceAsStream");
+ }
+ toReturn =
Application.class.getClassLoader().getResourceAsStream(path);
+ if (toReturn != null) {
+ return Optional.of(toReturn);
+ } else {
+ logger.debug("DMN model stream not found in
Application.class.getClassLoader().getResourceAsStream");
+ }
+ toReturn =
org.drools.util.IoUtils.class.getClassLoader().getResourceAsStream(path);
+ if (toReturn != null) {
+ return Optional.of(toReturn);
+ } else {
+ logger.debug("DMN model stream not found in
org.drools.util.IoUtils.class.getClassLoader().getResourceAsStream");
+ }
+ toReturn =
Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+ if (toReturn != null) {
+ return Optional.of(toReturn);
+ } else {
+ logger.debug("DMN model stream not found in
Thread.currentThread().getContextClassLoader().getResourceAsStream");
+ }
+ logger.warn("DMN model stream not found!!!");
+ return Optional.empty();
+ }
+
+ /**
+ * Internal Utility class.<br/>
+ * Use {@link Application#decisionModels()} of Kogito API to
programmatically access DMN assets and evaluate DMN
+ * decisions.
+ *
+ * @param customDMNProfiles
+ * @param enableRuntimeTypeCheckOption
+ * @param resources
+ * @return
+ */
+ static DMNRuntime createGenericDMNRuntime(Set<DMNProfile>
customDMNProfiles, boolean enableRuntimeTypeCheckOption, List<Resource>
resources) {
+ EvalHelper.clearGenericAccessorCache(); // KOGITO-3325 DMN hot reload
manage accessor cache when stronglytyped
+ DMNRuntimeBuilder dmnRuntimeBuilder = DMNRuntimeBuilder.fromDefaults();
+ customDMNProfiles.forEach(dmnRuntimeBuilder::addProfile);
+ DMNRuntime dmnRuntime = dmnRuntimeBuilder
+ .buildConfiguration()
+ .fromResources(resources)
+ .getOrElseThrow(e -> new RuntimeException("Error initializing
DMNRuntime", e));
+ RuntimeTypeCheckOption runtimeTypeCheckOption = new
RuntimeTypeCheckOption(enableRuntimeTypeCheckOption);
+ ((DMNRuntimeImpl) dmnRuntime).setOption(runtimeTypeCheckOption);
+ DMNKogitoCallbacks.afterCreateGenericDMNRuntime(dmnRuntime);
+ return dmnRuntime;
+ }
+
}
diff --git
a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogitoCallbacks.java
b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogitoCallbacks.java
index d54804fef5..5b6b20f08b 100644
--- a/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogitoCallbacks.java
+++ b/drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogitoCallbacks.java
@@ -19,12 +19,9 @@
package org.kie.kogito.dmn;
import java.io.Reader;
-import java.util.function.BiFunction;
+import java.util.Map;
import org.kie.dmn.api.core.DMNRuntime;
-import org.kie.kogito.ExecutionIdSupplier;
-import org.kie.kogito.KogitoGAV;
-import org.kie.kogito.decision.DecisionModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,11 +38,11 @@ public final class DMNKogitoCallbacks {
}
public static void beforeCreateGenericDMNRuntime(Reader[] readers) {
- if (isGraalVMNIRuntime()) {
- LOG.warn("createGenericDMNRuntime with {} model(s) for DMNRuntime
initialization...", readers.length);
- } else {
- LOG.debug("createGenericDMNRuntime with {} model(s) for DMNRuntime
initialization...", readers.length);
- }
+ beforeCreateGenericDMNRuntime(readers.length);
+ }
+
+ public static void beforeCreateGenericDMNRuntime(Map<String, String>
modelPaths) {
+ beforeCreateGenericDMNRuntime(modelPaths.size());
}
public static void afterCreateGenericDMNRuntime(DMNRuntime dmnRuntime) {
@@ -56,9 +53,7 @@ public final class DMNKogitoCallbacks {
}
}
- public static void beforeAbstractDecisionModelsInit(ExecutionIdSupplier
executionIdSupplier,
- BiFunction<DecisionModel, KogitoGAV, DecisionModel>
decisionModelTransformerInit,
- Reader[] readers) {
+ public static void beforeAbstractDecisionModelsInit() {
if (isGraalVMNIRuntime()) {
LOG.warn("AbstractDecisionModels.init() called.");
} else {
@@ -74,6 +69,14 @@ public final class DMNKogitoCallbacks {
}
}
+ private static void beforeCreateGenericDMNRuntime(int size) {
+ if (isGraalVMNIRuntime()) {
+ LOG.warn("createGenericDMNRuntime with {} model(s) for DMNRuntime
initialization...", size);
+ } else {
+ LOG.debug("createGenericDMNRuntime with {} model(s) for DMNRuntime
initialization...", size);
+ }
+ }
+
private static boolean isGraalVMNIRuntime() {
return
"runtime".equals(System.getProperty("org.graalvm.nativeimage.imagecode"));
}
diff --git
a/drools/kogito-dmn/src/test/java/org/kie/kogito/dmn/DMNKogitoTest.java
b/drools/kogito-dmn/src/test/java/org/kie/kogito/dmn/DMNKogitoTest.java
index 2d9d185715..43e47ee680 100644
--- a/drools/kogito-dmn/src/test/java/org/kie/kogito/dmn/DMNKogitoTest.java
+++ b/drools/kogito-dmn/src/test/java/org/kie/kogito/dmn/DMNKogitoTest.java
@@ -19,7 +19,9 @@
package org.kie.kogito.dmn;
import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
+import java.util.Map;
import org.junit.jupiter.api.Test;
import org.kie.dmn.api.core.DMNMessage.Severity;
@@ -33,7 +35,7 @@ public class DMNKogitoTest {
@Test
public void testBasic() {
- DMNRuntime dmnRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false, new
InputStreamReader(DMNKogitoTest.class.getResourceAsStream("TrafficViolation.dmn")));
+ DMNRuntime dmnRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false,
Map.of("/TrafficViolation.dmn", StandardCharsets.UTF_8.name()));
assertThat(dmnRuntime.getModels()).hasSize(1);
final String TRAFFIC_VIOLATION_NS =
"https://github.com/kiegroup/drools/kie-dmn/_A4BCA8B8-CF08-433F-93B2-A2598F19ECFF";
diff --git
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java
index c21375c02a..c52d93bbdc 100644
---
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java
+++
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java
@@ -19,6 +19,9 @@
*/
package org.kie.kogito.codegen.decision;
+import java.io.BufferedReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -77,6 +80,8 @@ import static
org.kie.efesto.common.core.utils.JSONUtils.getGeneratedResourcesSt
import static
org.kie.kogito.codegen.decision.CodegenUtils.getDefinitionsFileFromModel;
import static
org.kie.kogito.codegen.decision.DecisionCodegen.STRONGLY_TYPED_CONFIGURATION_KEY;
import static
org.kie.kogito.codegen.decision.DecisionRestResourceGenerator.DMN_DEFINITIONS_JSON_REFS;
+import static org.kie.kogito.codegen.decision.ReadResourceUtil.getResourcePath;
+import static org.kie.kogito.dmn.AbstractDecisionModels.DMN_MODEL_PATHS_FILE;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class DecisionCodegenUtils {
@@ -94,6 +99,16 @@ public class DecisionCodegenUtils {
private DecisionCodegenUtils() {
}
+ /**
+ *
+ * @param generatedFiles Act as accumulator for all generated files
+ * @param classesForManualReflection
+ * @param cResources
+ * @param customDMNProfiles
+ * @param runtimeTypeCheckOption
+ * @param generator
+ * @return A Map.Entry with the dmn-specific generated files.
+ */
static Map.Entry<String, GeneratedResources>
generateModelsFromResources(Collection<GeneratedFile> generatedFiles,
List<String> classesForManualReflection,
List<CollectedResource> cResources,
@@ -115,6 +130,7 @@ public class DecisionCodegenUtils {
}
generateModel(generatedFiles, classesForManualReflection, model,
generator, stronglyTypedEnabled, marshaller);
}
+ generateModelPathsFile(generatedFiles, cResources);
generateCloudEventsResources(generatedFiles, generator.context(),
dmnModels);
generateAndStoreDecisionModelResourcesProvider(generatedFiles,
resources, generator.context(), generator.applicationCanonicalName());
return generatedResourcesEntry;
@@ -256,6 +272,17 @@ public class DecisionCodegenUtils {
storeFile(generatedFiles, GeneratedFileType.INTERNAL_RESOURCE,
relativePath, marshaller.marshal(definitions));
}
+ static void generateModelPathsFile(Collection<GeneratedFile>
generatedFiles, Collection<CollectedResource> resources) {
+ StringBuilder builder = new StringBuilder();
+ for (CollectedResource resource : resources) {
+ String path = getResourcePath(resource);
+ Optional<String> encoding = determineEncoding(resource);
+ builder.append(String.format("%s:%s%n", path,
encoding.orElse(StandardCharsets.UTF_8.name())));
+ }
+ String content = builder.toString();
+ storeFile(generatedFiles, GeneratedFileType.INTERNAL_RESOURCE,
DMN_MODEL_PATHS_FILE, content);
+ }
+
static void generateCloudEventsResources(Collection<GeneratedFile>
generatedFiles, KogitoBuildContext context, List<DMNModel> dmnModels) {
if (context.getAddonsConfig().useCloudEvents()) {
final DecisionCloudEventMetaFactoryGenerator
ceMetaFactoryGenerator = new DecisionCloudEventMetaFactoryGenerator(context,
dmnModels);
@@ -334,6 +361,25 @@ public class DecisionCodegenUtils {
storeFile(generatedFiles, GeneratedFileType.SOURCE,
generator.generatedFilePath(), generator.generate());
}
+ private static Optional<String> determineEncoding(CollectedResource
resource) {
+ try (Reader reader = resource.resource().getReader()) {
+ BufferedReader br = new BufferedReader(reader);
+ StringBuilder sb = new StringBuilder(br.readLine());
+ sb.append(br.readLine());
+ String head = sb.toString();
+ boolean prologUTF8 = head.startsWith("<?xml version=\"1.0\"
encoding=\"UTF-8\"") || head.startsWith("<?xml version=\"1.0\"
encoding=\"utf-8\"");
+ boolean kogitoDMNEditor =
head.contains("xmlns:kie=\"http://www.drools.org/kie/dmn");
+ LOGGER.debug("resource {} determineEncoding results; prologUTF8
{}, kogitoDMNEditor {}.", resource.resource(), prologUTF8, kogitoDMNEditor);
+ if (prologUTF8 || kogitoDMNEditor) {
+ return Optional.of("UTF-8");
+ } else {
+ return Optional.empty();
+ }
+ } catch (Exception e) {
+ return Optional.empty();
+ }
+ }
+
private static void storeFile(Collection<GeneratedFile> generatedFiles,
GeneratedFileType type, String path, String source) {
generatedFiles.add(new GeneratedFile(type, path, source));
}
diff --git
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionContainerGenerator.java
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionContainerGenerator.java
index 89ded1dfa7..2f9adbd118 100644
---
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionContainerGenerator.java
+++
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionContainerGenerator.java
@@ -18,12 +18,10 @@
*/
package org.kie.kogito.codegen.decision;
-import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import org.kie.dmn.core.compiler.DMNProfile;
@@ -43,6 +41,7 @@ import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.InitializerDeclaration;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.FieldAccessExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.NullLiteralExpr;
@@ -51,7 +50,7 @@ import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import static org.kie.kogito.codegen.core.CodegenUtils.newObject;
-import static
org.kie.kogito.codegen.decision.ReadResourceUtil.getReadResourceMethod;
+import static org.kie.kogito.dmn.AbstractDecisionModels.DMN_MODEL_PATHS_FILE;
public class DecisionContainerGenerator extends AbstractApplicationSection {
@@ -85,9 +84,6 @@ public class DecisionContainerGenerator extends
AbstractApplicationSection {
@Override
public CompilationUnit compilationUnit() {
CompilationUnit compilationUnit =
templatedGenerator.compilationUnitOrThrow("Invalid Template: No
CompilationUnit");
-
- ClassOrInterfaceType applicationClass =
StaticJavaParser.parseClassOrInterfaceType(applicationCanonicalName);
-
final InitializerDeclaration staticDeclaration = compilationUnit
.findFirst(InitializerDeclaration.class)
.orElseThrow(() -> new InvalidTemplateException(
@@ -103,37 +99,10 @@ public class DecisionContainerGenerator extends
AbstractApplicationSection {
setupDecisionModelTransformerVariable(initMethod,
context.getAddonsConfig().useMonitoring());
setupCustomDMNProfiles(initMethod, customDMNProfiles);
setupEnableRuntimeTypeCheckOption(initMethod,
enableRuntimeTypeCheckOption);
-
- for (CollectedResource resource : resources) {
- Optional<String> encoding = determineEncoding(resource);
- MethodCallExpr getResAsStream =
getReadResourceMethod(applicationClass, resource);
- MethodCallExpr isr = new
MethodCallExpr("readResource").addArgument(getResAsStream);
- encoding.map(StringLiteralExpr::new).ifPresent(isr::addArgument);
- initMethod.addArgument(isr);
- }
-
+ setupModelPathsFile(initMethod, applicationCanonicalName);
return compilationUnit;
}
- private Optional<String> determineEncoding(CollectedResource resource) {
- try {
- BufferedReader br = new
BufferedReader(resource.resource().getReader());
- StringBuilder sb = new StringBuilder(br.readLine());
- sb.append(br.readLine());
- String head = sb.toString();
- boolean prologUTF8 = head.startsWith("<?xml version=\"1.0\"
encoding=\"UTF-8\"") || head.startsWith("<?xml version=\"1.0\"
encoding=\"utf-8\"");
- boolean kogitoDMNEditor =
head.contains("xmlns:kie=\"http://www.drools.org/kie/dmn");
- LOG.debug("resource {} determineEncoding results; prologUTF8 {},
kogitoDMNEditor {}.", resource.resource(), prologUTF8, kogitoDMNEditor);
- if (prologUTF8 || kogitoDMNEditor) {
- return Optional.of("UTF-8");
- } else {
- return Optional.empty();
- }
- } catch (Exception e) {
- return Optional.empty();
- }
- }
-
static void setupExecIdSupplierVariable(MethodCallExpr initMethod, boolean
useTracing) {
Expression execIdSupplier = useTracing ?
newObject(DmnExecutionIdSupplier.class) : new NullLiteralExpr();
initMethod.addArgument(execIdSupplier);
@@ -164,6 +133,14 @@ public class DecisionContainerGenerator extends
AbstractApplicationSection {
initMethod.addArgument(toAdd);
}
+ static void setupModelPathsFile(MethodCallExpr initMethod, String
applicationCanonicalName) {
+ ClassOrInterfaceType applicationClass =
StaticJavaParser.parseClassOrInterfaceType(applicationCanonicalName);
+ FieldAccessExpr fieldAccessExpr = new
FieldAccessExpr(applicationClass.getNameAsExpression(), "class");
+ MethodCallExpr methodCallExpr = new MethodCallExpr(fieldAccessExpr,
"getResource")
+ .addArgument(new StringLiteralExpr("/" +
DMN_MODEL_PATHS_FILE));
+ initMethod.addArgument(methodCallExpr);
+ }
+
public List<String> getClassesForManualReflection() {
return classesForManualReflection;
}
diff --git
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/ReadResourceUtil.java
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/ReadResourceUtil.java
index 976f5939a6..512f299cf9 100644
---
a/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/ReadResourceUtil.java
+++
b/kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/ReadResourceUtil.java
@@ -40,14 +40,23 @@ class ReadResourceUtil {
}
public static MethodCallExpr getReadResourceMethod(ClassOrInterfaceType
applicationClass, CollectedResource resource) {
+ String resourcePath = getResourcePath(resource);
if (resource.basePath().toString().endsWith(".jar")) {
return new MethodCallExpr(
new MethodCallExpr(new
NameExpr(IoUtils.class.getCanonicalName() + ".class"), "getClassLoader"),
- "getResourceAsStream").addArgument(new
StringLiteralExpr(getDecisionModelJarResourcePath(resource)));
+ "getResourceAsStream").addArgument(new
StringLiteralExpr(resourcePath));
}
return new MethodCallExpr(new
FieldAccessExpr(applicationClass.getNameAsExpression(), "class"),
"getResourceAsStream")
- .addArgument(new
StringLiteralExpr(getDecisionModelRelativeResourcePath(resource)));
+ .addArgument(new StringLiteralExpr(resourcePath));
+ }
+
+ public static String getResourcePath(CollectedResource resource) {
+ if (resource.basePath().toString().endsWith(".jar")) {
+ return getDecisionModelJarResourcePath(resource);
+ } else {
+ return getDecisionModelRelativeResourcePath(resource);
+ }
}
private static String getDecisionModelJarResourcePath(CollectedResource
resource) {
diff --git
a/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCloudEventMetaFactoryGeneratorTest.java
b/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCloudEventMetaFactoryGeneratorTest.java
index 71c69ebe44..551d010cfa 100644
---
a/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCloudEventMetaFactoryGeneratorTest.java
+++
b/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCloudEventMetaFactoryGeneratorTest.java
@@ -36,8 +36,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
class DecisionCloudEventMetaFactoryGeneratorTest {
private static final String MODEL_PATH =
"src/test/resources/decision/models/vacationDays";
- private static final int EXPECTED_FILES_WITH_CLOUDEVENTS = 6; // Now it
includes IndexFile.dmn_json
- private static final int EXPECTED_FILES_WITHOUT_CLOUDEVENTS = 5; // Now it
includes IndexFile.dmn_json
+ private static final int EXPECTED_FILES_WITH_CLOUDEVENTS = 7; // Now it
includes IndexFile.dmn_json and dmnModelPaths.txt
+ private static final int EXPECTED_FILES_WITHOUT_CLOUDEVENTS = 6; // Now it
includes IndexFile.dmn_json and dmnModelPaths.txt
private static final String EXPECTED_FILE_PATH =
"org/kie/kogito/app/DecisionCloudEventMetaFactory.java";
@Test
diff --git
a/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCodegenUtilsTest.java
b/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCodegenUtilsTest.java
index f1856328cc..c0e6b2fd2e 100644
---
a/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCodegenUtilsTest.java
+++
b/kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCodegenUtilsTest.java
@@ -20,12 +20,17 @@
package org.kie.kogito.codegen.decision;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
+import org.drools.codegen.common.GeneratedFile;
+import org.drools.codegen.common.GeneratedFileType;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.kie.api.io.Resource;
@@ -35,6 +40,9 @@ import org.kie.kogito.codegen.api.context.KogitoBuildContext;
import org.kie.kogito.codegen.api.io.CollectedResource;
import org.kie.kogito.codegen.core.io.CollectedResourceProducer;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.kie.kogito.dmn.AbstractDecisionModels.DMN_MODEL_PATHS_FILE;
+
class DecisionCodegenUtilsTest {
@ParameterizedTest
@@ -45,7 +53,26 @@ class DecisionCodegenUtilsTest {
Paths.get("src/test/resources/decision/models/vacationDays").toAbsolutePath());
Map<Resource, CollectedResource> r2cr =
cResources.stream().collect(Collectors.toMap(CollectedResource::resource,
Function.identity()));
Map.Entry<String, GeneratedResources> retrieved =
DecisionCodegenUtils.loadModelsAndValidate(context, r2cr,
Collections.emptySet(), new RuntimeTypeCheckOption(false));
- System.out.println(retrieved.getKey());
+ assertThat(retrieved).isNotNull();
+ }
+
+ @Test
+ void generateModelPathsFile() {
+ final Collection<CollectedResource> cResources =
CollectedResourceProducer.fromPaths(
+
Paths.get("src/test/resources/decision/models/vacationDays").toAbsolutePath(),
+
Paths.get("src/test/resources/decision/alltypes").toAbsolutePath());
+ Collection<GeneratedFile> generatedFiles = new ArrayList<>();
+ DecisionCodegenUtils.generateModelPathsFile(generatedFiles,
cResources);
+ assertThat(generatedFiles).hasSize(1);
+ GeneratedFile retrieved = generatedFiles.iterator().next();
+ assertThat(retrieved).isNotNull();
+
assertThat(retrieved.type()).isEqualTo(GeneratedFileType.INTERNAL_RESOURCE);
+
assertThat(retrieved.path().toString()).isEqualTo(DMN_MODEL_PATHS_FILE);
+ List<String> lines = new String(retrieved.contents()).lines().toList();
+ assertThat(lines).hasSize(2);
+ assertThat(lines)
+ .anyMatch(line -> line.equals("/vacationDays.dmn:UTF-8"))
+ .anyMatch(line -> line.equals("/OneOfEachType.dmn:UTF-8"));
}
}
diff --git
a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/AbstractCodegenIT.java
b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/AbstractCodegenIT.java
index 750738220c..258999e87f 100644
---
a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/AbstractCodegenIT.java
+++
b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/AbstractCodegenIT.java
@@ -19,6 +19,7 @@
package org.kie.kogito.codegen;
import java.io.File;
+import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
@@ -31,6 +32,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Properties;
import java.util.function.BiFunction;
@@ -62,6 +64,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.kie.kogito.dmn.AbstractDecisionModels.DMN_MODEL_PATHS_FILE;
import static
org.kie.kogito.services.jobs.impl.StaticJobService.staticJobService;
public abstract class AbstractCodegenIT {
@@ -193,23 +196,31 @@ public abstract class AbstractCodegenIT {
sources.add("org/drools/project/model/ProjectRuntime.java");
srcMfs.write("org/drools/project/model/ProjectRuntime.java",
DUMMY_PROCESS_RUNTIME.getBytes());
}
-
- if (LOGGER.isInfoEnabled()) {
- Path temp = Files.createTempDirectory("KOGITO_TESTS");
- LOGGER.info("Dumping generated files in " + temp);
- for (GeneratedFile entry : generatedFiles) {
- Path fpath = temp.resolve(entry.relativePath());
- fpath.getParent().toFile().mkdirs();
- Files.write(fpath, entry.contents());
+ Path temp = null;
+ URL modelPathsUrl = null;
+ String modelPathsFilePath = null;
+ for (GeneratedFile entry : generatedFiles) {
+ String fileName = entry.relativePath();
+ if (fileName.contains(DMN_MODEL_PATHS_FILE)) {
+ TempPaths tempPaths = conditionallyDumpGeneratedFile(temp,
entry);
+ temp = tempPaths.tempDir;
+ Path fpath = tempPaths.fpath;
+ modelPathsUrl = fpath.toUri().toURL();
+ modelPathsFilePath = entry.relativePath();
+ } else if (LOGGER.isInfoEnabled()) {
+ temp = conditionallyDumpGeneratedFile(temp, entry).tempDir;
}
}
-
CompilationResult result = JAVA_COMPILER.compile(sources.toArray(new
String[sources.size()]), srcMfs, trgMfs,
ClassLoaderUtils.getDefaultClassLoader());
assertThat(result).isNotNull();
assertThat(result.getErrors()).describedAs(String.join("\n\n",
Arrays.toString(result.getErrors()))).isEmpty();
classloader = new TestClassLoader(this.getClass().getClassLoader(),
trgMfs.getMap());
+ if (modelPathsUrl != null && modelPathsFilePath != null) {
+ classloader.addCustomResource(modelPathsFilePath, modelPathsUrl);
+ }
+
@SuppressWarnings("unchecked")
Class<Application> app = (Class<Application>)
Class.forName(context.getPackageName() + ".Application", true, classloader);
@@ -220,6 +231,16 @@ public abstract class AbstractCodegenIT {
return application;
}
+ private TempPaths conditionallyDumpGeneratedFile(Path temp, GeneratedFile
entry) throws IOException {
+ Path tempDirectory = temp != null ? temp :
Files.createTempDirectory("KOGITO_TESTS");
+ String relativePath = entry.relativePath();
+ LOGGER.info("Dumping generated file {} in {}", relativePath, temp);
+ Path fpath = tempDirectory.resolve(relativePath);
+ fpath.getParent().toFile().mkdirs();
+ Files.write(fpath, entry.contents());
+ return new TempPaths(tempDirectory, fpath);
+ }
+
private void initTimer(Application app) {
Processes processes = app.get(Processes.class);
UserTasks userTasks = app.get(UserTasks.class);
@@ -264,6 +285,7 @@ public abstract class AbstractCodegenIT {
private static class TestClassLoader extends URLClassLoader {
private final Map<String, byte[]> extraClassDefs;
+ private Map<String, URL> customAddedResource = new HashMap<>();
public TestClassLoader(ClassLoader parent, Map<PortablePath, byte[]>
extraClassDefs) {
super(new URL[0], parent);
@@ -274,6 +296,10 @@ public abstract class AbstractCodegenIT {
}
}
+ public void addCustomResource(String name, URL toAdd) {
+ customAddedResource.put(name, toAdd);
+ }
+
@Override
protected Class<?> findClass(final String name) throws
ClassNotFoundException {
byte[] classBytes = this.extraClassDefs.remove(name);
@@ -282,6 +308,19 @@ public abstract class AbstractCodegenIT {
}
return super.findClass(name);
}
+
+ @Override
+ public URL findResource(String name) {
+ URL url = customAddedResource.get(name);
+ return url != null ? url : super.findResource(name);
+ }
+ }
+
+ private record TempPaths(Path tempDir, Path fpath) {
+ public TempPaths {
+ Objects.requireNonNull(tempDir);
+ Objects.requireNonNull(fpath);
+ }
}
}
diff --git
a/quarkus/extensions/kogito-quarkus-decisions-extension/kogito-quarkus-decisions-integration-test/src/test/resources/application.properties
b/quarkus/extensions/kogito-quarkus-decisions-extension/kogito-quarkus-decisions-integration-test/src/test/resources/application.properties
index 65e0f5a0d2..916bcb44b0 100644
---
a/quarkus/extensions/kogito-quarkus-decisions-extension/kogito-quarkus-decisions-integration-test/src/test/resources/application.properties
+++
b/quarkus/extensions/kogito-quarkus-decisions-extension/kogito-quarkus-decisions-integration-test/src/test/resources/application.properties
@@ -17,4 +17,5 @@
# under the License.
#
-quarkus.http.test-port=0
\ No newline at end of file
+quarkus.http.test-port=0
+quarkus.log.category."org.kie.kogito".level=WARN
diff --git
a/springboot/addons/explainability/src/test/java/org/kie/kogito/explainability/ApplicationMock.java
b/springboot/addons/explainability/src/test/java/org/kie/kogito/explainability/ApplicationMock.java
index 8db66e2c2c..c1cf1851c5 100644
---
a/springboot/addons/explainability/src/test/java/org/kie/kogito/explainability/ApplicationMock.java
+++
b/springboot/addons/explainability/src/test/java/org/kie/kogito/explainability/ApplicationMock.java
@@ -18,8 +18,9 @@
*/
package org.kie.kogito.explainability;
-import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
+import java.util.Map;
import org.kie.dmn.api.core.DMNRuntime;
import org.kie.kogito.Application;
@@ -32,8 +33,7 @@ import org.kie.kogito.uow.UnitOfWorkManager;
public class ApplicationMock implements Application {
- final static DMNRuntime genericDMNRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false, new
InputStreamReader(
-
ApplicationMock.class.getResourceAsStream(Constants.MODEL_RESOURCE)));
+ final static DMNRuntime genericDMNRuntime =
DMNKogito.createGenericDMNRuntime(Collections.emptySet(), false,
Map.of(Constants.MODEL_RESOURCE, StandardCharsets.UTF_8.name()));
final static DecisionModels decisionModels;
diff --git
a/springboot/addons/tracing-decision/src/test/java/org/kie/kogito/tracing/decision/BaseSpringBootDecisionTracingTest.java
b/springboot/addons/tracing-decision/src/test/java/org/kie/kogito/tracing/decision/BaseSpringBootDecisionTracingTest.java
index 10b44bc5fa..247891e4a3 100644
---
a/springboot/addons/tracing-decision/src/test/java/org/kie/kogito/tracing/decision/BaseSpringBootDecisionTracingTest.java
+++
b/springboot/addons/tracing-decision/src/test/java/org/kie/kogito/tracing/decision/BaseSpringBootDecisionTracingTest.java
@@ -19,6 +19,7 @@
package org.kie.kogito.tracing.decision;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -89,8 +90,7 @@ public abstract class BaseSpringBootDecisionTracingTest {
}
private DMNRuntime buildDMNRuntime() {
- return DMNKogito.createGenericDMNRuntime(Collections.emptySet(),
false, new java.io.InputStreamReader(
-
BaseSpringBootDecisionTracingTest.class.getResourceAsStream(TEST_RESOURCE)));
+ return DMNKogito.createGenericDMNRuntime(Collections.emptySet(),
false, Map.of(TEST_RESOURCE, StandardCharsets.UTF_8.name()));
}
private DecisionModel buildDecisionModel(DMNRuntime runtime) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]