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

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


The following commit(s) were added to refs/heads/main by this push:
     new 2f25f63c9 chore: make KameletsCatalog lookup methods null-safe (#2892)
2f25f63c9 is described below

commit 2f25f63c93ca79300175c09435709291ce9cc193
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Jun 30 13:43:38 2026 +0200

    chore: make KameletsCatalog lookup methods null-safe (#2892)
    
    * chore: make KameletsCatalog lookup methods null-safe
    
    getKameletsByType/getKameletsByNamespace/getKameletsByGroups/
    getKameletByProvider dereferenced getMetadata().getLabels()/getAnnotations()
    .get(key) directly, so a Kamelet missing the queried label/annotation would
    NPE and break the entire call. Guard the access through small helpers
    (labelValue/annotationValue). Behaviour is unchanged for the shipped catalog
    (the validator guarantees the labels); this is defense-in-depth for the
    public API. Also drop the dead if/else in getKameletByProvider (it already
    returns an empty list on no match) and add a test pinning the
    non-null / empty-on-no-match contract.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * chore: strengthen KameletsCatalog lookup contract test
    
    Address review feedback on the lookup null-safety test:
    - also assert the populated (non-empty) case for known label/annotation
      values, so the test covers both the populated and empty/no-match 
contracts;
    - add descriptive failure messages that print the actual list on the
      empty-on-no-match checks, keeping the module's JUnit Jupiter style (no new
      AssertJ dependency).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
---
 .../camel/kamelets/catalog/KameletsCatalog.java    | 50 +++++++++++++++-------
 .../kamelets/catalog/KameletsCatalogTest.java      | 22 ++++++++++
 2 files changed, 56 insertions(+), 16 deletions(-)

diff --git 
a/library/camel-kamelets-catalog/src/main/java/org/apache/camel/kamelets/catalog/KameletsCatalog.java
 
b/library/camel-kamelets-catalog/src/main/java/org/apache/camel/kamelets/catalog/KameletsCatalog.java
index e95260e15..845fd091b 100644
--- 
a/library/camel-kamelets-catalog/src/main/java/org/apache/camel/kamelets/catalog/KameletsCatalog.java
+++ 
b/library/camel-kamelets-catalog/src/main/java/org/apache/camel/kamelets/catalog/KameletsCatalog.java
@@ -96,6 +96,20 @@ public class KameletsCatalog {
         return fileName.substring(9);
     }
 
+    private static String labelValue(Kamelet kamelet, String key) {
+        if (kamelet.getMetadata() != null && kamelet.getMetadata().getLabels() 
!= null) {
+            return kamelet.getMetadata().getLabels().get(key);
+        }
+        return null;
+    }
+
+    private static String annotationValue(Kamelet kamelet, String key) {
+        if (kamelet.getMetadata() != null && 
kamelet.getMetadata().getAnnotations() != null) {
+            return kamelet.getMetadata().getAnnotations().get(key);
+        }
+        return null;
+    }
+
 
     public Map<String, Kamelet> getKamelets() {
         return kameletModels;
@@ -114,27 +128,33 @@ public class KameletsCatalog {
     }
 
     public List<Kamelet> getKameletsByType(String type) {
-        List<Kamelet> collect = kameletModels.entrySet().stream()
-                .filter(x -> 
x.getValue().getMetadata().getLabels().get(KameletLabelNames.KAMELET_LABEL_TYPE).contains(type))
+        return kameletModels.entrySet().stream()
+                .filter(x -> {
+                    String value = labelValue(x.getValue(), 
KameletLabelNames.KAMELET_LABEL_TYPE);
+                    return value != null && value.contains(type);
+                })
                 .map(Map.Entry::getValue)
                 .collect(Collectors.toList());
-        return collect;
     }
 
     public List<Kamelet> getKameletsByNamespace(String namespace) {
-        List<Kamelet> collect = kameletModels.entrySet().stream()
-                .filter(x -> 
x.getValue().getMetadata().getAnnotations().get(KameletAnnotationsNames.KAMELET_ANNOTATION_NAMESPACE).contains(namespace))
+        return kameletModels.entrySet().stream()
+                .filter(x -> {
+                    String value = annotationValue(x.getValue(), 
KameletAnnotationsNames.KAMELET_ANNOTATION_NAMESPACE);
+                    return value != null && value.contains(namespace);
+                })
                 .map(Map.Entry::getValue)
                 .collect(Collectors.toList());
-        return collect;
     }
 
     public List<Kamelet> getKameletsByGroups(String group) {
-        List<Kamelet> collect = kameletModels.entrySet().stream()
-                .filter(x -> 
x.getValue().getMetadata().getAnnotations().get(KameletAnnotationsNames.KAMELET_ANNOTATION_GROUP).contains(group))
+        return kameletModels.entrySet().stream()
+                .filter(x -> {
+                    String value = annotationValue(x.getValue(), 
KameletAnnotationsNames.KAMELET_ANNOTATION_GROUP);
+                    return value != null && value.contains(group);
+                })
                 .map(Map.Entry::getValue)
                 .collect(Collectors.toList());
-        return collect;
     }
 
     public Definition getKameletDefinition(String name) {
@@ -147,15 +167,13 @@ public class KameletsCatalog {
     }
 
     public List<Kamelet> getKameletByProvider(String provider) {
-        List<Kamelet> collect = kameletModels.entrySet().stream()
-                .filter(x -> 
x.getValue().getMetadata().getAnnotations().get(KameletAnnotationsNames.KAMELET_ANNOTATION_PROVIDER).equalsIgnoreCase(provider))
+        return kameletModels.entrySet().stream()
+                .filter(x -> {
+                    String value = annotationValue(x.getValue(), 
KameletAnnotationsNames.KAMELET_ANNOTATION_PROVIDER);
+                    return value != null && value.equalsIgnoreCase(provider);
+                })
                 .map(Map.Entry::getValue)
                 .collect(Collectors.toList());
-        if (!collect.isEmpty()) {
-            return collect;
-        } else {
-            return Collections.emptyList();
-        }
     }
 
     public List<String> getKameletRequiredProperties(String name) {
diff --git 
a/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
 
b/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
index 811085e03..aa1a67f65 100644
--- 
a/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
+++ 
b/library/camel-kamelets-catalog/src/test/java/org/apache/camel/kamelets/catalog/KameletsCatalogTest.java
@@ -126,6 +126,28 @@ public class KameletsCatalogTest {
         assertTrue(c.isEmpty());
     }
 
+    @Test
+    void testLookupMethodsContract() throws Exception {
+        // Positive case: a known label/annotation value returns a populated 
list.
+        
assertFalse(catalog.getKameletsByType(KameletTypeEnum.SOURCE.type()).isEmpty());
+        assertFalse(catalog.getKameletsByNamespace("AWS").isEmpty());
+        assertFalse(catalog.getKameletsByGroups("AWS S3").isEmpty());
+        assertFalse(catalog.getKameletByProvider("Apache Software 
Foundation").isEmpty());
+
+        // Hardened contract: the lookups return a non-null (possibly empty) 
list
+        // and never NPE on a Kamelet that lacks the queried label/annotation; 
an
+        // unknown value yields an empty list.
+        assertNotNull(catalog.getKameletsByName("does-not-exist"));
+        List<Kamelet> byType = catalog.getKameletsByType("does-not-exist");
+        assertTrue(byType.isEmpty(), () -> "expected an empty list for an 
unknown type but got " + byType);
+        List<Kamelet> byNamespace = 
catalog.getKameletsByNamespace("does-not-exist");
+        assertTrue(byNamespace.isEmpty(), () -> "expected an empty list for an 
unknown namespace but got " + byNamespace);
+        List<Kamelet> byGroup = catalog.getKameletsByGroups("does-not-exist");
+        assertTrue(byGroup.isEmpty(), () -> "expected an empty list for an 
unknown group but got " + byGroup);
+        List<Kamelet> byProvider = 
catalog.getKameletByProvider("does-not-exist");
+        assertTrue(byProvider.isEmpty(), () -> "expected an empty list for an 
unknown provider but got " + byProvider);
+    }
+
     @Test
     void testGetKameletsDependencies() throws Exception {
         List<String> deps = catalog.getKameletDependencies("aws-sqs-source");

Reply via email to