You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/03/14 18:49:09 UTC

(camel) 09/10: CAMEL-17641: Generate json metadata for pojo beans in camel-core that end users can use such as AggregationStrategy implementations. And have that information in camel-catalog for tooling assistance.

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

davsclaus pushed a commit to branch pojo-beans
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1ee83e533cfca1adcaaf2ba2b8e2effe0e5833f7
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Mar 14 18:48:09 2024 +0100

    CAMEL-17641: Generate json metadata for pojo beans in camel-core that end users can use such as AggregationStrategy implementations. And have that information in camel-catalog for tooling assistance.
---
 .../org/apache/camel/catalog/beans.properties      | 10 ++++
 .../catalog/beans/DefaultHeaderFilterStrategy.json | 16 +++++
 .../catalog/beans/FileIdempotentRepository.json    | 16 +++++
 .../beans/GroupedBodyAggregationStrategy.json      | 15 +++++
 .../beans/GroupedExchangeAggregationStrategy.json  | 15 +++++
 .../beans/GroupedMessageAggregationStrategy.json   | 15 +++++
 .../catalog/beans/MemoryAggregationRepository.json | 16 +++++
 .../catalog/beans}/MemoryIdempotentRepository.json |  2 +-
 .../catalog/beans/StringAggregationStrategy.json   | 16 +++++
 .../beans/UseLatestAggregationStrategy.json        | 15 +++++
 .../beans/UseOriginalAggregationStrategy.json      | 15 +++++
 .../catalog/components/langchain-embeddings.json   |  4 +-
 .../camel/bean/DefaultHeaderFilterStrategy.json    |  2 +-
 .../camel/bean/FileIdempotentRepository.json       |  2 +-
 .../camel/bean/MemoryIdempotentRepository.json     |  2 +-
 .../org/apache/camel/tooling/model/JsonMapper.java | 38 ++++++++++++
 .../apache/camel/tooling/model/PojoBeanModel.java  | 46 +++++++++++++++
 .../maven/packaging/GeneratePojoBeanMojo.java      |  2 +-
 .../camel/maven/packaging/PrepareCatalogMojo.java  | 69 +++++++++++++++++++++-
 19 files changed, 308 insertions(+), 8 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans.properties
new file mode 100644
index 00000000000..682e217224d
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans.properties
@@ -0,0 +1,10 @@
+DefaultHeaderFilterStrategy
+FileIdempotentRepository
+GroupedBodyAggregationStrategy
+GroupedExchangeAggregationStrategy
+GroupedMessageAggregationStrategy
+MemoryAggregationRepository
+MemoryIdempotentRepository
+StringAggregationStrategy
+UseLatestAggregationStrategy
+UseOriginalAggregationStrategy
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/DefaultHeaderFilterStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/DefaultHeaderFilterStrategy.json
new file mode 100644
index 00000000000..bfe3e06376a
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/DefaultHeaderFilterStrategy.json
@@ -0,0 +1,16 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "DefaultHeaderFilterStrategy",
+    "javaType": "org.apache.camel.support.DefaultHeaderFilterStrategy",
+    "interfaceType": "org.apache.camel.spi.HeaderFilterStrategy",
+    "title": "Default Header Filter Strategy",
+    "description": "The default header filtering strategy. Users can configure which headers is allowed or denied.",
+    "deprecated": true,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-support",
+    "version": "4.5.0-SNAPSHOT",
+    "properties": { "allowNullValues": { "index": 0, "kind": "property", "displayName": "Allow Null Values", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.support.DefaultHeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Whether to allow null values. By default a header is skipped if its value is null. Setting this to true will preserve the header." }, "caseInsensitive": { "in [...]
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/FileIdempotentRepository.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/FileIdempotentRepository.json
new file mode 100644
index 00000000000..ca6dbee7ea3
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/FileIdempotentRepository.json
@@ -0,0 +1,16 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "FileIdempotentRepository",
+    "javaType": "org.apache.camel.support.processor.idempotent.FileIdempotentRepository",
+    "interfaceType": "org.apache.camel.spi.IdempotentRepository",
+    "title": "File Idempotent Repository",
+    "description": "A file based IdempotentRepository.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-support",
+    "version": "4.5.0-SNAPSHOT",
+    "properties": { "dropOldestFileStore": { "index": 0, "kind": "property", "displayName": "Drop Oldest File Store", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.FileIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Sets the number of oldest entries to drop from the file store when the maximum capacity is hit to reduce disk space to allow room for new entries." }, "f [...]
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedBodyAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedBodyAggregationStrategy.json
new file mode 100644
index 00000000000..10edccd31e1
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedBodyAggregationStrategy.json
@@ -0,0 +1,15 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "GroupedBodyAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "Grouped Body Aggregation Strategy",
+    "description": "Aggregate body of input Message into a single combined Exchange holding all the aggregated bodies in a List of type Object as the message body. This aggregation strategy can be used in combination with Splitter to batch messages.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT"
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedExchangeAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedExchangeAggregationStrategy.json
new file mode 100644
index 00000000000..7ba11aca0c4
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedExchangeAggregationStrategy.json
@@ -0,0 +1,15 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "GroupedExchangeAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "Grouped Exchange Aggregation Strategy",
+    "description": "Aggregate all Exchanges into a single combined Exchange holding all the aggregated exchanges in a List of Exchange as the message body. This aggregation strategy can be used in combination with Splitter to batch messages.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT"
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedMessageAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedMessageAggregationStrategy.json
new file mode 100644
index 00000000000..a03cad939d9
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/GroupedMessageAggregationStrategy.json
@@ -0,0 +1,15 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "GroupedMessageAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.GroupedMessageAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "Grouped Message Aggregation Strategy",
+    "description": "Aggregate all Message into a single combined Exchange holding all the aggregated messages in a List of Message as the message body. This aggregation strategy can be used in combination with Splitter to batch messages.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT"
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryAggregationRepository.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryAggregationRepository.json
new file mode 100644
index 00000000000..4e2092ec9fc
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryAggregationRepository.json
@@ -0,0 +1,16 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "MemoryAggregationRepository",
+    "javaType": "org.apache.camel.processor.aggregate.MemoryAggregationRepository",
+    "interfaceType": "org.apache.camel.spi.OptimisticLockingAggregationRepository",
+    "title": "Memory Aggregation Repository",
+    "description": "A memory based AggregationRepository which stores Exchange in memory only.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT",
+    "options": { "optimisticLocking": { "index": 0, "kind": "property", "displayName": "Optimistic Locking", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "description": "Whether to use optimistic locking" } }
+  }
+}
+
diff --git a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryIdempotentRepository.json
similarity index 56%
copy from core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json
copy to catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryIdempotentRepository.json
index 4c152136b51..a70bbdcdf2e 100644
--- a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/MemoryIdempotentRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-support",
     "version": "4.5.0-SNAPSHOT",
-    "options": { "cacheSize": { "index": 0, "kind": "property", "displayName": "Cache Size", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Maximum elements that can be stored in-memory" } }
+    "properties": { "cacheSize": { "index": 0, "kind": "property", "displayName": "Cache Size", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Maximum elements that can be stored in-memory" } }
   }
 }
 
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/StringAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/StringAggregationStrategy.json
new file mode 100644
index 00000000000..1702da816d7
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/StringAggregationStrategy.json
@@ -0,0 +1,16 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "StringAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.StringAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "String Aggregation Strategy",
+    "description": "Aggregate result of pick expression into a single combined Exchange holding all the aggregated bodies in a String as the message body. This aggregation strategy can used in combination with Splitter to batch messages",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT",
+    "options": { "delimiter": { "index": 0, "kind": "property", "displayName": "Delimiter", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Delimiter used for joining strings together." } }
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseLatestAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseLatestAggregationStrategy.json
new file mode 100644
index 00000000000..5d73c66d791
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseLatestAggregationStrategy.json
@@ -0,0 +1,15 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "UseLatestAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.UseLatestAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "Use Latest Aggregation Strategy",
+    "description": "An AggregationStrategy which just uses the latest exchange which is useful for status messages where old status messages have no real value. Another example is things like market data prices, where old stock prices are not that relevant, only the current price is.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT"
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseOriginalAggregationStrategy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseOriginalAggregationStrategy.json
new file mode 100644
index 00000000000..7ab066f5d79
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/UseOriginalAggregationStrategy.json
@@ -0,0 +1,15 @@
+{
+  "bean": {
+    "kind": "bean",
+    "name": "UseOriginalAggregationStrategy",
+    "javaType": "org.apache.camel.processor.aggregate.UseOriginalAggregationStrategy",
+    "interfaceType": "org.apache.camel.AggregationStrategy",
+    "title": "Use Original Aggregation Strategy",
+    "description": "An AggregationStrategy which just uses the original exchange which can be needed when you want to preserve the original Exchange. For example when splitting an Exchange and then you may want to keep routing using the original Exchange.",
+    "deprecated": false,
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-core-processor",
+    "version": "4.5.0-SNAPSHOT"
+  }
+}
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain-embeddings.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain-embeddings.json
index a064e3985a3..00a08f7f076 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain-embeddings.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain-embeddings.json
@@ -3,7 +3,7 @@
     "kind": "component",
     "name": "langchain-embeddings",
     "title": "Langchain4j Embeddings",
-    "description": "Langchain4j Embeddings",
+    "description": "Perform operations on the Qdrant Vector Database.",
     "deprecated": false,
     "firstVersion": "4.5.0",
     "label": "ai",
@@ -11,7 +11,7 @@
     "supportLevel": "Preview",
     "groupId": "org.apache.camel",
     "artifactId": "camel-langchain-embeddings",
-    "version": "4.5.0-SNAPSHOT",
+    "version": "4.4.0-SNAPSHOT",
     "scheme": "langchain-embeddings",
     "extendsScheme": "",
     "syntax": "langchain-embeddings:embeddingId",
diff --git a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/DefaultHeaderFilterStrategy.json b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/DefaultHeaderFilterStrategy.json
index 8d359b034cd..bfe3e06376a 100644
--- a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/DefaultHeaderFilterStrategy.json
+++ b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/DefaultHeaderFilterStrategy.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-support",
     "version": "4.5.0-SNAPSHOT",
-    "options": { "allowNullValues": { "index": 0, "kind": "property", "displayName": "Allow Null Values", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.support.DefaultHeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Whether to allow null values. By default a header is skipped if its value is null. Setting this to true will preserve the header." }, "caseInsensitive": { "index [...]
+    "properties": { "allowNullValues": { "index": 0, "kind": "property", "displayName": "Allow Null Values", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.support.DefaultHeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Whether to allow null values. By default a header is skipped if its value is null. Setting this to true will preserve the header." }, "caseInsensitive": { "in [...]
   }
 }
 
diff --git a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/FileIdempotentRepository.json b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/FileIdempotentRepository.json
index e40fb4b2bee..ca6dbee7ea3 100644
--- a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/FileIdempotentRepository.json
+++ b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/FileIdempotentRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-support",
     "version": "4.5.0-SNAPSHOT",
-    "options": { "dropOldestFileStore": { "index": 0, "kind": "property", "displayName": "Drop Oldest File Store", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.FileIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Sets the number of oldest entries to drop from the file store when the maximum capacity is hit to reduce disk space to allow room for new entries." }, "file [...]
+    "properties": { "dropOldestFileStore": { "index": 0, "kind": "property", "displayName": "Drop Oldest File Store", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.FileIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Sets the number of oldest entries to drop from the file store when the maximum capacity is hit to reduce disk space to allow room for new entries." }, "f [...]
   }
 }
 
diff --git a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json
index 4c152136b51..a70bbdcdf2e 100644
--- a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json
+++ b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/bean/MemoryIdempotentRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-support",
     "version": "4.5.0-SNAPSHOT",
-    "options": { "cacheSize": { "index": 0, "kind": "property", "displayName": "Cache Size", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Maximum elements that can be stored in-memory" } }
+    "properties": { "cacheSize": { "index": 0, "kind": "property", "displayName": "Cache Size", "required": false, "type": "object", "javaType": "org.apache.camel.support.processor.idempotent.MemoryIdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Maximum elements that can be stored in-memory" } }
   }
 }
 
diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
index 2cda577d491..8b5302d5011 100644
--- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
+++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
@@ -71,6 +71,8 @@ public final class JsonMapper {
             return generateOtherModel(obj);
         } else if (obj.containsKey("model")) {
             return generateEipModel(obj);
+        } else if (obj.containsKey("bean")) {
+            return generatePojoBeanModel(obj);
         } else {
             return null;
         }
@@ -315,6 +317,27 @@ public final class JsonMapper {
         return model;
     }
 
+    public static PojoBeanModel generatePojoBeanModel(String json) {
+        JsonObject obj = deserialize(json);
+        return generatePojoBeanModel(obj);
+    }
+
+    public static PojoBeanModel generatePojoBeanModel(JsonObject obj) {
+        JsonObject mobj = (JsonObject) obj.get("bean");
+        PojoBeanModel model = new PojoBeanModel();
+        parseModel(mobj, model);
+        JsonObject mprp = (JsonObject) obj.get("properties");
+        if (mprp != null) {
+            for (Map.Entry<String, Object> entry : mprp.entrySet()) {
+                JsonObject mp = (JsonObject) entry.getValue();
+                PojoBeanModel.PojoBeanOptionModel option = new PojoBeanModel.PojoBeanOptionModel();
+                parseOption(mp, option, entry.getKey());
+                model.addOption(option);
+            }
+        }
+        return model;
+    }
+
     public static String createParameterJsonSchema(EipModel model) {
         JsonObject wrapper = asJsonObject(model);
         return serialize(wrapper);
@@ -336,6 +359,21 @@ public final class JsonMapper {
         return wrapper;
     }
 
+    public static String createParameterJsonSchema(PojoBeanModel model) {
+        JsonObject wrapper = asJsonObject(model);
+        return serialize(wrapper);
+    }
+
+    public static JsonObject asJsonObject(PojoBeanModel model) {
+        JsonObject obj = new JsonObject();
+        baseToJson(model, obj);
+        obj.entrySet().removeIf(e -> e.getValue() == null);
+        JsonObject wrapper = new JsonObject();
+        wrapper.put("model", obj);
+        wrapper.put("properties", asJsonObject(model.getOptions()));
+        return wrapper;
+    }
+
     public static LanguageModel generateLanguageModel(String json) {
         JsonObject obj = deserialize(json);
         return generateLanguageModel(obj);
diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/PojoBeanModel.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/PojoBeanModel.java
new file mode 100644
index 00000000000..fccb953d2f8
--- /dev/null
+++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/PojoBeanModel.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.tooling.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PojoBeanModel extends BaseModel<PojoBeanModel.PojoBeanOptionModel> {
+
+    protected final List<PojoBeanModel.PojoBeanOptionModel> options = new ArrayList<>();
+
+    public PojoBeanModel() {
+    }
+
+    public void addOption(PojoBeanModel.PojoBeanOptionModel option) {
+        options.add(option);
+    }
+
+    @Override
+    public List<PojoBeanOptionModel> getOptions() {
+        return options;
+    }
+
+    @Override
+    public String getKind() {
+        return "bean";
+    }
+
+    public static class PojoBeanOptionModel extends BaseOptionModel {
+
+    }
+}
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GeneratePojoBeanMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GeneratePojoBeanMojo.java
index f9d3e0f6400..a19a72ac9df 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GeneratePojoBeanMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/GeneratePojoBeanMojo.java
@@ -276,7 +276,7 @@ public class GeneratePojoBeanMojo extends AbstractGeneratorMojo {
 
         if (!model.getOptions().isEmpty()) {
             JsonObject options = JsonMapper.asJsonObject(model.getOptions());
-            jo.put("options", options);
+            jo.put("properties", options);
         }
 
         JsonObject root = new JsonObject();
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
index 6809cafa0c9..3a1561a74d0 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
@@ -49,6 +49,7 @@ import org.apache.camel.tooling.model.EipModel;
 import org.apache.camel.tooling.model.JsonMapper;
 import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.tooling.model.OtherModel;
+import org.apache.camel.tooling.model.PojoBeanModel;
 import org.apache.camel.tooling.model.TransformerModel;
 import org.apache.camel.tooling.util.FileUtil;
 import org.apache.camel.tooling.util.PackageHelper;
@@ -119,6 +120,12 @@ public class PrepareCatalogMojo extends AbstractMojo {
     @Parameter(defaultValue = "${project.basedir}/src/generated/resources/org/apache/camel/catalog/transformers")
     protected File transformersOutDir;
 
+    /**
+     * The output directory for pojo beans catalog
+     */
+    @Parameter(defaultValue = "${project.basedir}/src/generated/resources/org/apache/camel/catalog/beans")
+    protected File beansOutDir;
+
     /**
      * The output directory for dev-consoles catalog
      */
@@ -329,7 +336,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
                                 allJsonFiles.add(p);
                             } else if (f.equals("component.properties") || f.equals("dataformat.properties")
                                     || f.equals("language.properties") || f.equals("other.properties")
-                                    || f.equals("transformer.properties")) {
+                                    || f.equals("transformer.properties") || f.equals("bean.properties")) {
                                 allPropertiesFiles.add(p);
                             }
                         });
@@ -381,6 +388,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
             Set<String> dataformats = executeDataFormats();
             Set<String> languages = executeLanguages();
             Set<String> transformers = executeTransformers();
+            Set<String> beans = executeBeans();
             Set<String> consoles = executeDevConsoles();
             Set<String> others = executeOthers();
             executeDocuments(components, dataformats, languages, others);
@@ -771,6 +779,48 @@ public class PrepareCatalogMojo extends AbstractMojo {
         return transformerNames;
     }
 
+    protected Set<String> executeBeans() throws Exception {
+        Path beansOutDir = this.beansOutDir.toPath();
+
+        getLog().info("Copying all Camel pojo bean json descriptors");
+
+        // lets use sorted set/maps
+        Set<Path> jsonFiles;
+        Set<Path> duplicateJsonFiles;
+        Set<Path> beanFiles;
+
+        // find all beans from the components directory
+        beanFiles = allPropertiesFiles.stream().filter(p -> p.endsWith("bean.properties"))
+                .collect(Collectors.toCollection(TreeSet::new));
+        jsonFiles = allJsonFiles.stream().filter(p -> allModels.get(p) instanceof PojoBeanModel)
+                .collect(Collectors.toCollection(TreeSet::new));
+
+        getLog().info("Found " + beanFiles.size() + " bean.properties files");
+        getLog().info("Found " + jsonFiles.size() + " bean json files");
+
+        // make sure to create out dir
+        Files.createDirectories(beansOutDir);
+
+        // Check duplicates
+        duplicateJsonFiles = getDuplicates(jsonFiles);
+
+        // Copy all descriptors
+        Map<Path, Path> newJsons = map(jsonFiles, p -> p, p -> beansOutDir.resolve(p.getFileName()));
+        try (Stream<Path> stream = list(beansOutDir).filter(p -> !newJsons.containsValue(p))) {
+            stream.forEach(this::delete);
+        }
+        newJsons.forEach(this::copy);
+
+        Path all = beansOutDir.resolve("../beans.properties");
+        Set<String> beanNames
+                = jsonFiles.stream().map(PrepareCatalogMojo::asComponentName).collect(Collectors.toCollection(TreeSet::new));
+        FileUtil.updateFile(all, String.join("\n", beanNames) + "\n");
+
+        printBeansReport(jsonFiles, duplicateJsonFiles);
+
+        return beanNames;
+    }
+
     protected Set<String> executeDevConsoles() throws Exception {
         Path consolesOutDir = this.consolesOutDir.toPath();
 
@@ -1273,6 +1323,23 @@ public class PrepareCatalogMojo extends AbstractMojo {
         getLog().info(SEPARATOR);
     }
 
+    private void printBeansReport(
+            Set<Path> json, Set<Path> duplicate) {
+        getLog().info(SEPARATOR);
+        getLog().info("");
+        getLog().info("Camel pojo beans catalog report");
+        getLog().info("");
+        getLog().info("\tPojo beans found: " + json.size());
+        printComponentDebug(json);
+        if (!duplicate.isEmpty()) {
+            getLog().info("");
+            getLog().warn("\tDuplicate pojo beans detected: " + duplicate.size());
+            printComponentWarning(duplicate);
+        }
+        getLog().info("");
+        getLog().info(SEPARATOR);
+    }
+
     private void printConsolesReport(
             Set<Path> json, Set<Path> duplicate) {
         getLog().info(SEPARATOR);