You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2025/09/29 12:23:13 UTC
(camel) branch keycloak-management updated (617999b5685 -> ffd622756de)
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a change to branch keycloak-management
in repository https://gitbox.apache.org/repos/asf/camel.git
discard 617999b5685 CAMEL-22464 - Camel-Keycloak: Create producer for managing operations
new ffd622756de CAMEL-22464 - Camel-Keycloak: Create producer for managing operations
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (617999b5685)
\
N -- N -- N refs/heads/keycloak-management (ffd622756de)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../apache/camel/catalog/components/keycloak.json | 10 +++-----
.../org/apache/camel/catalog/others.properties | 1 -
.../org/apache/camel/catalog/others/keycloak.json | 15 -----------
.../keycloak/KeycloakComponentConfigurer.java | 6 -----
.../keycloak/KeycloakEndpointConfigurer.java | 6 -----
.../keycloak/KeycloakEndpointUriFactory.java | 3 +--
.../apache/camel/component/keycloak/keycloak.json | 10 +++-----
.../services/org/apache/camel/other.properties | 8 ------
.../src/generated/resources/keycloak.json | 15 -----------
.../component/keycloak/KeycloakConfiguration.java | 14 ----------
.../modules/others/examples/json/keycloak.json | 1 -
.../dsl/KeycloakComponentBuilderFactory.java | 18 -------------
.../dsl/KeycloakEndpointBuilderFactory.java | 30 ----------------------
13 files changed, 9 insertions(+), 128 deletions(-)
delete mode 100644 catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/keycloak.json
delete mode 100644 components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/other.properties
delete mode 100644 components/camel-keycloak/src/generated/resources/keycloak.json
delete mode 120000 docs/components/modules/others/examples/json/keycloak.json
(camel) 01/01: CAMEL-22464 - Camel-Keycloak: Create producer for managing operations
Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch keycloak-management
in repository https://gitbox.apache.org/repos/asf/camel.git
commit ffd622756deed5d89a96db6989ebc5c3aefc3a35
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Mon Sep 29 14:03:52 2025 +0200
CAMEL-22464 - Camel-Keycloak: Create producer for managing operations
Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
.../org/apache/camel/catalog/components.properties | 1 +
.../apache/camel/catalog/components/keycloak.json | 65 +++
.../org/apache/camel/catalog/others.properties | 1 -
.../org/apache/camel/catalog/others/keycloak.json | 15 -
.../keycloak/KeycloakComponentConfigurer.java | 114 +++++
.../keycloak/KeycloakEndpointConfigurer.java | 98 +++++
.../keycloak/KeycloakEndpointUriFactory.java | 84 ++++
.../apache/camel/component/keycloak/keycloak.json | 65 +++
.../{other.properties => component.properties} | 2 +-
.../services/org/apache/camel/component/keycloak | 2 +
.../org/apache/camel/configurer/keycloak-component | 2 +
.../org/apache/camel/configurer/keycloak-endpoint | 2 +
.../org/apache/camel/urifactory/keycloak-endpoint | 2 +
.../src/generated/resources/keycloak.json | 15 -
.../{keycloak.adoc => keycloak-component.adoc} | 34 +-
.../component/keycloak/KeycloakComponent.java | 72 ++++
.../component/keycloak/KeycloakConfiguration.java | 178 ++++++++
.../component/keycloak/KeycloakConstants.java | 56 +++
.../camel/component/keycloak/KeycloakEndpoint.java | 121 ++++++
.../component/keycloak/KeycloakOperations.java | 37 ++
.../camel/component/keycloak/KeycloakProducer.java | 452 +++++++++++++++++++
.../component/keycloak/KeycloakComponentTest.java | 102 +++++
.../component/keycloak/KeycloakProducerIT.java | 420 ++++++++++++++++++
.../component/keycloak/KeycloakProducerTest.java | 163 +++++++
.../org/apache/camel/main/components.properties | 1 +
.../modules/ROOT/examples/json/keycloak.json | 1 +
docs/components/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/keycloak-component.adoc | 1 +
.../modules/others/examples/json/keycloak.json | 1 -
docs/components/modules/others/nav.adoc | 1 -
docs/components/modules/others/pages/keycloak.adoc | 1 -
.../component/ComponentsBuilderFactory.java | 13 +
.../dsl/KeycloakComponentBuilderFactory.java | 291 +++++++++++++
.../builder/endpoint/EndpointBuilderFactory.java | 1 +
.../camel/builder/endpoint/EndpointBuilders.java | 1 +
.../builder/endpoint/StaticEndpointBuilders.java | 40 ++
.../dsl/KeycloakEndpointBuilderFactory.java | 479 +++++++++++++++++++++
.../camel-component-known-dependencies.properties | 1 +
38 files changed, 2900 insertions(+), 36 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index fe46527a8bb..8b1b0a6722f 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -193,6 +193,7 @@ jt400
jte
kafka
kamelet
+keycloak
knative
kserve
kubernetes-config-maps
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
new file mode 100644
index 00000000000..f4a615c394d
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
@@ -0,0 +1,65 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "keycloak",
+ "title": "Keycloak",
+ "description": "Manage Keycloak instances via Admin API.",
+ "deprecated": false,
+ "firstVersion": "4.15.0",
+ "label": "security,management",
+ "javaType": "org.apache.camel.component.keycloak.KeycloakComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-keycloak",
+ "version": "4.15.0-SNAPSHOT",
+ "scheme": "keycloak",
+ "extendsScheme": "",
+ "syntax": "keycloak:label",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "clientId": { "index": 0, "kind": "property", "displayName": "Client Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client ID" },
+ "clientSecret": { "index": 1, "kind": "property", "displayName": "Client Secret", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client secret" },
+ "configuration": { "index": 2, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.keycloak.KeycloakConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" },
+ "keycloakClient": { "index": 3, "kind": "property", "displayName": "Keycloak Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "To use an existing configured Keycloak admin client" },
+ "lazyStartProducer": { "index": 4, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+ "operation": { "index": 5, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "autowired [...]
+ "password": { "index": 6, "kind": "property", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak password" },
+ "pojoRequest": { "index": 7, "kind": "property", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "realm": { "index": 8, "kind": "property", "displayName": "Realm", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak realm" },
+ "serverUrl": { "index": 9, "kind": "property", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak server URL" },
+ "username": { "index": 10, "kind": "property", "displayName": "Username", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak username" },
+ "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching [...]
+ },
+ "headers": {
+ "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "deprecationNote": "", " [...]
+ "CamelKeycloakRealmName": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The realm name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#REALM_NAME" },
+ "CamelKeycloakUserId": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user ID", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_ID" },
+ "CamelKeycloakUsername": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The username", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USERNAME" },
+ "CamelKeycloakUserEmail": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user email", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_EMAIL" },
+ "CamelKeycloakUserFirstName": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user first name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_FIRST_NAME" },
+ "CamelKeycloakUserLastName": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user last name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_LAST_NAME" },
+ "CamelKeycloakRoleId": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role ID", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_ID" },
+ "CamelKeycloakRoleName": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_NAME" },
+ "CamelKeycloakRoleDescription": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role description", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_DESCRIPTION" }
+ },
+ "properties": {
+ "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Logical name" },
+ "clientId": { "index": 1, "kind": "parameter", "displayName": "Client Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client ID" },
+ "clientSecret": { "index": 2, "kind": "parameter", "displayName": "Client Secret", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client secret" },
+ "keycloakClient": { "index": 3, "kind": "parameter", "displayName": "Keycloak Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "To use an existing configured Keycloak admin client" },
+ "operation": { "index": 4, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "autowire [...]
+ "password": { "index": 5, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak password" },
+ "pojoRequest": { "index": 6, "kind": "parameter", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "realm": { "index": 7, "kind": "parameter", "displayName": "Realm", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak realm" },
+ "serverUrl": { "index": 8, "kind": "parameter", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak server URL" },
+ "username": { "index": 9, "kind": "parameter", "displayName": "Username", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak username" },
+ "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
index f15734c9e30..39b1e80ca2e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
@@ -20,7 +20,6 @@ java-joor-dsl
jfr
jta
kamelet-main
-keycloak
langchain4j-tokenizer
leveldb
lra
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/keycloak.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/keycloak.json
deleted file mode 100644
index 7b005ac888f..00000000000
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/keycloak.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "other": {
- "kind": "other",
- "name": "keycloak",
- "title": "Keycloak",
- "description": "Security using Keycloak",
- "deprecated": false,
- "firstVersion": "4.15.0",
- "label": "security",
- "supportLevel": "Preview",
- "groupId": "org.apache.camel",
- "artifactId": "camel-keycloak",
- "version": "4.15.0-SNAPSHOT"
- }
-}
diff --git a/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakComponentConfigurer.java b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakComponentConfigurer.java
new file mode 100644
index 00000000000..e2cb8e22370
--- /dev/null
+++ b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakComponentConfigurer.java
@@ -0,0 +1,114 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.keycloak;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class KeycloakComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ private org.apache.camel.component.keycloak.KeycloakConfiguration getOrCreateConfiguration(KeycloakComponent target) {
+ if (target.getConfiguration() == null) {
+ target.setConfiguration(new org.apache.camel.component.keycloak.KeycloakConfiguration());
+ }
+ return target.getConfiguration();
+ }
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ KeycloakComponent target = (KeycloakComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
+ case "clientid":
+ case "clientId": getOrCreateConfiguration(target).setClientId(property(camelContext, java.lang.String.class, value)); return true;
+ case "clientsecret":
+ case "clientSecret": getOrCreateConfiguration(target).setClientSecret(property(camelContext, java.lang.String.class, value)); return true;
+ case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.keycloak.KeycloakConfiguration.class, value)); return true;
+ case "keycloakclient":
+ case "keycloakClient": getOrCreateConfiguration(target).setKeycloakClient(property(camelContext, org.keycloak.admin.client.Keycloak.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "operation": getOrCreateConfiguration(target).setOperation(property(camelContext, org.apache.camel.component.keycloak.KeycloakOperations.class, value)); return true;
+ case "password": getOrCreateConfiguration(target).setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "pojorequest":
+ case "pojoRequest": getOrCreateConfiguration(target).setPojoRequest(property(camelContext, boolean.class, value)); return true;
+ case "realm": getOrCreateConfiguration(target).setRealm(property(camelContext, java.lang.String.class, value)); return true;
+ case "serverurl":
+ case "serverUrl": getOrCreateConfiguration(target).setServerUrl(property(camelContext, java.lang.String.class, value)); return true;
+ case "username": getOrCreateConfiguration(target).setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public String[] getAutowiredNames() {
+ return new String[]{"keycloakClient"};
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "clientid":
+ case "clientId": return java.lang.String.class;
+ case "clientsecret":
+ case "clientSecret": return java.lang.String.class;
+ case "configuration": return org.apache.camel.component.keycloak.KeycloakConfiguration.class;
+ case "keycloakclient":
+ case "keycloakClient": return org.keycloak.admin.client.Keycloak.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "operation": return org.apache.camel.component.keycloak.KeycloakOperations.class;
+ case "password": return java.lang.String.class;
+ case "pojorequest":
+ case "pojoRequest": return boolean.class;
+ case "realm": return java.lang.String.class;
+ case "serverurl":
+ case "serverUrl": return java.lang.String.class;
+ case "username": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ KeycloakComponent target = (KeycloakComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "clientid":
+ case "clientId": return getOrCreateConfiguration(target).getClientId();
+ case "clientsecret":
+ case "clientSecret": return getOrCreateConfiguration(target).getClientSecret();
+ case "configuration": return target.getConfiguration();
+ case "keycloakclient":
+ case "keycloakClient": return getOrCreateConfiguration(target).getKeycloakClient();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "operation": return getOrCreateConfiguration(target).getOperation();
+ case "password": return getOrCreateConfiguration(target).getPassword();
+ case "pojorequest":
+ case "pojoRequest": return getOrCreateConfiguration(target).isPojoRequest();
+ case "realm": return getOrCreateConfiguration(target).getRealm();
+ case "serverurl":
+ case "serverUrl": return getOrCreateConfiguration(target).getServerUrl();
+ case "username": return getOrCreateConfiguration(target).getUsername();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointConfigurer.java b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointConfigurer.java
new file mode 100644
index 00000000000..1f967af67e1
--- /dev/null
+++ b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointConfigurer.java
@@ -0,0 +1,98 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.keycloak;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class KeycloakEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ KeycloakEndpoint target = (KeycloakEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "clientid":
+ case "clientId": target.getConfiguration().setClientId(property(camelContext, java.lang.String.class, value)); return true;
+ case "clientsecret":
+ case "clientSecret": target.getConfiguration().setClientSecret(property(camelContext, java.lang.String.class, value)); return true;
+ case "keycloakclient":
+ case "keycloakClient": target.getConfiguration().setKeycloakClient(property(camelContext, org.keycloak.admin.client.Keycloak.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "operation": target.getConfiguration().setOperation(property(camelContext, org.apache.camel.component.keycloak.KeycloakOperations.class, value)); return true;
+ case "password": target.getConfiguration().setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "pojorequest":
+ case "pojoRequest": target.getConfiguration().setPojoRequest(property(camelContext, boolean.class, value)); return true;
+ case "realm": target.getConfiguration().setRealm(property(camelContext, java.lang.String.class, value)); return true;
+ case "serverurl":
+ case "serverUrl": target.getConfiguration().setServerUrl(property(camelContext, java.lang.String.class, value)); return true;
+ case "username": target.getConfiguration().setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public String[] getAutowiredNames() {
+ return new String[]{"keycloakClient"};
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "clientid":
+ case "clientId": return java.lang.String.class;
+ case "clientsecret":
+ case "clientSecret": return java.lang.String.class;
+ case "keycloakclient":
+ case "keycloakClient": return org.keycloak.admin.client.Keycloak.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "operation": return org.apache.camel.component.keycloak.KeycloakOperations.class;
+ case "password": return java.lang.String.class;
+ case "pojorequest":
+ case "pojoRequest": return boolean.class;
+ case "realm": return java.lang.String.class;
+ case "serverurl":
+ case "serverUrl": return java.lang.String.class;
+ case "username": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ KeycloakEndpoint target = (KeycloakEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "clientid":
+ case "clientId": return target.getConfiguration().getClientId();
+ case "clientsecret":
+ case "clientSecret": return target.getConfiguration().getClientSecret();
+ case "keycloakclient":
+ case "keycloakClient": return target.getConfiguration().getKeycloakClient();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "operation": return target.getConfiguration().getOperation();
+ case "password": return target.getConfiguration().getPassword();
+ case "pojorequest":
+ case "pojoRequest": return target.getConfiguration().isPojoRequest();
+ case "realm": return target.getConfiguration().getRealm();
+ case "serverurl":
+ case "serverUrl": return target.getConfiguration().getServerUrl();
+ case "username": return target.getConfiguration().getUsername();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointUriFactory.java b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointUriFactory.java
new file mode 100644
index 00000000000..f58ca9bed69
--- /dev/null
+++ b/components/camel-keycloak/src/generated/java/org/apache/camel/component/keycloak/KeycloakEndpointUriFactory.java
@@ -0,0 +1,84 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.keycloak;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class KeycloakEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
+
+ private static final String BASE = ":label";
+
+ private static final Set<String> PROPERTY_NAMES;
+ private static final Set<String> SECRET_PROPERTY_NAMES;
+ private static final Set<String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(11);
+ props.add("clientId");
+ props.add("clientSecret");
+ props.add("keycloakClient");
+ props.add("label");
+ props.add("lazyStartProducer");
+ props.add("operation");
+ props.add("password");
+ props.add("pojoRequest");
+ props.add("realm");
+ props.add("serverUrl");
+ props.add("username");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ Set<String> secretProps = new HashSet<>(3);
+ secretProps.add("clientSecret");
+ secretProps.add("password");
+ secretProps.add("username");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
+ MULTI_VALUE_PREFIXES = Collections.emptySet();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "keycloak".equals(scheme);
+ }
+
+ @Override
+ public String buildUri(String scheme, Map<String, Object> properties, boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map<String, Object> copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "label", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set<String> propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
new file mode 100644
index 00000000000..f4a615c394d
--- /dev/null
+++ b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
@@ -0,0 +1,65 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "keycloak",
+ "title": "Keycloak",
+ "description": "Manage Keycloak instances via Admin API.",
+ "deprecated": false,
+ "firstVersion": "4.15.0",
+ "label": "security,management",
+ "javaType": "org.apache.camel.component.keycloak.KeycloakComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-keycloak",
+ "version": "4.15.0-SNAPSHOT",
+ "scheme": "keycloak",
+ "extendsScheme": "",
+ "syntax": "keycloak:label",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "clientId": { "index": 0, "kind": "property", "displayName": "Client Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client ID" },
+ "clientSecret": { "index": 1, "kind": "property", "displayName": "Client Secret", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client secret" },
+ "configuration": { "index": 2, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.keycloak.KeycloakConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" },
+ "keycloakClient": { "index": 3, "kind": "property", "displayName": "Keycloak Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "To use an existing configured Keycloak admin client" },
+ "lazyStartProducer": { "index": 4, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+ "operation": { "index": 5, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "autowired [...]
+ "password": { "index": 6, "kind": "property", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak password" },
+ "pojoRequest": { "index": 7, "kind": "property", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "realm": { "index": 8, "kind": "property", "displayName": "Realm", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak realm" },
+ "serverUrl": { "index": 9, "kind": "property", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak server URL" },
+ "username": { "index": 10, "kind": "property", "displayName": "Username", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak username" },
+ "autowiredEnabled": { "index": 11, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching [...]
+ },
+ "headers": {
+ "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "deprecationNote": "", " [...]
+ "CamelKeycloakRealmName": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The realm name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#REALM_NAME" },
+ "CamelKeycloakUserId": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user ID", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_ID" },
+ "CamelKeycloakUsername": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The username", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USERNAME" },
+ "CamelKeycloakUserEmail": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user email", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_EMAIL" },
+ "CamelKeycloakUserFirstName": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user first name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_FIRST_NAME" },
+ "CamelKeycloakUserLastName": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The user last name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#USER_LAST_NAME" },
+ "CamelKeycloakRoleId": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role ID", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_ID" },
+ "CamelKeycloakRoleName": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role name", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_NAME" },
+ "CamelKeycloakRoleDescription": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The role description", "constantName": "org.apache.camel.component.keycloak.KeycloakConstants#ROLE_DESCRIPTION" }
+ },
+ "properties": {
+ "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Logical name" },
+ "clientId": { "index": 1, "kind": "parameter", "displayName": "Client Id", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client ID" },
+ "clientSecret": { "index": 2, "kind": "parameter", "displayName": "Client Secret", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak client secret" },
+ "keycloakClient": { "index": 3, "kind": "parameter", "displayName": "Keycloak Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "To use an existing configured Keycloak admin client" },
+ "operation": { "index": 4, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [ "createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser", "deleteUser", "getUser", "updateUser", "listUsers", "createRole", "deleteRole", "getRole", "updateRole", "listRoles", "assignRoleToUser", "removeRoleFromUser" ], "deprecated": false, "autowire [...]
+ "password": { "index": 5, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak password" },
+ "pojoRequest": { "index": 6, "kind": "parameter", "displayName": "Pojo Request", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "If we want to use a POJO request as body or not" },
+ "realm": { "index": 7, "kind": "parameter", "displayName": "Realm", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak realm" },
+ "serverUrl": { "index": 8, "kind": "parameter", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak server URL" },
+ "username": { "index": 9, "kind": "parameter", "displayName": "Username", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.keycloak.KeycloakConfiguration", "configurationField": "configuration", "description": "Keycloak username" },
+ "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ }
+}
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component.properties
similarity index 91%
rename from components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/other.properties
rename to components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component.properties
index 6ddae4aa374..3360748bb2d 100644
--- a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/other.properties
+++ b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -1,5 +1,5 @@
# Generated by camel build tools - do NOT edit this file!
-name=keycloak
+components=keycloak
groupId=org.apache.camel
artifactId=camel-keycloak
version=4.15.0-SNAPSHOT
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component/keycloak b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component/keycloak
new file mode 100644
index 00000000000..4054b46ec7f
--- /dev/null
+++ b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/component/keycloak
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.keycloak.KeycloakComponent
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-component b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-component
new file mode 100644
index 00000000000..71f2b9bf190
--- /dev/null
+++ b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.keycloak.KeycloakComponentConfigurer
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-endpoint b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-endpoint
new file mode 100644
index 00000000000..7ad532e3fd5
--- /dev/null
+++ b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/configurer/keycloak-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.keycloak.KeycloakEndpointConfigurer
diff --git a/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/urifactory/keycloak-endpoint b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/urifactory/keycloak-endpoint
new file mode 100644
index 00000000000..706a43a4488
--- /dev/null
+++ b/components/camel-keycloak/src/generated/resources/META-INF/services/org/apache/camel/urifactory/keycloak-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.keycloak.KeycloakEndpointUriFactory
diff --git a/components/camel-keycloak/src/generated/resources/keycloak.json b/components/camel-keycloak/src/generated/resources/keycloak.json
deleted file mode 100644
index 7b005ac888f..00000000000
--- a/components/camel-keycloak/src/generated/resources/keycloak.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "other": {
- "kind": "other",
- "name": "keycloak",
- "title": "Keycloak",
- "description": "Security using Keycloak",
- "deprecated": false,
- "firstVersion": "4.15.0",
- "label": "security",
- "supportLevel": "Preview",
- "groupId": "org.apache.camel",
- "artifactId": "camel-keycloak",
- "version": "4.15.0-SNAPSHOT"
- }
-}
diff --git a/components/camel-keycloak/src/main/docs/keycloak.adoc b/components/camel-keycloak/src/main/docs/keycloak-component.adoc
similarity index 97%
rename from components/camel-keycloak/src/main/docs/keycloak.adoc
rename to components/camel-keycloak/src/main/docs/keycloak-component.adoc
index d0342c3a1f5..f02fcd690a8 100644
--- a/components/camel-keycloak/src/main/docs/keycloak.adoc
+++ b/components/camel-keycloak/src/main/docs/keycloak-component.adoc
@@ -2,13 +2,45 @@
:doctitle: Keycloak
:shortname: keycloak
:artifactid: camel-keycloak
-:description: Security using Keycloak
+:description: Manage Keycloak instances via Admin API.
:since: 4.15
:supportlevel: Preview
:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:camel-spring-boot-name: keycloak
*Since Camel {since}*
+*{component-header}*
+
+The Keycloak component supports running operations on Keycloak instance and policy enforcements.
+
+
+== URI Format
+
+-------------------------
+keycloak://label[?options]
+-------------------------
+
+You can append query options to the URI in the following format:
+
+`?options=value&option2=value&...`
+
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
+
The Keycloak security policy provides route-level authorization using Keycloak authentication and authorization services.
== Features
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakComponent.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakComponent.java
new file mode 100644
index 00000000000..2b53e64f29f
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakComponent.java
@@ -0,0 +1,72 @@
+/*
+ * 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.component.keycloak;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+
+/**
+ * For working with Keycloak Admin API.
+ */
+@Component("keycloak")
+public class KeycloakComponent extends DefaultComponent {
+
+ @Metadata
+ private KeycloakConfiguration configuration = new KeycloakConfiguration();
+
+ public KeycloakComponent() {
+ this(null);
+ }
+
+ public KeycloakComponent(CamelContext context) {
+ super(context);
+ }
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+ KeycloakConfiguration configuration
+ = this.configuration != null ? this.configuration.copy() : new KeycloakConfiguration();
+ configuration.setLabel(remaining);
+ KeycloakEndpoint endpoint = new KeycloakEndpoint(uri, this, configuration);
+ setProperties(endpoint, parameters);
+
+ if (configuration.getKeycloakClient() == null
+ && (configuration.getServerUrl() == null
+ || (configuration.getUsername() == null && configuration.getClientId() == null))) {
+ throw new IllegalArgumentException(
+ "Keycloak client or serverUrl with authentication credentials (username/password or clientId/clientSecret) must be specified");
+ }
+
+ return endpoint;
+ }
+
+ public KeycloakConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Component configuration
+ */
+ public void setConfiguration(KeycloakConfiguration configuration) {
+ this.configuration = configuration;
+ }
+}
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConfiguration.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConfiguration.java
new file mode 100644
index 00000000000..a22188859ae
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConfiguration.java
@@ -0,0 +1,178 @@
+/*
+ * 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.component.keycloak;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+import org.keycloak.admin.client.Keycloak;
+
+@UriParams
+public class KeycloakConfiguration implements Cloneable {
+
+ @UriPath(description = "Logical name")
+ @Metadata(required = true)
+ private String label;
+
+ @UriParam
+ @Metadata(autowired = true)
+ private Keycloak keycloakClient;
+
+ @UriParam(description = "Keycloak server URL")
+ private String serverUrl;
+
+ @UriParam(description = "Keycloak realm")
+ private String realm = "master";
+
+ @UriParam(description = "Keycloak client ID")
+ private String clientId;
+
+ @UriParam(description = "Keycloak client secret", secret = true)
+ private String clientSecret;
+
+ @UriParam(description = "Keycloak username", secret = true)
+ private String username;
+
+ @UriParam(description = "Keycloak password", secret = true)
+ private String password;
+
+ @UriParam(description = "The operation to perform")
+ private KeycloakOperations operation;
+
+ @UriParam(description = "If we want to use a POJO request as body or not")
+ private boolean pojoRequest;
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public Keycloak getKeycloakClient() {
+ return keycloakClient;
+ }
+
+ /**
+ * To use an existing configured Keycloak admin client
+ */
+ public void setKeycloakClient(Keycloak keycloakClient) {
+ this.keycloakClient = keycloakClient;
+ }
+
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ /**
+ * Keycloak server URL (e.g., http://localhost:8080/auth)
+ */
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ /**
+ * Keycloak realm name (default: master)
+ */
+ public void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ /**
+ * Keycloak client ID for authentication
+ */
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ /**
+ * Keycloak client secret for authentication
+ */
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * Keycloak username for authentication
+ */
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Keycloak password for authentication
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public KeycloakOperations getOperation() {
+ return operation;
+ }
+
+ /**
+ * The operation to perform.
+ *
+ * You can configure a default operation on the component level, or the operation as part of the endpoint, or via a
+ * message header with the key CamelKeycloakOperation.
+ */
+ public void setOperation(KeycloakOperations operation) {
+ this.operation = operation;
+ }
+
+ public boolean isPojoRequest() {
+ return pojoRequest;
+ }
+
+ /**
+ * If we want to use a POJO request as body or not
+ */
+ public void setPojoRequest(boolean pojoRequest) {
+ this.pojoRequest = pojoRequest;
+ }
+
+ public KeycloakConfiguration copy() {
+ try {
+ return (KeycloakConfiguration) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeCamelException(e);
+ }
+ }
+}
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
new file mode 100644
index 00000000000..212de4720ae
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
@@ -0,0 +1,56 @@
+/*
+ * 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.component.keycloak;
+
+import org.apache.camel.spi.Metadata;
+
+public final class KeycloakConstants {
+
+ @Metadata(description = "The operation to perform", javaType = "org.apache.camel.component.keycloak.KeycloakOperations")
+ public static final String OPERATION = "CamelKeycloakOperation";
+
+ @Metadata(description = "The realm name", javaType = "String")
+ public static final String REALM_NAME = "CamelKeycloakRealmName";
+
+ @Metadata(description = "The user ID", javaType = "String")
+ public static final String USER_ID = "CamelKeycloakUserId";
+
+ @Metadata(description = "The username", javaType = "String")
+ public static final String USERNAME = "CamelKeycloakUsername";
+
+ @Metadata(description = "The user email", javaType = "String")
+ public static final String USER_EMAIL = "CamelKeycloakUserEmail";
+
+ @Metadata(description = "The user first name", javaType = "String")
+ public static final String USER_FIRST_NAME = "CamelKeycloakUserFirstName";
+
+ @Metadata(description = "The user last name", javaType = "String")
+ public static final String USER_LAST_NAME = "CamelKeycloakUserLastName";
+
+ @Metadata(description = "The role ID", javaType = "String")
+ public static final String ROLE_ID = "CamelKeycloakRoleId";
+
+ @Metadata(description = "The role name", javaType = "String")
+ public static final String ROLE_NAME = "CamelKeycloakRoleName";
+
+ @Metadata(description = "The role description", javaType = "String")
+ public static final String ROLE_DESCRIPTION = "CamelKeycloakRoleDescription";
+
+ private KeycloakConstants() {
+ // Utility class
+ }
+}
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
new file mode 100644
index 00000000000..b6ed3e3955b
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
@@ -0,0 +1,121 @@
+/*
+ * 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.component.keycloak;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.EndpointServiceLocation;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.support.DefaultEndpoint;
+import org.apache.camel.util.ObjectHelper;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.KeycloakBuilder;
+
+/**
+ * Manage Keycloak instances via Admin API.
+ */
+@UriEndpoint(firstVersion = "4.15.0", scheme = "keycloak", title = "Keycloak",
+ syntax = "keycloak:label", producerOnly = true, category = { Category.SECURITY, Category.MANAGEMENT },
+ headersClass = KeycloakConstants.class)
+public class KeycloakEndpoint extends DefaultEndpoint implements EndpointServiceLocation {
+
+ private Keycloak keycloakClient;
+
+ @UriParam
+ private KeycloakConfiguration configuration;
+
+ public KeycloakEndpoint(String uri, Component component, KeycloakConfiguration configuration) {
+ super(uri, component);
+ this.configuration = configuration;
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ throw new UnsupportedOperationException("You cannot receive messages from this endpoint");
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ return new KeycloakProducer(this);
+ }
+
+ @Override
+ public KeycloakComponent getComponent() {
+ return (KeycloakComponent) super.getComponent();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ if (configuration.getKeycloakClient() != null) {
+ keycloakClient = configuration.getKeycloakClient();
+ } else {
+ keycloakClient = createKeycloakClient();
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (ObjectHelper.isEmpty(configuration.getKeycloakClient()) && keycloakClient != null) {
+ keycloakClient.close();
+ }
+ super.doStop();
+ }
+
+ public KeycloakConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public Keycloak getKeycloakClient() {
+ return keycloakClient;
+ }
+
+ private Keycloak createKeycloakClient() {
+ KeycloakBuilder builder = KeycloakBuilder.builder()
+ .serverUrl(configuration.getServerUrl())
+ .realm(configuration.getRealm());
+
+ if (configuration.getUsername() != null && configuration.getPassword() != null) {
+ builder.username(configuration.getUsername())
+ .password(configuration.getPassword())
+ .clientId("admin-cli");
+ } else if (configuration.getClientId() != null && configuration.getClientSecret() != null) {
+ builder.clientId(configuration.getClientId())
+ .clientSecret(configuration.getClientSecret())
+ .grantType("client_credentials");
+ } else {
+ throw new IllegalArgumentException("Either username/password or clientId/clientSecret must be provided");
+ }
+
+ return builder.build();
+ }
+
+ @Override
+ public String getServiceUrl() {
+ return configuration.getServerUrl();
+ }
+
+ @Override
+ public String getServiceProtocol() {
+ return "keycloak";
+ }
+}
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
new file mode 100644
index 00000000000..d4f3677cc5b
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
@@ -0,0 +1,37 @@
+/*
+ * 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.component.keycloak;
+
+public enum KeycloakOperations {
+
+ createRealm,
+ deleteRealm,
+ getRealm,
+ updateRealm,
+ createUser,
+ deleteUser,
+ getUser,
+ updateUser,
+ listUsers,
+ createRole,
+ deleteRole,
+ getRole,
+ updateRole,
+ listRoles,
+ assignRoleToUser,
+ removeRoleFromUser
+}
diff --git a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
new file mode 100644
index 00000000000..2339cd2e3ca
--- /dev/null
+++ b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
@@ -0,0 +1,452 @@
+/*
+ * 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.component.keycloak;
+
+import java.util.List;
+
+import jakarta.ws.rs.core.Response;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Producer which sends messages to Keycloak Admin API
+ */
+public class KeycloakProducer extends DefaultProducer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(KeycloakProducer.class);
+ public static final String MISSING_REALM_NAME = "Realm name must be specified";
+ public static final String MISSING_USER_NAME = "Username must be specified";
+ public static final String MISSING_ROLE_NAME = "Role name must be specified";
+ public static final String MISSING_USER_ID = "User ID must be specified";
+ public static final String MISSING_ROLE_ID = "Role ID must be specified";
+
+ private transient String keycloakProducerToString;
+
+ public KeycloakProducer(Endpoint endpoint) {
+ super(endpoint);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ KeycloakOperations operation = determineOperation(exchange);
+ if (operation == null) {
+ throw new IllegalArgumentException("Operation must be provided");
+ }
+
+ switch (operation) {
+ case createRealm:
+ createRealm(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case deleteRealm:
+ deleteRealm(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case getRealm:
+ getRealm(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case updateRealm:
+ updateRealm(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case createUser:
+ createUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case deleteUser:
+ deleteUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case getUser:
+ getUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case updateUser:
+ updateUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case listUsers:
+ listUsers(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case createRole:
+ createRole(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case deleteRole:
+ deleteRole(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case getRole:
+ getRole(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case updateRole:
+ updateRole(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case listRoles:
+ listRoles(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case assignRoleToUser:
+ assignRoleToUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case removeRoleFromUser:
+ removeRoleFromUser(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported operation: " + operation);
+ }
+ }
+
+ private KeycloakOperations determineOperation(Exchange exchange) {
+ KeycloakOperations operation = exchange.getIn().getHeader(KeycloakConstants.OPERATION, KeycloakOperations.class);
+ if (operation == null) {
+ operation = getConfiguration().getOperation();
+ }
+ return operation;
+ }
+
+ protected KeycloakConfiguration getConfiguration() {
+ return getEndpoint().getConfiguration();
+ }
+
+ @Override
+ public String toString() {
+ if (keycloakProducerToString == null) {
+ keycloakProducerToString = "KeycloakProducer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]";
+ }
+ return keycloakProducerToString;
+ }
+
+ @Override
+ public KeycloakEndpoint getEndpoint() {
+ return (KeycloakEndpoint) super.getEndpoint();
+ }
+
+ private void createRealm(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof RealmRepresentation) {
+ keycloakClient.realms().create((RealmRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Realm created successfully");
+ }
+ } else {
+ RealmRepresentation realm = new RealmRepresentation();
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.REALM_NAME))) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ realm.setRealm(realmName);
+ realm.setEnabled(true);
+ } else {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+ keycloakClient.realms().create(realm);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Realm created successfully");
+ }
+ }
+
+ private void deleteRealm(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ keycloakClient.realm(realmName).remove();
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Realm deleted successfully");
+ }
+
+ private void getRealm(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ RealmRepresentation realm = keycloakClient.realm(realmName).toRepresentation();
+ Message message = getMessageForResponse(exchange);
+ message.setBody(realm);
+ }
+
+ private void updateRealm(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof RealmRepresentation) {
+ keycloakClient.realm(realmName).update((RealmRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Realm updated successfully");
+ }
+ } else {
+ throw new IllegalArgumentException("Update realm requires POJO request with RealmRepresentation");
+ }
+ }
+
+ private void createUser(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof UserRepresentation) {
+ Response response = keycloakClient.realm(realmName).users().create((UserRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody(response);
+ }
+ } else {
+ UserRepresentation user = new UserRepresentation();
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.USERNAME))) {
+ String username = exchange.getIn().getHeader(KeycloakConstants.USERNAME, String.class);
+ user.setUsername(username);
+ user.setEnabled(true);
+
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.USER_EMAIL))) {
+ user.setEmail(exchange.getIn().getHeader(KeycloakConstants.USER_EMAIL, String.class));
+ }
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.USER_FIRST_NAME))) {
+ user.setFirstName(exchange.getIn().getHeader(KeycloakConstants.USER_FIRST_NAME, String.class));
+ }
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.USER_LAST_NAME))) {
+ user.setLastName(exchange.getIn().getHeader(KeycloakConstants.USER_LAST_NAME, String.class));
+ }
+ } else {
+ throw new IllegalArgumentException(MISSING_USER_NAME);
+ }
+ Response response = keycloakClient.realm(realmName).users().create(user);
+ Message message = getMessageForResponse(exchange);
+ message.setBody(response);
+ }
+ }
+
+ private void deleteUser(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String userId = exchange.getIn().getHeader(KeycloakConstants.USER_ID, String.class);
+ if (ObjectHelper.isEmpty(userId)) {
+ throw new IllegalArgumentException(MISSING_USER_ID);
+ }
+
+ Response response = keycloakClient.realm(realmName).users().delete(userId);
+ Message message = getMessageForResponse(exchange);
+ message.setBody(response);
+ }
+
+ private void getUser(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String userId = exchange.getIn().getHeader(KeycloakConstants.USER_ID, String.class);
+ if (ObjectHelper.isEmpty(userId)) {
+ throw new IllegalArgumentException(MISSING_USER_ID);
+ }
+
+ UserRepresentation user = keycloakClient.realm(realmName).users().get(userId).toRepresentation();
+ Message message = getMessageForResponse(exchange);
+ message.setBody(user);
+ }
+
+ private void updateUser(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String userId = exchange.getIn().getHeader(KeycloakConstants.USER_ID, String.class);
+ if (ObjectHelper.isEmpty(userId)) {
+ throw new IllegalArgumentException(MISSING_USER_ID);
+ }
+
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof UserRepresentation) {
+ keycloakClient.realm(realmName).users().get(userId).update((UserRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("User updated successfully");
+ }
+ } else {
+ throw new IllegalArgumentException("Update user requires POJO request with UserRepresentation");
+ }
+ }
+
+ private void listUsers(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ List<UserRepresentation> users = keycloakClient.realm(realmName).users().list();
+ Message message = getMessageForResponse(exchange);
+ message.setBody(users);
+ }
+
+ private void createRole(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof RoleRepresentation) {
+ keycloakClient.realm(realmName).roles().create((RoleRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role created successfully");
+ }
+ } else {
+ RoleRepresentation role = new RoleRepresentation();
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME))) {
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ role.setName(roleName);
+
+ if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.ROLE_DESCRIPTION))) {
+ role.setDescription(exchange.getIn().getHeader(KeycloakConstants.ROLE_DESCRIPTION, String.class));
+ }
+ } else {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+ keycloakClient.realm(realmName).roles().create(role);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role created successfully");
+ }
+ }
+
+ private void deleteRole(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ if (ObjectHelper.isEmpty(roleName)) {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+
+ keycloakClient.realm(realmName).roles().deleteRole(roleName);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role deleted successfully");
+ }
+
+ private void getRole(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ if (ObjectHelper.isEmpty(roleName)) {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+
+ RoleRepresentation role = keycloakClient.realm(realmName).roles().get(roleName).toRepresentation();
+ Message message = getMessageForResponse(exchange);
+ message.setBody(role);
+ }
+
+ private void updateRole(Keycloak keycloakClient, Exchange exchange) throws InvalidPayloadException {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ if (ObjectHelper.isEmpty(roleName)) {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+
+ if (getConfiguration().isPojoRequest()) {
+ Object payload = exchange.getIn().getMandatoryBody();
+ if (payload instanceof RoleRepresentation) {
+ keycloakClient.realm(realmName).roles().get(roleName).update((RoleRepresentation) payload);
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role updated successfully");
+ }
+ } else {
+ throw new IllegalArgumentException("Update role requires POJO request with RoleRepresentation");
+ }
+ }
+
+ private void listRoles(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ List<RoleRepresentation> roles = keycloakClient.realm(realmName).roles().list();
+ Message message = getMessageForResponse(exchange);
+ message.setBody(roles);
+ }
+
+ private void assignRoleToUser(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String userId = exchange.getIn().getHeader(KeycloakConstants.USER_ID, String.class);
+ if (ObjectHelper.isEmpty(userId)) {
+ throw new IllegalArgumentException(MISSING_USER_ID);
+ }
+
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ if (ObjectHelper.isEmpty(roleName)) {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+
+ RoleRepresentation role = keycloakClient.realm(realmName).roles().get(roleName).toRepresentation();
+ keycloakClient.realm(realmName).users().get(userId).roles().realmLevel().add(List.of(role));
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role assigned to user successfully");
+ }
+
+ private void removeRoleFromUser(Keycloak keycloakClient, Exchange exchange) {
+ String realmName = exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String userId = exchange.getIn().getHeader(KeycloakConstants.USER_ID, String.class);
+ if (ObjectHelper.isEmpty(userId)) {
+ throw new IllegalArgumentException(MISSING_USER_ID);
+ }
+
+ String roleName = exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME, String.class);
+ if (ObjectHelper.isEmpty(roleName)) {
+ throw new IllegalArgumentException(MISSING_ROLE_NAME);
+ }
+
+ RoleRepresentation role = keycloakClient.realm(realmName).roles().get(roleName).toRepresentation();
+ keycloakClient.realm(realmName).users().get(userId).roles().realmLevel().remove(List.of(role));
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Role removed from user successfully");
+ }
+
+ public static Message getMessageForResponse(final Exchange exchange) {
+ return exchange.getMessage();
+ }
+}
diff --git a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakComponentTest.java b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakComponentTest.java
new file mode 100644
index 00000000000..636a8133cf0
--- /dev/null
+++ b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakComponentTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.component.keycloak;
+
+import org.apache.camel.ResolveEndpointFailedException;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class KeycloakComponentTest extends CamelTestSupport {
+
+ @Test
+ public void testCreateEndpointWithKeycloakClient() throws Exception {
+ Keycloak keycloakClient = Mockito.mock(Keycloak.class);
+
+ context.getRegistry().bind("keycloakClient", keycloakClient);
+
+ KeycloakEndpoint endpoint = (KeycloakEndpoint) context.getEndpoint("keycloak:test?keycloakClient=#keycloakClient");
+
+ assertNotNull(endpoint);
+ assertEquals("test", endpoint.getConfiguration().getLabel());
+ assertSame(keycloakClient, endpoint.getConfiguration().getKeycloakClient());
+ }
+
+ @Test
+ public void testCreateEndpointWithCredentials() throws Exception {
+ KeycloakEndpoint endpoint = (KeycloakEndpoint) context.getEndpoint(
+ "keycloak:test?serverUrl=http://localhost:8080&username=admin&password=admin&realm=master");
+
+ assertNotNull(endpoint);
+ assertEquals("test", endpoint.getConfiguration().getLabel());
+ assertEquals("http://localhost:8080", endpoint.getConfiguration().getServerUrl());
+ assertEquals("admin", endpoint.getConfiguration().getUsername());
+ assertEquals("admin", endpoint.getConfiguration().getPassword());
+ assertEquals("master", endpoint.getConfiguration().getRealm());
+ }
+
+ @Test
+ public void testCreateEndpointWithClientCredentials() throws Exception {
+ KeycloakEndpoint endpoint = (KeycloakEndpoint) context.getEndpoint(
+ "keycloak:test?serverUrl=http://localhost:8080&clientId=admin-cli&clientSecret=secret&realm=master");
+
+ assertNotNull(endpoint);
+ assertEquals("test", endpoint.getConfiguration().getLabel());
+ assertEquals("http://localhost:8080", endpoint.getConfiguration().getServerUrl());
+ assertEquals("admin-cli", endpoint.getConfiguration().getClientId());
+ assertEquals("secret", endpoint.getConfiguration().getClientSecret());
+ assertEquals("master", endpoint.getConfiguration().getRealm());
+ }
+
+ @Test
+ public void testCreateEndpointWithOperation() throws Exception {
+ Keycloak keycloakClient = Mockito.mock(Keycloak.class);
+
+ context.getRegistry().bind("keycloakClient", keycloakClient);
+
+ KeycloakEndpoint endpoint = (KeycloakEndpoint) context.getEndpoint(
+ "keycloak:test?keycloakClient=#keycloakClient&operation=createUser");
+
+ assertNotNull(endpoint);
+ assertEquals(KeycloakOperations.createUser, endpoint.getConfiguration().getOperation());
+ }
+
+ @Test
+ public void testCreateEndpointMissingCredentials() {
+ assertThrows(ResolveEndpointFailedException.class, () -> {
+ context.getEndpoint("keycloak:test?serverUrl=http://localhost:8080");
+ });
+ }
+
+ @Test
+ public void testProducerOnlyEndpoint() throws Exception {
+ Keycloak keycloakClient = Mockito.mock(Keycloak.class);
+
+ context.getRegistry().bind("keycloakClient", keycloakClient);
+
+ KeycloakEndpoint endpoint = (KeycloakEndpoint) context.getEndpoint("keycloak:test?keycloakClient=#keycloakClient");
+
+ assertNotNull(endpoint.createProducer());
+
+ assertThrows(UnsupportedOperationException.class, () -> {
+ endpoint.createConsumer(null);
+ });
+ }
+}
diff --git a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerIT.java b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerIT.java
new file mode 100644
index 00000000000..596b6fa44d4
--- /dev/null
+++ b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerIT.java
@@ -0,0 +1,420 @@
+/*
+ * 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.component.keycloak;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import jakarta.ws.rs.core.Response;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Integration test for Keycloak producer operations using external Keycloak instance.
+ *
+ * Must be manually tested. Provide your own Keycloak instance and configuration using:
+ * -Dkeycloak.server.url=http://localhost:8080 -Dkeycloak.realm=master -Dkeycloak.username=admin
+ * -Dkeycloak.password=admin
+ *
+ * This test requires admin privileges to create/delete realms, users, and roles. IMPORTANT: Authentication is always
+ * done against the master realm (where admin user exists) but operations are performed on target realms specified in
+ * message headers.
+ *
+ * Example Docker command to start Keycloak: docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e
+ * KEYCLOAK_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:latest start-dev
+ */
+@EnabledIfSystemProperties({
+ @EnabledIfSystemProperty(named = "keycloak.server.url", matches = ".*",
+ disabledReason = "Keycloak server URL not provided"),
+ @EnabledIfSystemProperty(named = "keycloak.realm", matches = ".*",
+ disabledReason = "Keycloak realm not provided"),
+ @EnabledIfSystemProperty(named = "keycloak.username", matches = ".*",
+ disabledReason = "Keycloak username not provided"),
+ @EnabledIfSystemProperty(named = "keycloak.password", matches = ".*",
+ disabledReason = "Keycloak password not provided")
+})
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class KeycloakProducerIT extends CamelTestSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(KeycloakProducerIT.class);
+
+ private static String keycloakUrl;
+ private static String realm;
+ private static String username;
+ private static String password;
+
+ // Test data - use unique names to avoid conflicts
+ private static final String TEST_REALM_NAME = "test-realm-" + UUID.randomUUID().toString().substring(0, 8);
+ private static final String TEST_USER_NAME = "test-user-" + UUID.randomUUID().toString().substring(0, 8);
+ private static final String TEST_ROLE_NAME = "test-role-" + UUID.randomUUID().toString().substring(0, 8);
+
+ static {
+ // Load configuration from system properties
+ keycloakUrl = System.getProperty("keycloak.server.url");
+ realm = System.getProperty("keycloak.realm");
+ username = System.getProperty("keycloak.username");
+ password = System.getProperty("keycloak.password");
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // For admin operations, always authenticate against master realm
+ // but operations will be performed on the target realm specified in headers
+ String keycloakEndpoint = String.format(
+ "keycloak:admin?serverUrl=%s&realm=master&username=%s&password=%s",
+ keycloakUrl, username, password);
+
+ // Realm operations
+ from("direct:createRealm")
+ .to(keycloakEndpoint + "&operation=createRealm");
+
+ from("direct:getRealm")
+ .to(keycloakEndpoint + "&operation=getRealm");
+
+ from("direct:deleteRealm")
+ .to(keycloakEndpoint + "&operation=deleteRealm");
+
+ // User operations
+ from("direct:createUser")
+ .to(keycloakEndpoint + "&operation=createUser");
+
+ from("direct:getUser")
+ .to(keycloakEndpoint + "&operation=getUser");
+
+ from("direct:listUsers")
+ .to(keycloakEndpoint + "&operation=listUsers");
+
+ from("direct:deleteUser")
+ .to(keycloakEndpoint + "&operation=deleteUser");
+
+ // Role operations
+ from("direct:createRole")
+ .to(keycloakEndpoint + "&operation=createRole");
+
+ from("direct:getRole")
+ .to(keycloakEndpoint + "&operation=getRole");
+
+ from("direct:listRoles")
+ .to(keycloakEndpoint + "&operation=listRoles");
+
+ from("direct:deleteRole")
+ .to(keycloakEndpoint + "&operation=deleteRole");
+
+ // User-Role operations
+ from("direct:assignRoleToUser")
+ .to(keycloakEndpoint + "&operation=assignRoleToUser");
+
+ from("direct:removeRoleFromUser")
+ .to(keycloakEndpoint + "&operation=removeRoleFromUser");
+
+ // POJO-based operations
+ from("direct:createRealmPojo")
+ .to(keycloakEndpoint + "&operation=createRealm&pojoRequest=true");
+
+ from("direct:createUserPojo")
+ .to(keycloakEndpoint + "&operation=createUser&pojoRequest=true");
+
+ from("direct:createRolePojo")
+ .to(keycloakEndpoint + "&operation=createRole&pojoRequest=true");
+ }
+ };
+ }
+
+ @Test
+ @Order(1)
+ void testKeycloakProducerConfiguration() {
+ // Verify that the configuration is properly set up
+ assertNotNull(keycloakUrl);
+ assertNotNull(realm);
+ assertNotNull(username);
+ assertNotNull(password);
+ assertTrue(keycloakUrl.startsWith("http://") || keycloakUrl.startsWith("https://"));
+ log.info("Testing Keycloak at: {} with realm: {}", keycloakUrl, realm);
+ }
+
+ @Test
+ @Order(2)
+ void testCreateRealmWithHeaders() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:createRealm", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ String body = result.getIn().getBody(String.class);
+ assertEquals("Realm created successfully", body);
+
+ log.info("Created realm: {}", TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(4)
+ void testGetRealm() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:getRealm", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ RealmRepresentation realmRep = result.getIn().getBody(RealmRepresentation.class);
+ assertNotNull(realmRep);
+ assertEquals(TEST_REALM_NAME, realmRep.getRealm());
+ assertTrue(realmRep.isEnabled());
+
+ log.info("Retrieved realm: {} - enabled: {}", realmRep.getRealm(), realmRep.isEnabled());
+ }
+
+ @Test
+ @Order(5)
+ void testCreateUserWithHeaders() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.USERNAME, TEST_USER_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.USER_EMAIL, TEST_USER_NAME + "@test.com");
+ exchange.getIn().setHeader(KeycloakConstants.USER_FIRST_NAME, "Test");
+ exchange.getIn().setHeader(KeycloakConstants.USER_LAST_NAME, "User");
+
+ Exchange result = template.send("direct:createUser", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ // The result should be a Response object
+ Object body = result.getIn().getBody();
+ assertNotNull(body);
+ assertTrue(body instanceof Response);
+
+ log.info("Created user: {} in realm: {}", TEST_USER_NAME, TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(6)
+ void testCreateUserWithPojo() {
+ String pojoUserName = TEST_USER_NAME + "-pojo";
+
+ UserRepresentation user = new UserRepresentation();
+ user.setUsername(pojoUserName);
+ user.setEmail(pojoUserName + "@test.com");
+ user.setFirstName("Test");
+ user.setLastName("User POJO");
+ user.setEnabled(true);
+
+ Exchange exchange = createExchangeWithBody(user);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:createUserPojo", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ Object body = result.getIn().getBody();
+ assertNotNull(body);
+ assertTrue(body instanceof Response);
+
+ log.info("Created user via POJO: {} in realm: {}", pojoUserName, TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(7)
+ void testListUsers() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:listUsers", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ @SuppressWarnings("unchecked")
+ List<UserRepresentation> users = result.getIn().getBody(List.class);
+ assertNotNull(users);
+ assertTrue(users.size() >= 2); // At least our two test users
+
+ log.info("Found {} users in realm: {}", users.size(), TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(8)
+ void testCreateRoleWithHeaders() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_NAME, TEST_ROLE_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_DESCRIPTION, "Test role for integration testing");
+
+ Exchange result = template.send("direct:createRole", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ String body = result.getIn().getBody(String.class);
+ assertEquals("Role created successfully", body);
+
+ log.info("Created role: {} in realm: {}", TEST_ROLE_NAME, TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(9)
+ void testCreateRoleWithPojo() {
+ String pojoRoleName = TEST_ROLE_NAME + "-pojo";
+
+ RoleRepresentation role = new RoleRepresentation();
+ role.setName(pojoRoleName);
+ role.setDescription("Test role created via POJO");
+
+ Exchange exchange = createExchangeWithBody(role);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:createRolePojo", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ String body = result.getIn().getBody(String.class);
+ assertEquals("Role created successfully", body);
+
+ log.info("Created role via POJO: {} in realm: {}", pojoRoleName, TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(10)
+ void testGetRole() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_NAME, TEST_ROLE_NAME);
+
+ Exchange result = template.send("direct:getRole", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ RoleRepresentation roleRep = result.getIn().getBody(RoleRepresentation.class);
+ assertNotNull(roleRep);
+ assertEquals(TEST_ROLE_NAME, roleRep.getName());
+ assertEquals("Test role for integration testing", roleRep.getDescription());
+
+ log.info("Retrieved role: {} - description: {}", roleRep.getName(), roleRep.getDescription());
+ }
+
+ @Test
+ @Order(11)
+ void testListRoles() {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:listRoles", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ @SuppressWarnings("unchecked")
+ List<RoleRepresentation> roles = result.getIn().getBody(List.class);
+ assertNotNull(roles);
+ assertTrue(roles.size() >= 2); // At least our test roles + default roles
+
+ log.info("Found {} roles in realm: {}", roles.size(), TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(12)
+ void testErrorHandling() {
+ // Test with missing realm name
+ CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
+ template.sendBody("direct:createUser", null);
+ });
+ assertTrue(ex.getCause().getMessage().contains("Realm name must be specified"));
+
+ // Test with non-existent realm
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, "non-existent-realm");
+ exchange.getIn().setHeader(KeycloakConstants.USERNAME, "testuser");
+
+ log.info("Error handling tests completed successfully");
+ }
+
+ @Test
+ @Order(98)
+ void testCleanupRoles() {
+ // Delete test roles
+ String[] rolesToDelete = { TEST_ROLE_NAME, TEST_ROLE_NAME + "-pojo" };
+
+ for (String roleName : rolesToDelete) {
+ try {
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_NAME, roleName);
+
+ Exchange result = template.send("direct:deleteRole", exchange);
+ if (result.getException() == null) {
+ String body = result.getIn().getBody(String.class);
+ assertEquals("Role deleted successfully", body);
+ log.info("Deleted role: {}", roleName);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to delete role {}: {}", roleName, e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ @Order(99)
+ void testCleanupRealm() {
+ // Delete the test realm (this will also delete all users and roles in it)
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ Exchange result = template.send("direct:deleteRealm", exchange);
+ assertNotNull(result);
+ assertNull(result.getException());
+
+ String body = result.getIn().getBody(String.class);
+ assertEquals("Realm deleted successfully", body);
+
+ log.info("Deleted test realm: {}", TEST_REALM_NAME);
+ }
+
+ @Test
+ @Order(100)
+ void testVerifyRealmDeleted() {
+ CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
+ // Verify that the realm was actually deleted
+ Map<String, Object> headers = new HashMap<>();
+ headers.put(KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+ template.requestBodyAndHeaders("direct:getRealm", null, headers);
+ });
+
+ assertNotNull(ex.getCause());
+
+ log.info("Verified that test realm was deleted");
+ }
+}
diff --git a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
new file mode 100644
index 00000000000..b3cfe793707
--- /dev/null
+++ b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.component.keycloak;
+
+import java.util.List;
+
+import jakarta.ws.rs.core.Response;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.RealmsResource;
+import org.keycloak.admin.client.resource.RolesResource;
+import org.keycloak.admin.client.resource.UsersResource;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+public class KeycloakProducerTest extends CamelTestSupport {
+
+ @BindToRegistry("keycloakClient")
+ private Keycloak keycloakClient = Mockito.mock(Keycloak.class);
+
+ private RealmsResource realmsResource = Mockito.mock(RealmsResource.class);
+ private RealmResource realmResource = Mockito.mock(RealmResource.class);
+ private UsersResource usersResource = Mockito.mock(UsersResource.class);
+ private RolesResource rolesResource = Mockito.mock(RolesResource.class);
+ private Response response = Mockito.mock(Response.class);
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:createRealm")
+ .to("keycloak:test?keycloakClient=#keycloakClient&operation=createRealm")
+ .to("mock:result");
+
+ from("direct:createUser")
+ .to("keycloak:test?keycloakClient=#keycloakClient&operation=createUser")
+ .to("mock:result");
+
+ from("direct:createRole")
+ .to("keycloak:test?keycloakClient=#keycloakClient&operation=createRole")
+ .to("mock:result");
+
+ from("direct:listUsers")
+ .to("keycloak:test?keycloakClient=#keycloakClient&operation=listUsers")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ public void testCreateRealm() throws Exception {
+ when(keycloakClient.realms()).thenReturn(realmsResource);
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:createRealm", null, KeycloakConstants.REALM_NAME, "testRealm");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testCreateUser() throws Exception {
+ when(keycloakClient.realm(anyString())).thenReturn(realmResource);
+ when(realmResource.users()).thenReturn(usersResource);
+ when(usersResource.create(any(UserRepresentation.class))).thenReturn(response);
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+ exchange.getIn().setHeader(KeycloakConstants.USERNAME, "testUser");
+ exchange.getIn().setHeader(KeycloakConstants.USER_EMAIL, "test@example.com");
+
+ template.send("direct:createUser", exchange);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testCreateRole() throws Exception {
+ when(keycloakClient.realm(anyString())).thenReturn(realmResource);
+ when(realmResource.roles()).thenReturn(rolesResource);
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ Exchange exchange = createExchangeWithBody(null);
+ exchange.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_NAME, "testRole");
+ exchange.getIn().setHeader(KeycloakConstants.ROLE_DESCRIPTION, "Test Role Description");
+
+ template.send("direct:createRole", exchange);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testListUsers() throws Exception {
+ when(keycloakClient.realm(anyString())).thenReturn(realmResource);
+ when(realmResource.users()).thenReturn(usersResource);
+ when(usersResource.list()).thenReturn(List.of(new UserRepresentation()));
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ template.sendBodyAndHeader("direct:listUsers", null, KeycloakConstants.REALM_NAME, "testRealm");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testMissingRealmName() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(0);
+
+ try {
+ template.sendBody("direct:createRealm", null);
+ } catch (Exception e) {
+ assertTrue(e.getCause().getMessage().contains("Realm name must be specified"));
+ }
+ }
+
+ @Test
+ public void testMissingUserName() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(0);
+
+ try {
+ template.sendBodyAndHeader("direct:createUser", null, KeycloakConstants.REALM_NAME, "testRealm");
+ } catch (Exception e) {
+ assertTrue(e.getCause().getMessage().contains("Username must be specified"));
+ }
+ }
+}
diff --git a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
index fe46527a8bb..8b1b0a6722f 100644
--- a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
+++ b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
@@ -193,6 +193,7 @@ jt400
jte
kafka
kamelet
+keycloak
knative
kserve
kubernetes-config-maps
diff --git a/docs/components/modules/ROOT/examples/json/keycloak.json b/docs/components/modules/ROOT/examples/json/keycloak.json
new file mode 120000
index 00000000000..61e3297e600
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/keycloak.json
@@ -0,0 +1 @@
+../../../../../../components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc
index 52b088b28c7..f8911943a52 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -212,6 +212,7 @@
** xref:jte-component.adoc[JTE]
** xref:kafka-component.adoc[Kafka]
** xref:kamelet-component.adoc[Kamelet]
+** xref:keycloak-component.adoc[Keycloak]
** xref:knative-component.adoc[Knative]
** xref:knative-http-component.adoc[Knative Http]
** xref:kubernetes-summary.adoc[Kubernetes]
diff --git a/docs/components/modules/ROOT/pages/keycloak-component.adoc b/docs/components/modules/ROOT/pages/keycloak-component.adoc
new file mode 120000
index 00000000000..afa435d7452
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/keycloak-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-keycloak/src/main/docs/keycloak-component.adoc
\ No newline at end of file
diff --git a/docs/components/modules/others/examples/json/keycloak.json b/docs/components/modules/others/examples/json/keycloak.json
deleted file mode 120000
index dd95f7cdef2..00000000000
--- a/docs/components/modules/others/examples/json/keycloak.json
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../components/camel-keycloak/src/generated/resources/keycloak.json
\ No newline at end of file
diff --git a/docs/components/modules/others/nav.adoc b/docs/components/modules/others/nav.adoc
index 958ff9d2f6d..02b181394d9 100644
--- a/docs/components/modules/others/nav.adoc
+++ b/docs/components/modules/others/nav.adoc
@@ -24,7 +24,6 @@
** xref:jasypt.adoc[Jasypt]
** xref:jfr.adoc[JFR]
** xref:jta.adoc[JTA]
-** xref:keycloak.adoc[Keycloak]
** xref:leveldb.adoc[LevelDB]
** xref:lra.adoc[LRA]
** xref:mail-microsoft-oauth.adoc[Mail Microsoft Oauth]
diff --git a/docs/components/modules/others/pages/keycloak.adoc b/docs/components/modules/others/pages/keycloak.adoc
deleted file mode 120000
index 3d6e01bb9cf..00000000000
--- a/docs/components/modules/others/pages/keycloak.adoc
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../components/camel-keycloak/src/main/docs/keycloak.adoc
\ No newline at end of file
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index 8446c8845f4..4ad4ab75280 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -2634,6 +2634,19 @@ public interface ComponentsBuilderFactory {
static KameletComponentBuilderFactory.KameletComponentBuilder kamelet() {
return KameletComponentBuilderFactory.kamelet();
}
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * @return the dsl builder
+ */
+ static KeycloakComponentBuilderFactory.KeycloakComponentBuilder keycloak() {
+ return KeycloakComponentBuilderFactory.keycloak();
+ }
/**
* Knative (camel-knative)
* Send and receive events from Knative.
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KeycloakComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KeycloakComponentBuilderFactory.java
new file mode 100644
index 00000000000..303bce02c0f
--- /dev/null
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/KeycloakComponentBuilderFactory.java
@@ -0,0 +1,291 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.builder.component.dsl;
+
+import javax.annotation.processing.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.keycloak.KeycloakComponent;
+
+/**
+ * Manage Keycloak instances via Admin API.
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface KeycloakComponentBuilderFactory {
+
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * @return the dsl builder
+ */
+ static KeycloakComponentBuilder keycloak() {
+ return new KeycloakComponentBuilderImpl();
+ }
+
+ /**
+ * Builder for the Keycloak component.
+ */
+ interface KeycloakComponentBuilder extends ComponentBuilder<KeycloakComponent> {
+
+ /**
+ * Keycloak client ID.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param clientId the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder clientId(java.lang.String clientId) {
+ doSetProperty("clientId", clientId);
+ return this;
+ }
+
+ /**
+ * Keycloak client secret.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param clientSecret the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder clientSecret(java.lang.String clientSecret) {
+ doSetProperty("clientSecret", clientSecret);
+ return this;
+ }
+
+ /**
+ * Component configuration.
+ *
+ * The option is a:
+ * <code>org.apache.camel.component.keycloak.KeycloakConfiguration</code> type.
+ *
+ * Group: producer
+ *
+ * @param configuration the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder configuration(org.apache.camel.component.keycloak.KeycloakConfiguration configuration) {
+ doSetProperty("configuration", configuration);
+ return this;
+ }
+
+ /**
+ * To use an existing configured Keycloak admin client.
+ *
+ * The option is a:
+ * <code>org.keycloak.admin.client.Keycloak</code> type.
+ *
+ * Group: producer
+ *
+ * @param keycloakClient the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder keycloakClient(org.keycloak.admin.client.Keycloak keycloakClient) {
+ doSetProperty("keycloakClient", keycloakClient);
+ return this;
+ }
+
+
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder lazyStartProducer(boolean lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+
+ /**
+ * The operation to perform.
+ *
+ * The option is a:
+ * <code>org.apache.camel.component.keycloak.KeycloakOperations</code> type.
+ *
+ * Group: producer
+ *
+ * @param operation the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder operation(org.apache.camel.component.keycloak.KeycloakOperations operation) {
+ doSetProperty("operation", operation);
+ return this;
+ }
+
+ /**
+ * Keycloak password.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param password the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder password(java.lang.String password) {
+ doSetProperty("password", password);
+ return this;
+ }
+
+
+ /**
+ * If we want to use a POJO request as body or not.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param pojoRequest the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder pojoRequest(boolean pojoRequest) {
+ doSetProperty("pojoRequest", pojoRequest);
+ return this;
+ }
+
+ /**
+ * Keycloak realm.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param realm the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder realm(java.lang.String realm) {
+ doSetProperty("realm", realm);
+ return this;
+ }
+
+ /**
+ * Keycloak server URL.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param serverUrl the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder serverUrl(java.lang.String serverUrl) {
+ doSetProperty("serverUrl", serverUrl);
+ return this;
+ }
+
+ /**
+ * Keycloak username.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param username the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder username(java.lang.String username) {
+ doSetProperty("username", username);
+ return this;
+ }
+
+
+ /**
+ * Whether autowiring is enabled. This is used for automatic autowiring
+ * options (the option must be marked as autowired) by looking up in the
+ * registry to find if there is a single instance of matching type,
+ * which then gets configured on the component. This can be used for
+ * automatic configuring JDBC data sources, JMS connection factories,
+ * AWS Clients, etc.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param autowiredEnabled the value to set
+ * @return the dsl builder
+ */
+ default KeycloakComponentBuilder autowiredEnabled(boolean autowiredEnabled) {
+ doSetProperty("autowiredEnabled", autowiredEnabled);
+ return this;
+ }
+ }
+
+ class KeycloakComponentBuilderImpl
+ extends AbstractComponentBuilder<KeycloakComponent>
+ implements KeycloakComponentBuilder {
+ @Override
+ protected KeycloakComponent buildConcreteComponent() {
+ return new KeycloakComponent();
+ }
+ private org.apache.camel.component.keycloak.KeycloakConfiguration getOrCreateConfiguration(KeycloakComponent component) {
+ if (component.getConfiguration() == null) {
+ component.setConfiguration(new org.apache.camel.component.keycloak.KeycloakConfiguration());
+ }
+ return component.getConfiguration();
+ }
+ @Override
+ protected boolean setPropertyOnComponent(
+ Component component,
+ String name,
+ Object value) {
+ switch (name) {
+ case "clientId": getOrCreateConfiguration((KeycloakComponent) component).setClientId((java.lang.String) value); return true;
+ case "clientSecret": getOrCreateConfiguration((KeycloakComponent) component).setClientSecret((java.lang.String) value); return true;
+ case "configuration": ((KeycloakComponent) component).setConfiguration((org.apache.camel.component.keycloak.KeycloakConfiguration) value); return true;
+ case "keycloakClient": getOrCreateConfiguration((KeycloakComponent) component).setKeycloakClient((org.keycloak.admin.client.Keycloak) value); return true;
+ case "lazyStartProducer": ((KeycloakComponent) component).setLazyStartProducer((boolean) value); return true;
+ case "operation": getOrCreateConfiguration((KeycloakComponent) component).setOperation((org.apache.camel.component.keycloak.KeycloakOperations) value); return true;
+ case "password": getOrCreateConfiguration((KeycloakComponent) component).setPassword((java.lang.String) value); return true;
+ case "pojoRequest": getOrCreateConfiguration((KeycloakComponent) component).setPojoRequest((boolean) value); return true;
+ case "realm": getOrCreateConfiguration((KeycloakComponent) component).setRealm((java.lang.String) value); return true;
+ case "serverUrl": getOrCreateConfiguration((KeycloakComponent) component).setServerUrl((java.lang.String) value); return true;
+ case "username": getOrCreateConfiguration((KeycloakComponent) component).setUsername((java.lang.String) value); return true;
+ case "autowiredEnabled": ((KeycloakComponent) component).setAutowiredEnabled((boolean) value); return true;
+ default: return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index fc9be74a735..6bbf57197bd 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -200,6 +200,7 @@ public interface EndpointBuilderFactory
org.apache.camel.builder.endpoint.dsl.KafkaEndpointBuilderFactory.KafkaBuilders,
org.apache.camel.builder.endpoint.dsl.KameletEndpointBuilderFactory.KameletBuilders,
org.apache.camel.builder.endpoint.dsl.KeyVaultEndpointBuilderFactory.KeyVaultBuilders,
+ org.apache.camel.builder.endpoint.dsl.KeycloakEndpointBuilderFactory.KeycloakBuilders,
org.apache.camel.builder.endpoint.dsl.KeystoneEndpointBuilderFactory.KeystoneBuilders,
org.apache.camel.builder.endpoint.dsl.Kinesis2EndpointBuilderFactory.Kinesis2Builders,
org.apache.camel.builder.endpoint.dsl.KinesisFirehose2EndpointBuilderFactory.KinesisFirehose2Builders,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
index ec9df4c1832..d0d6ed1a9b9 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
@@ -197,6 +197,7 @@ public interface EndpointBuilders
org.apache.camel.builder.endpoint.dsl.KafkaEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.KameletEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.KeyVaultEndpointBuilderFactory,
+ org.apache.camel.builder.endpoint.dsl.KeycloakEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.KeystoneEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.Kinesis2EndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.KinesisFirehose2EndpointBuilderFactory,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index b4e78fab4c7..a77e3434de4 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -8620,6 +8620,46 @@ public class StaticEndpointBuilders {
public static KameletEndpointBuilderFactory.KameletEndpointBuilder kamelet(String componentName, String path) {
return KameletEndpointBuilderFactory.endpointBuilder(componentName, path);
}
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * Syntax: <code>keycloak:label</code>
+ *
+ * Path parameter: label (required)
+ * Logical name
+ *
+ * @param path label
+ * @return the dsl builder
+ */
+ public static KeycloakEndpointBuilderFactory.KeycloakEndpointBuilder keycloak(String path) {
+ return keycloak("keycloak", path);
+ }
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * Syntax: <code>keycloak:label</code>
+ *
+ * Path parameter: label (required)
+ * Logical name
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path label
+ * @return the dsl builder
+ */
+ public static KeycloakEndpointBuilderFactory.KeycloakEndpointBuilder keycloak(String componentName, String path) {
+ return KeycloakEndpointBuilderFactory.endpointBuilder(componentName, path);
+ }
/**
* Knative (camel-knative)
* Send and receive events from Knative.
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
new file mode 100644
index 00000000000..6c8998dd7a8
--- /dev/null
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
@@ -0,0 +1,479 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.builder.endpoint.dsl;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+import javax.annotation.processing.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * Manage Keycloak instances via Admin API.
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface KeycloakEndpointBuilderFactory {
+
+ /**
+ * Builder for endpoint for the Keycloak component.
+ */
+ public interface KeycloakEndpointBuilder
+ extends
+ EndpointProducerBuilder {
+ default AdvancedKeycloakEndpointBuilder advanced() {
+ return (AdvancedKeycloakEndpointBuilder) this;
+ }
+
+ /**
+ * Keycloak client ID.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param clientId the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder clientId(String clientId) {
+ doSetProperty("clientId", clientId);
+ return this;
+ }
+ /**
+ * Keycloak client secret.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param clientSecret the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder clientSecret(String clientSecret) {
+ doSetProperty("clientSecret", clientSecret);
+ return this;
+ }
+ /**
+ * To use an existing configured Keycloak admin client.
+ *
+ * The option is a: <code>org.keycloak.admin.client.Keycloak</code>
+ * type.
+ *
+ * Group: producer
+ *
+ * @param keycloakClient the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder keycloakClient(org.keycloak.admin.client.Keycloak keycloakClient) {
+ doSetProperty("keycloakClient", keycloakClient);
+ return this;
+ }
+ /**
+ * To use an existing configured Keycloak admin client.
+ *
+ * The option will be converted to a
+ * <code>org.keycloak.admin.client.Keycloak</code> type.
+ *
+ * Group: producer
+ *
+ * @param keycloakClient the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder keycloakClient(String keycloakClient) {
+ doSetProperty("keycloakClient", keycloakClient);
+ return this;
+ }
+ /**
+ * The operation to perform.
+ *
+ * The option is a:
+ * <code>org.apache.camel.component.keycloak.KeycloakOperations</code>
+ * type.
+ *
+ * Group: producer
+ *
+ * @param operation the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder operation(org.apache.camel.component.keycloak.KeycloakOperations operation) {
+ doSetProperty("operation", operation);
+ return this;
+ }
+ /**
+ * The operation to perform.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.component.keycloak.KeycloakOperations</code>
+ * type.
+ *
+ * Group: producer
+ *
+ * @param operation the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder operation(String operation) {
+ doSetProperty("operation", operation);
+ return this;
+ }
+ /**
+ * Keycloak password.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param password the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder password(String password) {
+ doSetProperty("password", password);
+ return this;
+ }
+ /**
+ * If we want to use a POJO request as body or not.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param pojoRequest the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder pojoRequest(boolean pojoRequest) {
+ doSetProperty("pojoRequest", pojoRequest);
+ return this;
+ }
+ /**
+ * If we want to use a POJO request as body or not.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param pojoRequest the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder pojoRequest(String pojoRequest) {
+ doSetProperty("pojoRequest", pojoRequest);
+ return this;
+ }
+ /**
+ * Keycloak realm.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param realm the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder realm(String realm) {
+ doSetProperty("realm", realm);
+ return this;
+ }
+ /**
+ * Keycloak server URL.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param serverUrl the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder serverUrl(String serverUrl) {
+ doSetProperty("serverUrl", serverUrl);
+ return this;
+ }
+ /**
+ * Keycloak username.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param username the value to set
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder username(String username) {
+ doSetProperty("username", username);
+ return this;
+ }
+ }
+
+ /**
+ * Advanced builder for endpoint for the Keycloak component.
+ */
+ public interface AdvancedKeycloakEndpointBuilder
+ extends
+ EndpointProducerBuilder {
+ default KeycloakEndpointBuilder basic() {
+ return (KeycloakEndpointBuilder) this;
+ }
+
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer (advanced)
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default AdvancedKeycloakEndpointBuilder lazyStartProducer(boolean lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer (advanced)
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default AdvancedKeycloakEndpointBuilder lazyStartProducer(String lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+ }
+
+ public interface KeycloakBuilders {
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * @return the dsl builder for the headers' name.
+ */
+ default KeycloakHeaderNameBuilder keycloak() {
+ return KeycloakHeaderNameBuilder.INSTANCE;
+ }
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * Syntax: <code>keycloak:label</code>
+ *
+ * Path parameter: label (required)
+ * Logical name
+ *
+ * @param path label
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder keycloak(String path) {
+ return KeycloakEndpointBuilderFactory.endpointBuilder("keycloak", path);
+ }
+ /**
+ * Keycloak (camel-keycloak)
+ * Manage Keycloak instances via Admin API.
+ *
+ * Category: security,management
+ * Since: 4.15
+ * Maven coordinates: org.apache.camel:camel-keycloak
+ *
+ * Syntax: <code>keycloak:label</code>
+ *
+ * Path parameter: label (required)
+ * Logical name
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path label
+ * @return the dsl builder
+ */
+ default KeycloakEndpointBuilder keycloak(String componentName, String path) {
+ return KeycloakEndpointBuilderFactory.endpointBuilder(componentName, path);
+ }
+
+ }
+ /**
+ * The builder of headers' name for the Keycloak component.
+ */
+ public static class KeycloakHeaderNameBuilder {
+ /**
+ * The internal instance of the builder used to access to all the
+ * methods representing the name of headers.
+ */
+ private static final KeycloakHeaderNameBuilder INSTANCE = new KeycloakHeaderNameBuilder();
+
+ /**
+ * The operation to perform.
+ *
+ * The option is a: {@code
+ * org.apache.camel.component.keycloak.KeycloakOperations} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakOperation}.
+ */
+ public String keycloakOperation() {
+ return "CamelKeycloakOperation";
+ }
+ /**
+ * The realm name.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakRealmName}.
+ */
+ public String keycloakRealmName() {
+ return "CamelKeycloakRealmName";
+ }
+ /**
+ * The user ID.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakUserId}.
+ */
+ public String keycloakUserId() {
+ return "CamelKeycloakUserId";
+ }
+ /**
+ * The username.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakUsername}.
+ */
+ public String keycloakUsername() {
+ return "CamelKeycloakUsername";
+ }
+ /**
+ * The user email.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakUserEmail}.
+ */
+ public String keycloakUserEmail() {
+ return "CamelKeycloakUserEmail";
+ }
+ /**
+ * The user first name.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakUserFirstName}.
+ */
+ public String keycloakUserFirstName() {
+ return "CamelKeycloakUserFirstName";
+ }
+ /**
+ * The user last name.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakUserLastName}.
+ */
+ public String keycloakUserLastName() {
+ return "CamelKeycloakUserLastName";
+ }
+ /**
+ * The role ID.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakRoleId}.
+ */
+ public String keycloakRoleId() {
+ return "CamelKeycloakRoleId";
+ }
+ /**
+ * The role name.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakRoleName}.
+ */
+ public String keycloakRoleName() {
+ return "CamelKeycloakRoleName";
+ }
+ /**
+ * The role description.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code KeycloakRoleDescription}.
+ */
+ public String keycloakRoleDescription() {
+ return "CamelKeycloakRoleDescription";
+ }
+ }
+ static KeycloakEndpointBuilder endpointBuilder(String componentName, String path) {
+ class KeycloakEndpointBuilderImpl extends AbstractEndpointBuilder implements KeycloakEndpointBuilder, AdvancedKeycloakEndpointBuilder {
+ public KeycloakEndpointBuilderImpl(String path) {
+ super(componentName, path);
+ }
+ }
+ return new KeycloakEndpointBuilderImpl(path);
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
index bd80f6ccfc1..ba0980c64b5 100644
--- a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
+++ b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
@@ -205,6 +205,7 @@ org.apache.camel.component.jt400.Jt400Component=camel:jt400
org.apache.camel.component.jte.JteComponent=camel:jte
org.apache.camel.component.kafka.KafkaComponent=camel:kafka
org.apache.camel.component.kamelet.KameletComponent=camel:kamelet
+org.apache.camel.component.keycloak.KeycloakComponent=camel:keycloak
org.apache.camel.component.knative.KnativeComponent=camel:knative
org.apache.camel.component.kserve.KServeComponent=camel:kserve
org.apache.camel.component.kubernetes.config_maps.KubernetesConfigMapsComponent=camel:kubernetes