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

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git

commit db0e1c61f0878221742a126a51cf60a877976bb2
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Apr 3 10:59:36 2026 -0400

    Karavan App Backend Changes
---
 karavan-app/pom.xml                                |  5 ++++
 .../org/apache/camel/karavan/KaravanEvents.java    |  1 +
 .../camel/karavan/api/AbstractApiResource.java     |  5 +++-
 .../org/apache/camel/karavan/api/AuthResource.java |  2 +-
 .../karavan/api/CookieSessionAuthMechanism.java    |  2 +-
 .../apache/camel/karavan/api/PublicResource.java   |  6 ++--
 .../apache/camel/karavan/cache/KaravanCache.java   |  3 ++
 .../camel/karavan/complexity/ComplexityRoute.java  |  9 ++++++
 .../camel/karavan/docker/DockerHealthCheck.java    | 26 ++++++++++++++++
 .../apache/camel/karavan/docker/DockerService.java | 35 +++++++++-------------
 .../camel/karavan/listener/ActivityListener.java   | 12 ++++----
 .../karavan/listener/CamelReloadListener.java      |  1 -
 .../karavan/listener/NotificationListener.java     | 11 +++++++
 .../org/apache/camel/karavan/loader/GitLoader.java |  4 +--
 .../camel/karavan/model/DockerComposeService.java  |  4 ++-
 .../apache/camel/karavan/service/AuthService.java  |  1 -
 .../apache/camel/karavan/service/CodeService.java  | 22 ++++++++++----
 .../camel/karavan/service/ComplexityService.java   | 32 ++++++++++++++++----
 .../apache/camel/karavan/service/GitService.java   |  2 +-
 19 files changed, 132 insertions(+), 51 deletions(-)

diff --git a/karavan-app/pom.xml b/karavan-app/pom.xml
index 55395d3e..5e8d84ce 100644
--- a/karavan-app/pom.xml
+++ b/karavan-app/pom.xml
@@ -39,6 +39,7 @@
         <quinoa.version>2.7.1</quinoa.version>
         <commons-text.version>1.14.0</commons-text.version>
         <resources-plugin.version>3.3.0</resources-plugin.version>
+        <json-schema-validator.version>1.5.9</json-schema-validator.version>
         <docker-java.version>3.7.0</docker-java.version>
     </properties>
 
@@ -55,6 +56,10 @@
     </dependencyManagement>
 
     <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-cache</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-messaging</artifactId>
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/KaravanEvents.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/KaravanEvents.java
index ea9a16df..6fedc9fb 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/KaravanEvents.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/KaravanEvents.java
@@ -22,6 +22,7 @@ public class KaravanEvents {
 
     public static final String NOTIFICATION_PROJECTS_STARTED = 
"NOTIFICATION_PROJECTS_STARTED";
     public static final String NOTIFICATION_PROJECTS_IMPORTED = 
"NOTIFICATION_PROJECTS_IMPORTED";
+    public static final String NOTIFICATION_OTHER = "NOTIFICATION_OTHER";
     public static final String COMMIT_HAPPENED = "COMMIT_HAPPENED";
     public static final String NOTIFICATION_IMAGES_LOADED = 
"NOTIFICATION_IMAGES_LOADED";
 
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/AbstractApiResource.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/AbstractApiResource.java
index 2614f3b0..9f63e6c4 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/AbstractApiResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/AbstractApiResource.java
@@ -17,6 +17,7 @@
 package org.apache.camel.karavan.api;
 
 import io.quarkus.security.identity.SecurityIdentity;
+import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 import jakarta.inject.Inject;
 import org.apache.camel.karavan.cache.KaravanCache;
@@ -40,9 +41,11 @@ public class AbstractApiResource {
         String username = identity.getPrincipal().getName();
         var user = karavanCache.getUser(username);
 
+        var roles = new JsonArray(new 
java.util.ArrayList<>(identity.getRoles()));
+
         return JsonObject.of()
                 .put("email", user != null ? user.getEmail() : null)
                 .put("username", username)
-                .put("roles", new java.util.ArrayList<>(identity.getRoles())); 
// from Quarkus
+                .put("roles", roles);
     }
 }
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
index f8e71178..e3f5fe0e 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
@@ -21,7 +21,7 @@ import static 
org.apache.camel.karavan.service.AuthService.SESSION_MAX_AGE;
 public class AuthResource extends AbstractApiResource {
 
     private static final Logger LOGGER = 
Logger.getLogger(AuthResource.class.getName());
-    private static final String SESSION_ID = "sessionId";
+    private static final String SESSION_ID = "taskId";
     private static final String CSRF = "csrf";
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/CookieSessionAuthMechanism.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/CookieSessionAuthMechanism.java
index 82825c67..f0c1ce82 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/CookieSessionAuthMechanism.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/CookieSessionAuthMechanism.java
@@ -43,7 +43,7 @@ public class CookieSessionAuthMechanism implements 
HttpAuthenticationMechanism {
         try {
             builder.setPrincipal(() -> "anonymous");
             builder.setAnonymous(true);
-            var cookie = ctx.request().getCookie("sessionId");
+            var cookie = ctx.request().getCookie("taskId");
             if (cookie == null) {
                 return Uni.createFrom().item(builder.build());
             }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
index 7c880378..a57b5b2d 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
@@ -24,7 +24,7 @@ import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 import org.apache.camel.karavan.KaravanConstants;
-import org.apache.camel.karavan.docker.DockerService;
+import org.apache.camel.karavan.docker.DockerHealthCheck;
 import org.apache.camel.karavan.kubernetes.KubernetesStatusService;
 import org.apache.camel.karavan.loader.StartupLoader;
 import org.apache.camel.karavan.service.ConfigService;
@@ -45,7 +45,7 @@ public class PublicResource {
     KubernetesStatusService kubernetesStatusService;
 
     @Inject
-    DockerService dockerService;
+    DockerHealthCheck dockerHealthCheck;
 
     @ConfigProperty(name = "karavan.environment", defaultValue = 
KaravanConstants.DEV)
     String environment;
@@ -55,7 +55,7 @@ public class PublicResource {
     @PermitAll
     @Produces(MediaType.APPLICATION_JSON)
     public Response getConfiguration() throws Exception {
-        var infraCheck = ConfigService.inKubernetes() ? 
kubernetesStatusService.call() : dockerService.call();
+        var infraCheck = ConfigService.inKubernetes() ? 
kubernetesStatusService.call() : dockerHealthCheck.call();
 
         List<HealthCheckResponse> list = List.of(
                 infraCheck,
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/cache/KaravanCache.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/cache/KaravanCache.java
index 318711f8..aa3cbffd 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/cache/KaravanCache.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/cache/KaravanCache.java
@@ -482,6 +482,9 @@ public class KaravanCache {
     }
 
     public void saveUserHeartBeat(ActivityUser activityUser) {
+        if (activityUser == null || activityUser.getUserName() == null) {
+            return;
+        }
         usersHeartBeat.put(activityUser.getUserName(), activityUser);
     }
 
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/complexity/ComplexityRoute.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/complexity/ComplexityRoute.java
index 3d4b9ec3..bd4080f0 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/complexity/ComplexityRoute.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/complexity/ComplexityRoute.java
@@ -8,6 +8,7 @@ import java.util.Map;
 public class ComplexityRoute {
 
     private String routeId;
+    private String routeDescription;
     private String nodePrefixId;
     private String routeTemplateRef;
     private Boolean isTemplated;
@@ -168,4 +169,12 @@ public class ComplexityRoute {
     public void setTemplated(Boolean templated) {
         isTemplated = templated;
     }
+
+    public String getRouteDescription() {
+        return routeDescription;
+    }
+
+    public void setRouteDescription(String routeDescription) {
+        this.routeDescription = routeDescription;
+    }
 }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerHealthCheck.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerHealthCheck.java
new file mode 100644
index 00000000..8ef1c026
--- /dev/null
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerHealthCheck.java
@@ -0,0 +1,26 @@
+package org.apache.camel.karavan.docker;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Default;
+import jakarta.inject.Inject;
+import org.apache.camel.karavan.service.ConfigService;
+import org.eclipse.microprofile.health.HealthCheck;
+import org.eclipse.microprofile.health.HealthCheckResponse;
+import org.eclipse.microprofile.health.Readiness;
+
+@Default
+@Readiness
+@ApplicationScoped
+public class DockerHealthCheck implements HealthCheck {
+
+    @Inject
+    DockerService dockerService;
+
+    @Override
+    public HealthCheckResponse call() {
+        if (!ConfigService.inKubernetes()) {
+            return dockerService.checkDocker() ? 
HealthCheckResponse.named("Docker").up().build() : 
HealthCheckResponse.named("Docker").down().build();
+        }
+        return HealthCheckResponse.named("Docker").up().build();
+    }
+}
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 10405b81..0811337e 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -9,6 +9,7 @@ import com.github.dockerjava.core.DockerClientImpl;
 import com.github.dockerjava.core.command.ExecStartResultCallback;
 import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
 import com.github.dockerjava.transport.DockerHttpClient;
+import io.quarkus.cache.CacheResult;
 import io.quarkus.runtime.ShutdownEvent;
 import io.quarkus.runtime.StartupEvent;
 import io.vertx.core.Vertx;
@@ -29,7 +30,6 @@ import 
org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.eclipse.microprofile.health.HealthCheckResponse;
 import org.eclipse.microprofile.health.Readiness;
 import org.jboss.logging.Logger;
 
@@ -46,7 +46,19 @@ import static org.apache.camel.karavan.KaravanConstants.*;
 @Default
 @Readiness
 @ApplicationScoped
-public class DockerService implements 
org.eclipse.microprofile.health.HealthCheck {
+public class DockerService {
+
+    @CacheResult(cacheName = "docker-check")
+    public boolean checkDocker() {
+        LOGGER.debug("Checking Docker");
+        try {
+            getDockerClient().infoCmd().exec();
+            return true;
+        } catch (Exception e) {
+            LOGGER.error("Error connecting Docker: " + e.getMessage());
+            return false;
+        }
+    }
 
     public enum PULL_IMAGE {
         always, ifNotExists, never
@@ -129,17 +141,6 @@ public class DockerService implements 
org.eclipse.microprofile.health.HealthChec
         }
     }
 
-    public boolean checkDocker() {
-        LOGGER.info("Checking Docker");
-        try {
-            getDockerClient().infoCmd().exec();
-            return true;
-        } catch (Exception e) {
-            LOGGER.error("Error connecting Docker: " + e.getMessage());
-            return false;
-        }
-    }
-
     public boolean checkDockerSwarm() {
         try {
             Info info = getDockerClient().infoCmd().exec();
@@ -484,12 +485,4 @@ public class DockerService implements 
org.eclipse.microprofile.health.HealthChec
     public void createConfig(String name, String config) {
         
getDockerClient().createConfigCmd().withName(name).withData(config.getBytes()).exec();
     }
-
-    @Override
-    public HealthCheckResponse call() {
-        if (!ConfigService.inKubernetes()) {
-            return checkDocker() ? 
HealthCheckResponse.named("Docker").up().build() : 
HealthCheckResponse.named("Docker").down().build();
-        }
-        return HealthCheckResponse.named("Docker").up().build();
-    }
 }
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/ActivityListener.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/ActivityListener.java
index b9d4d3f4..6cff2d7c 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/ActivityListener.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/ActivityListener.java
@@ -39,13 +39,13 @@ public class ActivityListener {
     @ConsumeEvent(value = ON_USER_ACTIVITY, ordered = true)
     public void onUserActivity(JsonObject json) {
         var activityUser = json.mapTo(ActivityUser.class);
-        if (activityUser != null && activityUser.getUserName() != null) {
-            if 
(ActivityUser.ActivityType.WORKING.equals(activityUser.getType())) {
-                karavanCache.saveUserWorking(activityUser);
-            } else {
-                karavanCache.saveUserHeartBeat(activityUser);
-            }
+        if (Objects.isNull(activityUser)) {
+        } else if 
(ActivityUser.ActivityType.WORKING.equals(activityUser.getType())) {
+            karavanCache.saveUserWorking(activityUser);
+        } else {
+            karavanCache.saveUserHeartBeat(activityUser);
         }
+
     }
 
     @ConsumeEvent(value = ON_PROJECT_ACTIVITY, ordered = true)
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/CamelReloadListener.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/CamelReloadListener.java
index 81ecf060..a1275bdf 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/CamelReloadListener.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/CamelReloadListener.java
@@ -74,7 +74,6 @@ public class CamelReloadListener {
         LOGGER.debug("Reload project code " + projectId);
         try {
             PodContainerStatus podContainerStatus = 
karavanCache.getDevModePodContainerStatus(projectId, environment);
-            System.out.println(podContainerStatus);
             deleteRequest(podContainerStatus);
             Map<String, String> files = 
codeService.getProjectFilesForDevMode(projectId, true);
             files.forEach((name, code) -> putRequest(podContainerStatus, name, 
code, 1000));
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/NotificationListener.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/NotificationListener.java
index 5d3ba97c..a3138969 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/listener/NotificationListener.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/listener/NotificationListener.java
@@ -41,6 +41,7 @@ public class NotificationListener {
     public static final String EVENT_COMMIT = "commit";
     public static final String EVENT_CONFIG_SHARED = "configShared";
     public static final String EVENT_IMAGES_LOADED = "imagesLoaded";
+    public static final String EVENT_PROJECT_CHANGED = "projectChanged";
 
     @Inject
     EventBus eventBus;
@@ -78,6 +79,16 @@ public class NotificationListener {
         }
     }
 
+    @ConsumeEvent(value = NOTIFICATION_OTHER, blocking = true)
+    public void onProjectChanges(JsonObject event) throws Exception {
+        String userId = event.getString("userName");
+        if (userId != null) {
+            send(userId, null, EVENT_PROJECT_CHANGED, "otherEvent", event);
+        } else {
+            sendSystem(null, EVENT_PROJECT_CHANGED, "otherEvent", event);
+        }
+    }
+
     @ConsumeEvent(value = COMMIT_HAPPENED, blocking = true, ordered = true)
     public void onCommitHappened(JsonObject event) throws Exception {
         JsonObject project = event.getJsonObject("project");
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/loader/GitLoader.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/loader/GitLoader.java
index 0f334cfb..d3cef68b 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/loader/GitLoader.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/loader/GitLoader.java
@@ -26,12 +26,12 @@ import org.apache.camel.karavan.service.CodeService;
 import org.apache.camel.karavan.service.GitHistoryService;
 import org.apache.camel.karavan.service.GitService;
 import org.apache.camel.karavan.service.ProjectService;
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
 import java.time.Instant;
 import java.util.Objects;
-import java.util.regex.Pattern;
 
 import static org.apache.camel.karavan.KaravanConstants.DEV;
 
@@ -94,7 +94,7 @@ public class GitLoader {
         try {
             ProjectFolder projectFolder = karavanCache.getProject(projectId);
             if (projectFolder == null) {
-                var title = 
Pattern.compile("^.").matcher(projectId).replaceFirst(m -> 
m.group().toUpperCase());
+                var title = projectId.length() < 5 ? projectId.toUpperCase() : 
StringUtils.capitalize(projectId);
                 projectFolder = new ProjectFolder(projectId, title, 
Instant.now().getEpochSecond() * 1000L, ProjectFolder.Type.valueOf(projectId));
                 karavanCache.saveProject(projectFolder, false);
 
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
index c1e82012..d1b52b01 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/model/DockerComposeService.java
@@ -110,7 +110,9 @@ public class DockerComposeService {
 
     public List<String> getEnvironmentList() {
         return environment != null
-                ? environment.entrySet().stream() .map(e -> 
e.getKey().concat("=").concat(e.getValue())).collect(Collectors.toList())
+                ? environment.entrySet().stream()
+                    .filter(e -> e.getKey() != null && e.getValue() != null)
+                    .map(e -> 
e.getKey().concat("=").concat(e.getValue())).collect(Collectors.toList())
                 : new ArrayList<>();
     }
 
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
index 49c7e305..3cf42533 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
@@ -30,7 +30,6 @@ public class AuthService {
     public static final String ROLE_ADMIN = "platform-admin";
     public static final String ROLE_DEVELOPER = "platform-developer";
     public static final String ROLE_USER = "platform-user";
-    public static final String ROLE_SYSTEM_BUILDER = "platform-system-builder";
 
     public static final String USER_ADMIN = "admin";
     public static final String USER_DEVELOPER = "developer";
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/CodeService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/CodeService.java
index 2bc9c474..b926b436 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/CodeService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/CodeService.java
@@ -70,7 +70,9 @@ public class CodeService {
     public static final String BUILD_SCRIPT_FILENAME = "build.sh";
     public static final String JSON_EXTENSION = ".json";
     public static final String YAML_EXTENSION = ".yaml";
+    public static final String GROOVY_EXTENSION = ".groovy";
     public static final String CAMEL_YAML_EXTENSION = ".camel.yaml";
+    public static final String KAMELET_YAML_EXTENSION = ".kamelet.yaml";
     public static final String COMPOSE_FILENAME_PREFIX= "docker-compose.";
 
     @ConfigProperty(name = "karavan.environment", defaultValue = 
KaravanConstants.DEV)
@@ -281,10 +283,10 @@ public class CodeService {
         return (ObjectNode) mapper.readTree(openApi);
     }
 
-    private ObjectNode readNodeFromYaml(String openApi) throws 
FileNotFoundException {
+    private ObjectNode readNodeFromYaml(String yaml) throws 
FileNotFoundException {
         final ObjectMapper mapper = new ObjectMapper();
         Yaml loader = new Yaml(new SafeConstructor(new LoaderOptions()));
-        Map map = loader.load(openApi);
+        Map map = loader.load(yaml);
         return mapper.convertValue(map, ObjectNode.class);
     }
 
@@ -301,6 +303,15 @@ public class CodeService {
         return null;
     }
 
+    public String getProjectProperty(String projectId, String property) {
+        var file = getApplicationProperties(projectId);
+        if (file != null) {
+            return getProperty(file.getCode(), property);
+        } else  {
+            return null;
+        }
+    }
+
     public static String getProperty(String file, String property) {
         String prefix = property + "=";
         return Arrays.stream(file.split("\\r?\\n")) // handle both \n and \r\n 
line endings
@@ -316,7 +327,7 @@ public class CodeService {
         return line.substring(0, parts).trim();
     }
 
-    public static String getGavPackageSuffix(String  projectId) {
+    public static String getGavPackageSuffix(String projectId) {
         return projectId.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
     }
 
@@ -469,8 +480,8 @@ public class CodeService {
     public List<String> listResources(String resourceFolder) {
         List<String> result = new ArrayList<>();
         try {
-            if (ConfigService.class.getResource(resourceFolder) != null) {
-                URI uri = 
ConfigService.class.getResource(resourceFolder).toURI();
+            if (CodeService.class.getResource(resourceFolder) != null) {
+                URI uri = 
CodeService.class.getResource(resourceFolder).toURI();
                 Path myPath;
                 FileSystem fileSystem = null;
                 if (uri.getScheme().equals("jar")) {
@@ -511,5 +522,4 @@ public class CodeService {
     public String getGav() {
         return gav.orElse("org.camel.karavan.demo") + ":%s:1";
     }
-
 }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/ComplexityService.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/ComplexityService.java
index 62bd2b72..828067fc 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/ComplexityService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/ComplexityService.java
@@ -82,6 +82,8 @@ public class ComplexityService {
         return karavanCache.getFolders().stream()
                 .filter(p -> Objects.equals(p.getType(), 
ProjectFolder.Type.integration)
                         || Objects.equals(p.getType(), 
ProjectFolder.Type.templates)
+                        || Objects.equals(p.getType(), 
ProjectFolder.Type.kamelets)
+                        || Objects.equals(p.getType(), 
ProjectFolder.Type.documentation)
                         || Objects.equals(p.getType(), 
ProjectFolder.Type.contracts))
                 .map(this::getProjectComplexity).toList();
     }
@@ -144,6 +146,7 @@ public class ComplexityService {
             complexityProject.setRoutes(routes);
         } catch (Exception e) {
             LOGGER.error(e);
+            e.printStackTrace();
         }
         return calculateComplexity(complexityProject);
     }
@@ -333,9 +336,7 @@ public class ComplexityService {
 
     private List<ComplexityRoute> getRoutes(String code, String fileName) {
         List<ComplexityRoute> result = new ArrayList<>();
-        Yaml yaml = new Yaml();
-        List<Object> obj = yaml.load(code);
-        JsonArray json = JsonArray.of(obj);
+        JsonArray json = getRouteJsonArray(code);
         for (Object list : json) {
             if (list instanceof JsonArray l) {
                 for (Object obj1 : l) {
@@ -357,12 +358,19 @@ public class ComplexityService {
         return result;
     }
 
-    private ComplexityRoute getRouteComplexity(JsonObject route, String 
fileName) {
+    public JsonArray getRouteJsonArray(String code) {
+        Yaml yaml = new Yaml();
+        List<Object> obj = yaml.load(code);
+        return JsonArray.of(obj);
+    }
+
+    public ComplexityRoute getRouteComplexity(JsonObject route, String 
fileName) {
         ComplexityRoute complexity = new ComplexityRoute();
         complexity.setFileName(fileName);
         try {
             complexity.setRouteId(route.getString("id"));
             complexity.setNodePrefixId(route.getString("nodePrefixId"));
+            complexity.setRouteDescription(route.getString("description"));
             var from = route.getJsonObject("from");
             var id = from.getString("id");
             var fromUri = from.getString("uri");
@@ -385,6 +393,7 @@ public class ComplexityService {
             }
         } catch (Exception e) {
             LOGGER.error(e);
+            e.printStackTrace();
         }
         return complexity;
     }
@@ -399,6 +408,7 @@ public class ComplexityService {
             complexity.setNodePrefixId(templatedRoute.getString("prefixId"));
         } catch (Exception e) {
             LOGGER.error(e);
+            e.printStackTrace();
         }
         return complexity;
     }
@@ -407,8 +417,17 @@ public class ComplexityService {
         try {
             for (Object stepObject : steps) {
                 var obj = (JsonObject) stepObject;
-                var stepName = obj.getMap().keySet().toArray()[0].toString();
-                var step = obj.getJsonObject(stepName);
+
+                if (obj.isEmpty()) {
+                    continue;
+                }
+
+                var stepName = obj.getMap().keySet().iterator().next();
+                Object rawValue = obj.getValue(stepName);
+                if (!(rawValue instanceof JsonObject step)) {
+                    continue; // Skip this step, as it's a String (or another 
type)
+                }
+                // Safe to cast now (line 414 equivalent)
                 if (stepName.equals("poll") || stepName.equals("pollEnrich")) {
                     var id = step.getString("id");
                     var uri = step.getString("uri");
@@ -470,6 +489,7 @@ public class ComplexityService {
             }
         } catch (Exception e) {
             LOGGER.error(e);
+            e.printStackTrace();
         }
         return complexity;
     }
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
index b035f915..9bd6c409 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/GitService.java
@@ -188,7 +188,7 @@ public class GitService {
                     boolean isFolder = treeWalk.isSubtree();
                     Iterable<RevCommit> commits = 
git.log().addPath(path).setMaxCount(1).call();
 
-                    if (isFolder) {
+                    if (isFolder && !path.startsWith(".")) {
                         for (RevCommit commit : commits) {
                             String commitId = commit.getName();
                             Long commitTime = 
Integer.valueOf(commit.getCommitTime()).longValue() * 1000;

Reply via email to