Copilot commented on code in PR #4229:
URL: 
https://github.com/apache/incubator-kie-kogito-runtimes/pull/4229#discussion_r3116831281


##########
drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/DMNKogito.java:
##########
@@ -58,17 +67,36 @@ private 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 {
+                        logger.warn("DMN model stream not found for path: {}", 
modelPathEntry.getKey());
+                    }
+                    return null;
+                })
+                .filter(Objects::nonNull)
+                .map(ReaderResource::new).collect(Collectors.toList());

Review Comment:
   `createGenericDMNRuntime(..., Map<String,String> modelPaths)` logs a warning 
and silently skips entries whose streams can’t be found, potentially 
initializing a runtime with missing models and failing later in less obvious 
ways. It would be safer to fail fast (throw) when any expected model can’t be 
loaded, or at least collect all missing paths and throw a single exception 
summarizing them.



##########
kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java:
##########
@@ -94,6 +98,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

Review Comment:
   The added Javadoc block has typos and placeholder-style tags (e.g., "ACt as 
accumulator" and empty `@return`). Either remove it or complete it with 
accurate parameter/return descriptions to avoid misleading documentation.
   ```suggestion
        * Loads and validates DMN models from the collected resources, then 
generates the
        * corresponding source files and metadata artifacts.
        *
        * @param generatedFiles accumulator for all generated files produced 
during code generation
        * @param classesForManualReflection class names that must be registered 
for manual reflection
        * @param cResources collected DMN resources to compile and process
        * @param customDMNProfiles custom DMN profiles to use during model 
loading and validation
        * @param runtimeTypeCheckOption runtime type check configuration to 
apply while compiling models
        * @param generator decision code generator providing build context and 
application metadata
        * @return the generated resources entry produced while loading and 
validating the DMN models
   ```



##########
kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/AbstractCodegenIT.java:
##########
@@ -194,22 +194,34 @@ protected Application generateCode(Map<TYPE, 
List<String>> resourcesTypeMap, Kog
             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 temp = Files.createTempDirectory("KOGITO_TESTS");
+        LOGGER.info("Dumping generated files in " + temp);
+        URL modelPathsUrl = null;
+        String modelPathsFilePath = null;
+        for (GeneratedFile entry : generatedFiles) {
+            String fileName = entry.relativePath();
+            if (fileName.contains("modelPaths.txt")) {
+                Path fpath = temp.resolve(entry.relativePath());
+                fpath.getParent().toFile().mkdirs();
+                Files.write(fpath, entry.contents());
+                modelPathsUrl = fpath.toUri().toURL();
+                modelPathsFilePath = entry.relativePath();
+            } else if (LOGGER.isInfoEnabled()) {

Review Comment:
   `generateCode(...)` now always creates a temp directory and logs "Dumping 
generated files" at INFO, even when INFO logging is disabled and even when no 
files are actually dumped. This can slow down test runs and leave many temp 
directories behind. Restore the previous `LOGGER.isInfoEnabled()` guard (or 
delete the temp dir when not needed) while still handling `modelPaths.txt` when 
present.
   ```suggestion
           boolean dumpGeneratedFiles = LOGGER.isInfoEnabled();
           Path temp = null;
           URL modelPathsUrl = null;
           String modelPathsFilePath = null;
           for (GeneratedFile entry : generatedFiles) {
               String fileName = entry.relativePath();
               if (fileName.contains("modelPaths.txt")) {
                   if (temp == null) {
                       temp = Files.createTempDirectory("KOGITO_TESTS");
                   }
                   Path fpath = temp.resolve(entry.relativePath());
                   fpath.getParent().toFile().mkdirs();
                   Files.write(fpath, entry.contents());
                   modelPathsUrl = fpath.toUri().toURL();
                   modelPathsFilePath = entry.relativePath();
               } else if (dumpGeneratedFiles) {
                   if (temp == null) {
                       temp = Files.createTempDirectory("KOGITO_TESTS");
                       LOGGER.info("Dumping generated files in " + temp);
                   }
   ```



##########
kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionContainerGenerator.java:
##########
@@ -103,37 +99,10 @@ public CompilationUnit compilationUnit() {
         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;

Review Comment:
   `DecisionContainerGenerator` no longer uses the `resources` collection or 
the `LOG` logger after switching to `setupModelPathsFile(...)`. Leaving these 
unused fields/imports makes the generator harder to maintain and may produce 
compiler warnings. Consider removing unused members or reintroducing usage 
where needed.



##########
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=DEBUG

Review Comment:
   Setting `org.kie.kogito` logging to DEBUG for this integration test module 
can significantly increase CI logs and make failures harder to scan. If this 
was only for troubleshooting, please remove it or scope it to a specific test 
via test logging configuration rather than committing DEBUG by default.
   ```suggestion
   quarkus.http.test-port=0
   ```



##########
kogito-codegen-modules/kogito-codegen-decisions/src/test/java/org/kie/kogito/codegen/decision/DecisionCodegenUtilsTest.java:
##########
@@ -45,7 +53,26 @@ void loadModelsAndValidate(KogitoBuildContext.Builder 
contextBuilder) {
                 
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 generateDecisionsFiles() {
+        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);

Review Comment:
   Test name `generateDecisionsFiles()` is misleading: it only asserts the 
contents of the generated `modelPaths.txt`. Renaming the test to reflect what 
it verifies will make failures easier to interpret (e.g., 
`generateModelPathsFile_shouldContainAllModels`).



##########
drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java:
##########
@@ -97,6 +110,21 @@ protected static java.io.InputStreamReader 
readResource(java.io.InputStream stre
         }
     }
 
+    static Map<String, String> getModelPaths(URL modelPathsUrl) {
+        LOG.trace("getModelPaths {}", modelPathsUrl);
+        if (modelPathsUrl == null) {
+            LOG.error("Failed to find {} with current thread classloader", 
DMN_MODEL_PATHS_FILE);
+            throw new IllegalStateException("Failed to find " + 
DMN_MODEL_PATHS_FILE);
+        }
+        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) {

Review Comment:
   `getModelPaths(...)` parses each line using `substring(0, 
line.indexOf(':'))` / `substring(line.indexOf(':') + 1)` without validating 
that `':'` exists. A malformed/blank line will cause 
`StringIndexOutOfBoundsException`, and `Collectors.toMap` will also throw on 
duplicate paths. Consider splitting with a limit of 2, skipping empty/comment 
lines, and providing an explicit merge function or throwing a descriptive 
exception when duplicates are encountered.



##########
kogito-codegen-modules/kogito-codegen-decisions/src/main/java/org/kie/kogito/codegen/decision/DecisionCodegenUtils.java:
##########
@@ -334,6 +360,25 @@ static void 
generateAndStoreDecisionModelResourcesProvider(Collection<GeneratedF
         storeFile(generatedFiles, GeneratedFileType.SOURCE, 
generator.generatedFilePath(), generator.generate());
     }
 
+    private static 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";);
+            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();
+        }

Review Comment:
   `determineEncoding(...)` doesn’t close the `Reader` obtained from 
`resource.resource().getReader()`, which can leak file handles during codegen 
(especially with many models). Also, `br.readLine()` can return `null`, so `new 
StringBuilder(br.readLine())` can throw NPE for short/empty files. Use 
try-with-resources and handle missing lines defensively.



##########
drools/kogito-dmn/src/main/java/org/kie/kogito/dmn/AbstractDecisionModels.java:
##########
@@ -97,6 +110,21 @@ protected static java.io.InputStreamReader 
readResource(java.io.InputStream stre
         }
     }
 
+    static Map<String, String> getModelPaths(URL modelPathsUrl) {
+        LOG.trace("getModelPaths {}", modelPathsUrl);
+        if (modelPathsUrl == null) {
+            LOG.error("Failed to find {} with current thread classloader", 
DMN_MODEL_PATHS_FILE);
+            throw new IllegalStateException("Failed to find " + 
DMN_MODEL_PATHS_FILE);

Review Comment:
   The log message "Failed to find ... with current thread classloader" is 
misleading here: `getModelPaths(...)` receives a `URL` from the caller rather 
than performing any classloader lookup. Update the message to reflect the 
actual failure (e.g., caller provided null / resource not found) so 
troubleshooting points to the right place.
   ```suggestion
               LOG.error("No URL provided for {}", DMN_MODEL_PATHS_FILE);
               throw new IllegalStateException("No URL provided for " + 
DMN_MODEL_PATHS_FILE);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to