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

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


The following commit(s) were added to refs/heads/main by this push:
     new 79f1b52  Add Camel 4.22 upgrade recipes
79f1b52 is described below

commit 79f1b527a85312aac7f3c3cb78b65f8099916207
Author: Jiří Ondrušek <[email protected]>
AuthorDate: Wed Aug 19 12:06:25 2026 +0000

    Add Camel 4.22 upgrade recipes
    
    Covers:
    - Azure component-specific CredentialType enum consolidation (10 components)
    - AWS SDK apache-client -> apache5-client dependency rename
    - Minio CopySource -> SourceObject type rename (minio 9.0)
    - camel-spring-ai-tools removal migrated to camel-ai-tool, including the
      camel-spring-ai-tools-starter -> camel-ai-tool-starter rename in the
      Spring Boot recipe
    - camel-reactive-executor-tomcat deprecation handled via RemoveDependency
    - OpenAI ChatCompletion package move via ChangeType, testable by staging
      openai-java-core 0.8.1 (pre-move package layout) on the test classpath
    - release notes synced with the current upgrade guide and every topic linked
      to its guide section
    - camel-latest-version set to the released 4.22.0
    - rewrite-recipe-bom bumped to 3.37.0 and rewrite-maven-plugin to 6.46.1
      (aligned with quarkus-updates), with the removed RemoveTraitsUsageRecipes
      reference dropped from the internal best-practices recipe
    
    Minio inner-class type renames excluded - OpenRewrite ChangeType to inner
    classes is not idempotent.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Co-Authored-By: Claude Fable 5 <[email protected]>
---
 camel-spring-boot-upgrade-recipes/pom.xml          |   1 -
 .../src/main/resources/META-INF/rewrite/4.22.yaml  |  38 ++
 .../main/resources/META-INF/rewrite/latest.yaml    |   2 +-
 .../upgrade/springboot/CamelSpringBoot422Test.java |  81 ++++
 camel-upgrade-recipes/pom.xml                      |  28 +-
 .../camel418_3/RenameHeaderInJavaMethod.java       |  10 +-
 .../customRecipes/ChangeComponentUriRecipe.java    |  18 +-
 .../internal/ChangeJavaComponentUriRecipe.java     |  25 +
 .../internal/ChangeXmlComponentUriRecipe.java      |  20 +-
 .../internal/ChangeYamlComponentUriRecipe.java     |  21 +-
 .../src/main/resources/META-INF/rewrite/4.22.yaml  | 195 ++++++++
 .../main/resources/META-INF/rewrite/latest.yaml    |   1 +
 .../org/apache/camel/upgrade/CamelTestUtil.java    |   3 +-
 .../apache/camel/upgrade/CamelUpdate421Test.java   |  74 +--
 .../apache/camel/upgrade/CamelUpdate422Test.java   | 516 +++++++++++++++++++++
 pom.xml                                            |   6 +-
 release_notes.adoc                                 |  57 +++
 rewrite.yml                                        |   1 -
 18 files changed, 1047 insertions(+), 50 deletions(-)

diff --git a/camel-spring-boot-upgrade-recipes/pom.xml 
b/camel-spring-boot-upgrade-recipes/pom.xml
index 3b1767e..dc9a5e0 100644
--- a/camel-spring-boot-upgrade-recipes/pom.xml
+++ b/camel-spring-boot-upgrade-recipes/pom.xml
@@ -76,7 +76,6 @@
             <artifactId>rewrite-maven</artifactId>
             <scope>provided</scope>
         </dependency>
-
         <dependency>
             <groupId>org.openrewrite</groupId>
             <artifactId>rewrite-yaml</artifactId>
diff --git 
a/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml
 
b/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml
new file mode 100644
index 0000000..2e5e17c
--- /dev/null
+++ 
b/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+---
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.CamelSpringBootMigrationRecipe
+displayName: Migrates Camel Spring Boot applications to Camel Spring Boot 4.22
+description: Migrates Camel Spring Boot applications to Camel Spring Boot 4.22.
+recipeList:
+  - org.apache.camel.upgrade.camel421.CamelSpringBootMigrationRecipe
+  - org.apache.camel.upgrade.camel422.CamelMigrationRecipe
+  - org.apache.camel.upgrade.camel422.migrateSpringAiToolsStarterDependency
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-spring-ai-chat
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateSpringAiToolsStarterDependency
+displayName: Migrate camel-spring-ai-tools-starter to camel-ai-tool-starter
+description: Migrates the camel-spring-ai-tools-starter dependency, removed in 
Camel Spring Boot 4.22, to camel-ai-tool-starter. Route URIs using the 
spring-ai-tools scheme must be migrated to ai-tool manually.
+recipeList:
+  - org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId:
+      oldGroupId: org.apache.camel.springboot
+      oldArtifactId: camel-spring-ai-tools-starter
+      newGroupId: org.apache.camel.springboot
+      newArtifactId: camel-ai-tool-starter
+      newVersion: 4.22.0
diff --git 
a/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
 
b/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
index e35f85a..8d35ace 100644
--- 
a/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
+++ 
b/camel-spring-boot-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
@@ -21,7 +21,7 @@ displayName: Migrate to Apache Camel Spring Boot 
@camel-latest-version@
 description: >- 
   Migrate applications to Apache Camel Spring Boot @camel-latest-version@ and 
Spring Boot @spring-boot-version@
 recipeList:
-  - org.apache.camel.upgrade.camel421.CamelSpringBootMigrationRecipe
+  - org.apache.camel.upgrade.camel422.CamelSpringBootMigrationRecipe
   - org.openrewrite.maven.UpgradeDependencyVersion:
       groupId: '*camel*'
       artifactId: 'camel-spring-boot-bom'
diff --git 
a/camel-spring-boot-upgrade-recipes/src/test/java/org/apache/camel/upgrade/springboot/CamelSpringBoot422Test.java
 
b/camel-spring-boot-upgrade-recipes/src/test/java/org/apache/camel/upgrade/springboot/CamelSpringBoot422Test.java
new file mode 100644
index 0000000..24345b1
--- /dev/null
+++ 
b/camel-spring-boot-upgrade-recipes/src/test/java/org/apache/camel/upgrade/springboot/CamelSpringBoot422Test.java
@@ -0,0 +1,81 @@
+/*
+ * 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.upgrade.springboot;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.config.Environment;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.maven.Assertions.pomXml;
+
+class CamelSpringBoot422Test implements RewriteTest {
+
+    @Override
+    public void defaults(RecipeSpec spec) {
+        spec.recipe(Environment.builder()
+                .scanYamlResources()
+                .build()
+                
.activateRecipes("org.apache.camel.upgrade.camel422.CamelSpringBootMigrationRecipe"));
+    }
+
+    @DocumentExample
+    @Test
+    void migrateSpringAiToolsStarterDependency() {
+        //language=xml
+        rewriteRun(
+                pomXml(
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    
<groupId>org.apache.camel.springboot</groupId>
+                                    
<artifactId>camel-spring-ai-tools-starter</artifactId>
+                                    <version>4.21.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """,
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    
<groupId>org.apache.camel.springboot</groupId>
+                                    
<artifactId>camel-ai-tool-starter</artifactId>
+                                    <version>4.22.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """
+                )
+        );
+    }
+
+}
diff --git a/camel-upgrade-recipes/pom.xml b/camel-upgrade-recipes/pom.xml
index a94624d..263b43d 100644
--- a/camel-upgrade-recipes/pom.xml
+++ b/camel-upgrade-recipes/pom.xml
@@ -74,9 +74,11 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <!-- Ships recipe classes (ModuleHasDependency) used by 
preconditions at end-user
+                 runtime; must not be provided-scope, the rewrite plugin does 
not resolve
+                 provided transitives of recipe artifacts -->
             <groupId>org.openrewrite.recipe</groupId>
             <artifactId>rewrite-java-dependencies</artifactId>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.openrewrite</groupId>
@@ -617,6 +619,30 @@
                                     
<outputDirectory>${rewrite-tmp-classpath}</outputDirectory>
                                 </artifactItem>
 
+                                <!-- Azure component JARs for CredentialType 
migration tests (4.22) -->
+                                <artifactItem>
+                                    <groupId>org.apache.camel</groupId>
+                                    
<artifactId>camel-azure-storage-blob</artifactId>
+                                    <version>${camel4.18-version}</version>
+                                    
<outputDirectory>${rewrite-tmp-classpath}</outputDirectory>
+                                </artifactItem>
+
+                                <!-- Minio client for minio type migration 
tests (4.22) -->
+                                <artifactItem>
+                                    <groupId>io.minio</groupId>
+                                    <artifactId>minio</artifactId>
+                                    <version>8.5.7</version>
+                                    
<outputDirectory>${rewrite-tmp-classpath}</outputDirectory>
+                                </artifactItem>
+
+                                <!-- OpenAI SDK with the pre-4.22 package 
layout for ChatCompletion migration tests (4.22) -->
+                                <artifactItem>
+                                    <groupId>com.openai</groupId>
+                                    <artifactId>openai-java-core</artifactId>
+                                    <version>0.8.1</version>
+                                    
<outputDirectory>${rewrite-tmp-classpath}</outputDirectory>
+                                </artifactItem>
+
                             </artifactItems>
                         </configuration>
                     </execution>
diff --git 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethod.java
 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethod.java
index 2dbddf1..6575d32 100644
--- 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethod.java
+++ 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethod.java
@@ -22,6 +22,7 @@ import org.openrewrite.ExecutionContext;
 import org.openrewrite.Option;
 import org.openrewrite.Recipe;
 import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.MethodMatcher;
 import org.openrewrite.java.tree.J;
 
 import java.util.ArrayList;
@@ -82,6 +83,11 @@ public class RenameHeaderInJavaMethod extends Recipe {
         private static final String MATCHER_GET_HEADER_2_ARGS = 
"org.apache.camel.Message getHeader(String, Class)";
         private static final String MATCHER_GET_HEADER_3_ARGS = 
"org.apache.camel.Message getHeader(String, Object, Class)";
         private static final String MATCHER_GET_HEADER_SUPPLIER = 
"org.apache.camel.Message getHeader(String, java.util.function.Supplier, 
Class)";
+        // matchOverrides=true: the DSL methods are invoked on 
ProcessorDefinition subtypes (RouteDefinition, ...)
+        private static final MethodMatcher DSL_SET_HEADER_MATCHER =
+                new MethodMatcher("org.apache.camel.model.ProcessorDefinition 
setHeader(String, ..)", true);
+        private static final MethodMatcher DSL_REMOVE_HEADER_MATCHER =
+                new MethodMatcher("org.apache.camel.model.ProcessorDefinition 
removeHeader(String)", true);
 
         private final String oldHeaderName;
         private final String newHeaderName;
@@ -125,7 +131,9 @@ public class RenameHeaderInJavaMethod extends Recipe {
                    getMethodMatcher(MATCHER_GET_HEADER_1_ARG).matches(mi) ||
                    getMethodMatcher(MATCHER_GET_HEADER_2_ARGS).matches(mi) ||
                    getMethodMatcher(MATCHER_GET_HEADER_3_ARGS).matches(mi) ||
-                   getMethodMatcher(MATCHER_GET_HEADER_SUPPLIER).matches(mi);
+                   getMethodMatcher(MATCHER_GET_HEADER_SUPPLIER).matches(mi) ||
+                   DSL_SET_HEADER_MATCHER.matches(mi) ||
+                   DSL_REMOVE_HEADER_MATCHER.matches(mi);
         }
     }
 }
diff --git 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ChangeComponentUriRecipe.java
 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ChangeComponentUriRecipe.java
index 1ce65df..2d25439 100644
--- 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ChangeComponentUriRecipe.java
+++ 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ChangeComponentUriRecipe.java
@@ -58,6 +58,14 @@ public class ChangeComponentUriRecipe extends Recipe {
     )
     public String replacement;
 
+    @Option(
+        displayName = "Consumer only",
+        description = "When true, only consumer endpoints (from) are 
transformed; producer endpoints (to) are left unchanged.",
+        example = "true",
+        required = false
+    )
+    public Boolean consumerOnly;
+
     public ChangeComponentUriRecipe() {
     }
 
@@ -74,6 +82,10 @@ public class ChangeComponentUriRecipe extends Recipe {
         this.replacement = replacement;
     }
 
+    public void setConsumerOnly(Boolean consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
     @Override
     public String getDisplayName() {
         return "Change Camel component URI across all DSLs";
@@ -90,9 +102,9 @@ public class ChangeComponentUriRecipe extends Recipe {
         List<Recipe> recipes = new ArrayList<>();
 
         // Apply transformation to all three DSL types
-        recipes.add(new ChangeJavaComponentUriRecipe(uriPattern, replacement));
-        recipes.add(new ChangeXmlComponentUriRecipe(uriPattern, replacement));
-        recipes.add(new ChangeYamlComponentUriRecipe(uriPattern, replacement));
+        recipes.add(new ChangeJavaComponentUriRecipe(uriPattern, replacement, 
consumerOnly));
+        recipes.add(new ChangeXmlComponentUriRecipe(uriPattern, replacement, 
consumerOnly));
+        recipes.add(new ChangeYamlComponentUriRecipe(uriPattern, replacement, 
consumerOnly));
 
         return recipes;
     }
diff --git 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeJavaComponentUriRecipe.java
 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeJavaComponentUriRecipe.java
index 62f2ed7..5ca1e84 100644
--- 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeJavaComponentUriRecipe.java
+++ 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeJavaComponentUriRecipe.java
@@ -46,12 +46,25 @@ public class ChangeJavaComponentUriRecipe extends Recipe {
     )
     public String replacement;
 
+    @Option(
+        displayName = "Consumer only",
+        description = "When true, only URIs passed to from(...)/fromF(...) are 
transformed; producer endpoints are left unchanged.",
+        example = "true",
+        required = false
+    )
+    public Boolean consumerOnly;
+
     public ChangeJavaComponentUriRecipe() {
     }
 
     public ChangeJavaComponentUriRecipe(String uriPattern, String replacement) 
{
+        this(uriPattern, replacement, null);
+    }
+
+    public ChangeJavaComponentUriRecipe(String uriPattern, String replacement, 
Boolean consumerOnly) {
         this.uriPattern = uriPattern;
         this.replacement = replacement;
+        this.consumerOnly = consumerOnly;
     }
 
     public void setUriPattern(String uriPattern) {
@@ -62,6 +75,10 @@ public class ChangeJavaComponentUriRecipe extends Recipe {
         this.replacement = replacement;
     }
 
+    public void setConsumerOnly(Boolean consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
     @Override
     public String getDisplayName() {
         return "Change Camel component URI in Java";
@@ -81,6 +98,14 @@ public class ChangeJavaComponentUriRecipe extends Recipe {
             protected J.Literal doVisitLiteral(J.Literal literal, 
ExecutionContext ctx) {
                 J.Literal l = super.doVisitLiteral(literal, ctx);
 
+                if (Boolean.TRUE.equals(consumerOnly)) {
+                    J.MethodInvocation enclosing = 
getCursor().firstEnclosing(J.MethodInvocation.class);
+                    if (enclosing == null
+                            || !("from".equals(enclosing.getSimpleName()) || 
"fromF".equals(enclosing.getSimpleName()))) {
+                        return l;
+                    }
+                }
+
                 if (JavaType.Primitive.String == l.getType() && l.getValue() 
!= null) {
                     String value = (String) l.getValue();
                     return RecipesUtil.transform(value, pattern, replacement)
diff --git 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeXmlComponentUriRecipe.java
 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeXmlComponentUriRecipe.java
index 2717534..88b0ac4 100644
--- 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeXmlComponentUriRecipe.java
+++ 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeXmlComponentUriRecipe.java
@@ -50,12 +50,25 @@ public class ChangeXmlComponentUriRecipe extends Recipe {
     )
     public String replacement;
 
+    @Option(
+        displayName = "Consumer only",
+        description = "When true, only <from> endpoints are transformed; <to> 
endpoints are left unchanged.",
+        example = "true",
+        required = false
+    )
+    public Boolean consumerOnly;
+
     public ChangeXmlComponentUriRecipe() {
     }
 
     public ChangeXmlComponentUriRecipe(String uriPattern, String replacement) {
+        this(uriPattern, replacement, null);
+    }
+
+    public ChangeXmlComponentUriRecipe(String uriPattern, String replacement, 
Boolean consumerOnly) {
         this.uriPattern = uriPattern;
         this.replacement = replacement;
+        this.consumerOnly = consumerOnly;
     }
 
     public void setUriPattern(String uriPattern) {
@@ -66,6 +79,10 @@ public class ChangeXmlComponentUriRecipe extends Recipe {
         this.replacement = replacement;
     }
 
+    public void setConsumerOnly(Boolean consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
     @Override
     public String getDisplayName() {
         return "Change Camel component URI in XML DSL";
@@ -85,7 +102,8 @@ public class ChangeXmlComponentUriRecipe extends Recipe {
             public Xml.Tag doVisitTag(Xml.Tag tag, ExecutionContext ctx) {
                 Xml.Tag t = super.doVisitTag(tag, ctx);
 
-                if (FROM_MATCHER.matches(getCursor()) || 
TO_MATCHER.matches(getCursor())) {
+                if (FROM_MATCHER.matches(getCursor())
+                        || (!Boolean.TRUE.equals(consumerOnly) && 
TO_MATCHER.matches(getCursor()))) {
                     return transformXmlUri(t, pattern, replacement);
                 }
 
diff --git 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeYamlComponentUriRecipe.java
 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeYamlComponentUriRecipe.java
index 04b6750..5e7ab9d 100644
--- 
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeYamlComponentUriRecipe.java
+++ 
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/internal/ChangeYamlComponentUriRecipe.java
@@ -34,6 +34,7 @@ import java.util.regex.Pattern;
 public class ChangeYamlComponentUriRecipe extends Recipe {
 
     private static final JsonPathMatcher YAML_URI_MATCHER = new 
JsonPathMatcher("$..uri");
+    private static final JsonPathMatcher YAML_FROM_URI_MATCHER = new 
JsonPathMatcher("$..from.uri");
 
     @Option(
         displayName = "URI pattern",
@@ -49,12 +50,25 @@ public class ChangeYamlComponentUriRecipe extends Recipe {
     )
     public String replacement;
 
+    @Option(
+        displayName = "Consumer only",
+        description = "When true, only from.uri endpoints are transformed; 
other uri fields are left unchanged.",
+        example = "true",
+        required = false
+    )
+    public Boolean consumerOnly;
+
     public ChangeYamlComponentUriRecipe() {
     }
 
     public ChangeYamlComponentUriRecipe(String uriPattern, String replacement) 
{
+        this(uriPattern, replacement, null);
+    }
+
+    public ChangeYamlComponentUriRecipe(String uriPattern, String replacement, 
Boolean consumerOnly) {
         this.uriPattern = uriPattern;
         this.replacement = replacement;
+        this.consumerOnly = consumerOnly;
     }
 
     public void setUriPattern(String uriPattern) {
@@ -65,6 +79,10 @@ public class ChangeYamlComponentUriRecipe extends Recipe {
         this.replacement = replacement;
     }
 
+    public void setConsumerOnly(Boolean consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
     @Override
     public String getDisplayName() {
         return "Change Camel component URI in YAML DSL";
@@ -90,7 +108,8 @@ public class ChangeYamlComponentUriRecipe extends Recipe {
                 Yaml.Mapping.Entry e = super.doVisitMappingEntry(entry, ctx);
 
                 // Check if this is a uri field
-                if (YAML_URI_MATCHER.matches(getCursor()) && e.getValue() 
instanceof Yaml.Scalar) {
+                JsonPathMatcher uriMatcher = Boolean.TRUE.equals(consumerOnly) 
? YAML_FROM_URI_MATCHER : YAML_URI_MATCHER;
+                if (uriMatcher.matches(getCursor()) && e.getValue() instanceof 
Yaml.Scalar) {
                     Yaml.Scalar scalar = (Yaml.Scalar) e.getValue();
                     return RecipesUtil.transform(scalar.getValue(), pattern, 
replacement)
                             .map(newValue -> 
e.withValue(scalar.withValue(newValue)))
diff --git 
a/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml 
b/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml
new file mode 100644
index 0000000..075e4b2
--- /dev/null
+++ b/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/4.22.yaml
@@ -0,0 +1,195 @@
+#
+# 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.
+#
+
+#####
+# Rules coming from 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html
+#####
+
+#####
+# Update the Camel project from 4.21 to 4.22
+#####
+---
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.CamelMigrationRecipe
+displayName: Migrates `camel 4.21` application to `camel 4.22`
+description: Migrates `camel 4.21` application to `camel 4.22`.
+recipeList:
+  - org.apache.camel.upgrade.camel422.migrateAzureCredentialTypes
+  - org.apache.camel.upgrade.camel422.migrateAwsApacheClient
+  - org.apache.camel.upgrade.camel422.migrateMinioTypes
+  - 
org.apache.camel.upgrade.camel422.removeCamelReactiveExecutorTomcatDependency
+  - org.apache.camel.upgrade.camel422.migrateSpringAiToolsDependency
+  - org.apache.camel.upgrade.camel422.migrateOpenAiChatCompletion
+  - org.apache.camel.upgrade.camel422.migrateLangchain4jToolsUris
+  - org.apache.camel.upgrade.camel422.migrateSpringAiToolsUris
+  - org.apache.camel.upgrade.camel422.migrateAtmosphereWebsocketHeaders
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-azure---component-specific-credentialtype-enums-removed
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateAzureCredentialTypes
+displayName: Migrate Azure component-specific CredentialType enums to common 
enum
+description: Migrates removed component-specific CredentialType enums to the 
shared org.apache.camel.component.azure.common.CredentialType enum.
+recipeList:
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.cosmosdb.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.eventgrid.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.eventhubs.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.file.azure.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.functions.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.key.vault.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.servicebus.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.storage.blob.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.storage.datalake.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: 
org.apache.camel.component.azure.storage.queue.CredentialType
+      newFullyQualifiedTypeName: 
org.apache.camel.component.azure.common.CredentialType
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-aws---migrated-from-apache-client-to-apache5-client
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateAwsApacheClient
+displayName: Migrate AWS SDK apache-client to apache5-client
+description: Migrates software.amazon.awssdk:apache-client to 
software.amazon.awssdk:apache5-client for projects using Camel AWS components. 
Explicit versions are set to 2.46.0, the AWS SDK release that made 
apache5-client the default; BOM-managed dependencies keep their managed version.
+preconditions:
+  - org.openrewrite.java.dependencies.search.ModuleHasDependency:
+      groupIdPattern: org.apache.camel
+      artifactIdPattern: camel-aws*
+recipeList:
+  - org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId:
+      oldGroupId: software.amazon.awssdk
+      oldArtifactId: apache-client
+      newGroupId: software.amazon.awssdk
+      newArtifactId: apache5-client
+      # Applied to explicitly pinned versions only; BOM-managed dependencies 
keep their managed version
+      newVersion: 2.46.0
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-minio---upgraded-to-minio-903---breaking-changes
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateMinioTypes
+displayName: Migrate Minio types for minio 9.0 upgrade
+description: Migrates Minio types that were renamed or moved in the minio 8.x 
to 9.0 upgrade.
+preconditions:
+  - org.openrewrite.java.dependencies.search.ModuleHasDependency:
+      groupIdPattern: org.apache.camel
+      artifactIdPattern: camel-minio
+recipeList:
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: io.minio.CopySource
+      newFullyQualifiedTypeName: io.minio.SourceObject
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-reactive-executor-tomcat
+type: specs.openrewrite.org/v1beta/recipe
+name: 
org.apache.camel.upgrade.camel422.removeCamelReactiveExecutorTomcatDependency
+displayName: Remove camel-reactive-executor-tomcat dependency
+description: Removes the camel-reactive-executor-tomcat dependency which was 
deprecated in Camel 4.22 (functionally identical to the built-in default 
reactive executor since JDK 17, Camel falls back to it automatically).
+recipeList:
+  - org.openrewrite.maven.RemoveDependency:
+      groupId: org.apache.camel
+      artifactId: camel-reactive-executor-tomcat
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-spring-ai-chat
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateSpringAiToolsDependency
+displayName: Migrate camel-spring-ai-tools to camel-ai-tool
+description: Migrates the camel-spring-ai-tools dependency, removed in Camel 
4.22, to camel-ai-tool. Route URIs using the spring-ai-tools scheme must be 
migrated to ai-tool manually.
+recipeList:
+  - org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId:
+      oldGroupId: org.apache.camel
+      oldArtifactId: camel-spring-ai-tools
+      newGroupId: org.apache.camel
+      newArtifactId: camel-ai-tool
+      newVersion: 4.22.0
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-openai
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateOpenAiChatCompletion
+displayName: Migrate OpenAI ChatCompletion type to its new package
+description: Migrates com.openai.models.ChatCompletion to 
com.openai.models.chat.completions.ChatCompletion, matching the javaType 
declared for the CamelOpenAIResponse exchange property since Camel 4.22.
+preconditions:
+  - org.openrewrite.java.dependencies.search.ModuleHasDependency:
+      groupIdPattern: org.apache.camel
+      artifactIdPattern: camel-openai
+recipeList:
+  - org.openrewrite.java.ChangeType:
+      oldFullyQualifiedTypeName: com.openai.models.ChatCompletion
+      newFullyQualifiedTypeName: 
com.openai.models.chat.completions.ChatCompletion
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-langchain4j-tools-deprecated
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateLangchain4jToolsUris
+displayName: Migrate langchain4j-tools endpoint URIs to ai-tool
+description: Renames the langchain4j-tools URI scheme to ai-tool on consumer 
endpoints (tool definition routes) in Java, XML and YAML DSL, and adds the 
camel-ai-tool dependency. Producer endpoints for direct tool calling are left 
unchanged and must be migrated to langchain4j-agent manually.
+preconditions:
+  - org.openrewrite.java.dependencies.search.ModuleHasDependency:
+      groupIdPattern: org.apache.camel
+      artifactIdPattern: camel-langchain4j-tools
+recipeList:
+  - org.apache.camel.upgrade.customRecipes.ChangeComponentUriRecipe:
+      uriPattern: "^langchain4j-tools:(.*)$"
+      replacement: "ai-tool:${1}"
+      consumerOnly: true
+  - org.openrewrite.maven.AddDependency:
+      groupId: org.apache.camel
+      artifactId: camel-ai-tool
+      # Fallback for poms with explicit versions only: when a BOM manages 
camel-ai-tool,
+      # AddDependency omits the version tag and the BOM-managed version wins. 
The latest
+      # migration chain additionally bumps org.apache.camel:* to its target 
version.
+      version: 4.22.0
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-spring-ai-chat
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateSpringAiToolsUris
+displayName: Migrate spring-ai-tools endpoint URIs to ai-tool
+description: Renames the spring-ai-tools URI scheme to ai-tool in Java, XML 
and YAML DSL routes, following the removal of the camel-spring-ai-tools 
component. Applies without a dependency precondition so that projects whose 
camel-spring-ai-tools dependency was already renamed (manually or by the 
dependency recipe) still get their routes migrated; the scheme is unique to the 
removed component.
+recipeList:
+  - org.apache.camel.upgrade.customRecipes.ChangeComponentUriRecipe:
+      uriPattern: "^spring-ai-tools:(.*)$"
+      replacement: "ai-tool:${1}"
+---
+## 
https://github.com/apache/camel/blob/main/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc#camel-atmosphere-websocket---potential-breaking-change
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateAtmosphereWebsocketHeaders
+displayName: Migrate camel-atmosphere-websocket header values to new naming 
convention
+description: Renames the atmosphere-websocket Exchange header string values 
from websocket.* to CamelAtmosphereWebsocket*, only when the 
camel-atmosphere-websocket dependency is present. Symbolic WebsocketConstants 
references are unaffected and need no migration.
+preconditions:
+  - org.openrewrite.java.dependencies.search.ModuleHasDependency:
+      groupIdPattern: org.apache.camel
+      artifactIdPattern: camel-atmosphere-websocket
+recipeList:
+  - org.apache.camel.upgrade.camel418_3.RenameHeaders:
+      headerMappings:
+        websocket.connectionKey.list: CamelAtmosphereWebsocketConnectionKeyList
+        websocket.connectionKey: CamelAtmosphereWebsocketConnectionKey
+        websocket.sendToAll: CamelAtmosphereWebsocketSendToAll
+        websocket.eventType: CamelAtmosphereWebsocketEventType
+        websocket.errorType: CamelAtmosphereWebsocketErrorType
diff --git 
a/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml 
b/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
index 921aa54..83b6410 100644
--- a/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
+++ b/camel-upgrade-recipes/src/main/resources/META-INF/rewrite/latest.yaml
@@ -20,6 +20,7 @@ name: org.apache.camel.upgrade.CamelMigrationRecipe
 displayName: Migrate to @camel-latest-version@
 description: Migrates Apache Camel application to @camel-latest-version@.
 recipeList:
+  - org.apache.camel.upgrade.camel422.CamelMigrationRecipe
   - org.apache.camel.upgrade.camel421.CamelMigrationRecipe
   - org.apache.camel.upgrade.camel420.CamelMigrationRecipe
   - org.apache.camel.upgrade.camel419.CamelMigrationRecipe
diff --git 
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelTestUtil.java
 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelTestUtil.java
index 56fb836..7118070 100644
--- 
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelTestUtil.java
+++ 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelTestUtil.java
@@ -62,7 +62,8 @@ public class CamelTestUtil {
         v4_18_3(4, 18, 3, true),
         v4_19(4, 19, 0),
         v4_20(4, 20, 0),
-        v4_21(4, 21, 0);
+        v4_21(4, 21, 0),
+        v4_22(4, 22, 0);
 
         private int major;
         private int minor;
diff --git 
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate421Test.java
 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate421Test.java
index ccaa588..620f618 100644
--- 
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate421Test.java
+++ 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate421Test.java
@@ -17,6 +17,7 @@
 package org.apache.camel.upgrade;
 
 import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
 import org.openrewrite.test.RecipeSpec;
 import org.openrewrite.test.RewriteTest;
 import org.openrewrite.test.TypeValidation;
@@ -42,6 +43,43 @@ public class CamelUpdate421Test implements RewriteTest {
                 .expectedCyclesThatMakeChanges(1);
     }
 
+    @DocumentExample
+    @Test
+    void removeCamelStompDependency() {
+        //language=xml
+        rewriteRun(
+                pomXml(
+                """
+                <project>
+                    <groupId>com.example</groupId>
+                    <artifactId>test</artifactId>
+                    <version>1.0.0</version>
+                    <properties>
+                        <maven.compiler.release>17</maven.compiler.release>
+                    </properties>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.apache.camel</groupId>
+                            <artifactId>camel-stomp</artifactId>
+                            <version>4.20.0</version>
+                        </dependency>
+                    </dependencies>
+                </project>
+                """,
+                """
+                <project>
+                    <groupId>com.example</groupId>
+                    <artifactId>test</artifactId>
+                    <version>1.0.0</version>
+                    <properties>
+                        <maven.compiler.release>17</maven.compiler.release>
+                    </properties>
+                </project>
+                """
+                )
+        );
+    }
+
     @Test
     void jGroupsHeadersMigration() {
         new CamelUpdate418_3Test().jGroupsHeadersMigration();
@@ -256,42 +294,6 @@ public class CamelUpdate421Test implements RewriteTest {
         new CamelUpdate418_3Test().luceneHeadersMigrationJava();
     }
 
-    @Test
-    void removeCamelStompDependency() {
-        //language=xml
-        rewriteRun(
-                pomXml(
-                """
-                <project>
-                    <groupId>com.example</groupId>
-                    <artifactId>test</artifactId>
-                    <version>1.0.0</version>
-                    <properties>
-                        <maven.compiler.release>17</maven.compiler.release>
-                    </properties>
-                    <dependencies>
-                        <dependency>
-                            <groupId>org.apache.camel</groupId>
-                            <artifactId>camel-stomp</artifactId>
-                            <version>4.20.0</version>
-                        </dependency>
-                    </dependencies>
-                </project>
-                """,
-                """
-                <project>
-                    <groupId>com.example</groupId>
-                    <artifactId>test</artifactId>
-                    <version>1.0.0</version>
-                    <properties>
-                        <maven.compiler.release>17</maven.compiler.release>
-                    </properties>
-                </project>
-                """
-                )
-        );
-    }
-
     @Test
     void removeCamelAwsXrayDependency() {
         //language=xml
diff --git 
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate422Test.java
 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate422Test.java
new file mode 100644
index 0000000..b87305e
--- /dev/null
+++ 
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate422Test.java
@@ -0,0 +1,516 @@
+/*
+ * 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.upgrade;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+import org.openrewrite.test.TypeValidation;
+
+import static org.openrewrite.java.Assertions.java;
+import static org.openrewrite.java.Assertions.mavenProject;
+import static org.openrewrite.maven.Assertions.pomXml;
+
+public class CamelUpdate422Test implements RewriteTest {
+
+    @Override
+    public void defaults(RecipeSpec spec) {
+        CamelTestUtil.recipe(spec, CamelTestUtil.CamelVersion.v4_22, true)
+                
.parser(CamelTestUtil.parserFromClasspath(CamelTestUtil.CamelVersion.v4_21,
+                        "camel-core-model", "camel-api", "camel-support", 
"camel-azure-storage-blob", "minio",
+                        "openai-java-core", "jakarta.xml.bind-api"))
+                .typeValidationOptions(TypeValidation.none())
+                .expectedCyclesThatMakeChanges(1);
+    }
+
+    @DocumentExample
+    @Test
+    void migrateAzureStorageBlobCredentialType() {
+        //language=java
+        rewriteRun(
+                java(
+                        """
+                        import 
org.apache.camel.component.azure.storage.blob.CredentialType;
+
+                        public class BlobExample {
+                            public void example() {
+                                CredentialType type = 
CredentialType.SHARED_KEY_CREDENTIAL;
+                            }
+                        }
+                        """,
+                        """
+                        import 
org.apache.camel.component.azure.common.CredentialType;
+
+                        public class BlobExample {
+                            public void example() {
+                                CredentialType type = 
CredentialType.SHARED_KEY_CREDENTIAL;
+                            }
+                        }
+                        """
+                )
+        );
+    }
+
+    @Test
+    @DisabledIfSystemProperty(named = CamelTestUtil.PROPERTY_USE_RECIPE, 
matches = ".+")
+    void migrateAwsApacheClient() {
+        //language=xml
+        rewriteRun(
+                mavenProject("test-aws",
+                pomXml(
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.apache.camel</groupId>
+                                    <artifactId>camel-aws2-sqs</artifactId>
+                                    <version>4.21.0</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>software.amazon.awssdk</groupId>
+                                    <artifactId>apache-client</artifactId>
+                                    <version>2.20.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """,
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.apache.camel</groupId>
+                                    <artifactId>camel-aws2-sqs</artifactId>
+                                    <version>4.21.0</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>software.amazon.awssdk</groupId>
+                                    <artifactId>apache5-client</artifactId>
+                                    <version>2.46.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """
+                )
+                )
+        );
+    }
+
+    @Test
+    void preconditionBlocksAwsApacheClientWithoutCamelAws() {
+        //language=xml
+        rewriteRun(
+                spec -> spec.expectedCyclesThatMakeChanges(0),
+                pomXml(
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>software.amazon.awssdk</groupId>
+                                    <artifactId>apache-client</artifactId>
+                                    <version>2.20.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """
+                )
+        );
+    }
+
+    @Test
+    void migrateMinioCopySource() {
+        //language=java
+        rewriteRun(
+                mavenProject("test-minio",
+                        CamelTestUtil.pomXmlSpec("camel-minio", 
CamelTestUtil.CamelVersion.v4_21),
+                        java(
+                                """
+                                import io.minio.CopySource;
+
+                                public class MinioExample {
+                                    public void example() {
+                                        CopySource src = null;
+                                    }
+                                }
+                                """,
+                                """
+                                import io.minio.SourceObject;
+
+                                public class MinioExample {
+                                    public void example() {
+                                        SourceObject src = null;
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+    @Test
+    void removeCamelReactiveExecutorTomcatDependency() {
+        //language=xml
+        rewriteRun(
+                pomXml(
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.apache.camel</groupId>
+                                    
<artifactId>camel-reactive-executor-tomcat</artifactId>
+                                    <version>4.21.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """,
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                        </project>
+                        """
+                )
+        );
+    }
+
+    @DisabledIfSystemProperty(named = CamelTestUtil.PROPERTY_USE_RECIPE, 
matches = ".+")
+    @Test
+    void migrateSpringAiToolsDependency() {
+        //language=xml
+        rewriteRun(
+                pomXml(
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.apache.camel</groupId>
+                                    
<artifactId>camel-spring-ai-tools</artifactId>
+                                    <version>4.21.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """,
+                        """
+                        <project>
+                            <groupId>com.example</groupId>
+                            <artifactId>test</artifactId>
+                            <version>1.0.0</version>
+                            <properties>
+                                
<maven.compiler.release>17</maven.compiler.release>
+                            </properties>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.apache.camel</groupId>
+                                    <artifactId>camel-ai-tool</artifactId>
+                                    <version>4.22.0</version>
+                                </dependency>
+                            </dependencies>
+                        </project>
+                        """
+                )
+        );
+    }
+
+    @Test
+    void migrateOpenAiChatCompletion() {
+        //language=java
+        rewriteRun(
+                mavenProject("test-openai",
+                        CamelTestUtil.pomXmlSpec("camel-openai", 
CamelTestUtil.CamelVersion.v4_21),
+                        java(
+                                """
+                                import com.openai.models.ChatCompletion;
+
+                                public class OpenAiExample {
+                                    public void example() {
+                                        ChatCompletion completion = null;
+                                    }
+                                }
+                                """,
+                                """
+                                import 
com.openai.models.chat.completions.ChatCompletion;
+
+                                public class OpenAiExample {
+                                    public void example() {
+                                        ChatCompletion completion = null;
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+    @Test
+    @DisabledIfSystemProperty(named = CamelTestUtil.PROPERTY_USE_RECIPE, 
matches = ".+")
+    void migrateLangchain4jToolsUris() {
+        rewriteRun(
+                mavenProject("test-langchain4j-tools",
+                        //language=xml
+                        pomXml(
+                                """
+                                <project>
+                                    <groupId>com.example</groupId>
+                                    <artifactId>test</artifactId>
+                                    <version>1.0.0</version>
+                                    <properties>
+                                        
<maven.compiler.release>17</maven.compiler.release>
+                                    </properties>
+                                    <dependencies>
+                                        <dependency>
+                                            <groupId>org.apache.camel</groupId>
+                                            
<artifactId>camel-langchain4j-tools</artifactId>
+                                            <version>4.21.0</version>
+                                        </dependency>
+                                    </dependencies>
+                                </project>
+                                """,
+                                """
+                                <project>
+                                    <groupId>com.example</groupId>
+                                    <artifactId>test</artifactId>
+                                    <version>1.0.0</version>
+                                    <properties>
+                                        
<maven.compiler.release>17</maven.compiler.release>
+                                    </properties>
+                                    <dependencies>
+                                        <dependency>
+                                            <groupId>org.apache.camel</groupId>
+                                            
<artifactId>camel-ai-tool</artifactId>
+                                            <version>4.22.0</version>
+                                        </dependency>
+                                        <dependency>
+                                            <groupId>org.apache.camel</groupId>
+                                            
<artifactId>camel-langchain4j-tools</artifactId>
+                                            <version>4.21.0</version>
+                                        </dependency>
+                                    </dependencies>
+                                </project>
+                                """
+                        ),
+                        //language=java
+                        java(
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class ToolRoute extends RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        
from("langchain4j-tools:userDb?tags=users&description=Query user 
database&parameter.userId=string")
+                                            .to("mock:result");
+                                        from("direct:invoke")
+                                            
.to("langchain4j-tools:userDb?tags=users");
+                                    }
+                                }
+                                """,
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class ToolRoute extends RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        
from("ai-tool:userDb?tags=users&description=Query user 
database&parameter.userId=string")
+                                            .to("mock:result");
+                                        from("direct:invoke")
+                                            
.to("langchain4j-tools:userDb?tags=users");
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+    @DisabledIfSystemProperty(named = CamelTestUtil.PROPERTY_USE_RECIPE, 
matches = ".+")
+    @Test
+    void migrateSpringAiToolsUris() {
+        rewriteRun(
+                mavenProject("test-spring-ai-tools",
+                        //language=xml
+                        pomXml(
+                                """
+                                <project>
+                                    <groupId>com.example</groupId>
+                                    <artifactId>test</artifactId>
+                                    <version>1.0.0</version>
+                                    <properties>
+                                        
<maven.compiler.release>17</maven.compiler.release>
+                                    </properties>
+                                    <dependencies>
+                                        <dependency>
+                                            <groupId>org.apache.camel</groupId>
+                                            
<artifactId>camel-spring-ai-tools</artifactId>
+                                            <version>4.21.0</version>
+                                        </dependency>
+                                    </dependencies>
+                                </project>
+                                """,
+                                """
+                                <project>
+                                    <groupId>com.example</groupId>
+                                    <artifactId>test</artifactId>
+                                    <version>1.0.0</version>
+                                    <properties>
+                                        
<maven.compiler.release>17</maven.compiler.release>
+                                    </properties>
+                                    <dependencies>
+                                        <dependency>
+                                            <groupId>org.apache.camel</groupId>
+                                            
<artifactId>camel-ai-tool</artifactId>
+                                            <version>4.22.0</version>
+                                        </dependency>
+                                    </dependencies>
+                                </project>
+                                """
+                        ),
+                        //language=java
+                        java(
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class WeatherToolRoute extends 
RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        
from("spring-ai-tools:weather?tags=weather&description=Get current 
weather&parameter.city=string")
+                                            .to("mock:result");
+                                    }
+                                }
+                                """,
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class WeatherToolRoute extends 
RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        
from("ai-tool:weather?tags=weather&description=Get current 
weather&parameter.city=string")
+                                            .to("mock:result");
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+    @Test
+    void migrateAtmosphereWebsocketHeaders() {
+        //language=java
+        rewriteRun(
+                mavenProject("test-atmosphere-websocket",
+                        CamelTestUtil.pomXmlSpec("camel-atmosphere-websocket", 
CamelTestUtil.CamelVersion.v4_21),
+                        java(
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class WebsocketRoute extends 
RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        from("direct:next")
+                                            
.setHeader("websocket.connectionKey", header("myKey"))
+                                            
.to("atmosphere-websocket:///servicepath");
+                                        from("direct:broadcast")
+                                            .process(exchange -> {
+                                                
exchange.getIn().setHeader("websocket.connectionKey.list", "keys");
+                                                
exchange.getIn().setHeader("websocket.sendToAll", "true");
+                                                
exchange.getIn().setHeader("websocket.eventType", "1");
+                                            })
+                                            
.to("atmosphere-websocket:///servicepath");
+                                    }
+                                }
+                                """,
+                                """
+                                import org.apache.camel.builder.RouteBuilder;
+
+                                public class WebsocketRoute extends 
RouteBuilder {
+                                    @Override
+                                    public void configure() {
+                                        from("direct:next")
+                                            
.setHeader("CamelAtmosphereWebsocketConnectionKey", header("myKey"))
+                                            
.to("atmosphere-websocket:///servicepath");
+                                        from("direct:broadcast")
+                                            .process(exchange -> {
+                                                
exchange.getIn().setHeader("CamelAtmosphereWebsocketConnectionKeyList", "keys");
+                                                
exchange.getIn().setHeader("CamelAtmosphereWebsocketSendToAll", "true");
+                                                
exchange.getIn().setHeader("CamelAtmosphereWebsocketEventType", "1");
+                                            })
+                                            
.to("atmosphere-websocket:///servicepath");
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+    @Test
+    void preconditionBlocksMinioWithoutDependency() {
+        //language=java
+        rewriteRun(
+                spec -> 
spec.expectedCyclesThatMakeChanges(CamelTestUtil.isRecipeOverridden() ? 1 : 0),
+                mavenProject("test-negative",
+                        CamelTestUtil.pomXmlSpec("camel-core", 
CamelTestUtil.CamelVersion.v4_21),
+                        java(
+                                """
+                                import io.minio.CopySource;
+
+                                public class NegativeMinioExample {
+                                    public void example() {
+                                        CopySource src = null;
+                                    }
+                                }
+                                """
+                        )
+                )
+        );
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index 5ac7a15..aa4b722 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,7 +109,7 @@
         <camel4.18-lts-version>4.18.3</camel4.18-lts-version>
 
         <!-- versions for latest recipes, has to be kept aligned to the latest 
camel release -->
-        <camel-latest-version>4.21.0</camel-latest-version>
+        <camel-latest-version>4.22.0</camel-latest-version>
 
         <camel-version>${project.version}</camel-version>
         
<camel-spring-boot-version>${project.version}</camel-spring-boot-version>
@@ -119,7 +119,7 @@
         <jspecify-version>1.0.0</jspecify-version>
 
         <!-- Should be aligned to quarkus-updates - 
https://github.com/quarkusio/quarkus-updates/blob/main/pom.xml#L64 -->
-        <rewrite-recipe-bom.version>3.31.0</rewrite-recipe-bom.version>
+        <rewrite-recipe-bom.version>3.37.0</rewrite-recipe-bom.version>
 
         <slf4j.version>1.7.36</slf4j.version>
 
@@ -188,7 +188,7 @@
                     <plugin>
                         <groupId>org.openrewrite.maven</groupId>
                         <artifactId>rewrite-maven-plugin</artifactId>
-                        <version>6.19.0</version>
+                        <version>6.46.1</version>
                         <configuration>
                             <activeRecipes>
                                 
<recipe>org.apache.camel.upgrade.internal.OpenRewriteRecipeBestPractices</recipe>
diff --git a/release_notes.adoc b/release_notes.adoc
index 00a3363..04d4daa 100644
--- a/release_notes.adoc
+++ b/release_notes.adoc
@@ -1,5 +1,62 @@
 = Camel Upgrade Recipes - Release notes
 
+== 4.22.0
+
+=== Summary
+
+This is a release supporting Camel, Camel Quarkus and Camel Spring Boot 4.22.0 
with the required upgrade recipes (described by the 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html[migration 
guide]).
+
+=== Migration coverage
+
+The following table lists migration topics and indicates the level of coverage 
(full, partial, or not covered), along with additional comments.
+
+[%autowidth,stripes=hover]
+|===
+| Migration | Coverage | Comment
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_reactive_executor_tomcat[camel-reactive-executor-tomcat:
 component deprecated]
+| ✅ Full
+| Automated via `RemoveDependency` — the component is functionally identical 
to the built-in default reactive executor since JDK 17, Camel falls back to it 
automatically
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_route_tools_now_use_ai_tool[camel-langchain4j-agent:
 tool routes `langchain4j-tools:` → `ai-tool:`]
+| ⚠️ Partial
+| Consumer route URIs renamed via `ChangeComponentUriRecipe` across Java, XML 
and YAML DSL and the `camel-ai-tool` dependency added automatically (gated on 
`camel-langchain4j-tools`); producer endpoints are preserved and must be 
migrated to `langchain4j-agent` manually
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_langchain4j_tools_deprecated[camel-langchain4j-tools:
 component deprecated]
+| ⚠️ Partial
+| Tool definition (consumer) route URIs `langchain4j-tools:` → `ai-tool:` 
automated via `ChangeComponentUriRecipe` and the `camel-ai-tool` dependency 
added automatically (gated on `camel-langchain4j-tools`); direct tool-calling 
producer endpoints are preserved and must be migrated to `langchain4j-agent` 
manually
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_openai[camel-openai:
 ChatCompletion type moved]
+| ⚠️ Partial
+| Automated via `ChangeType` for `com.openai.models.ChatCompletion` → 
`com.openai.models.chat.completions.ChatCompletion` (gated on the 
`camel-openai` dependency)
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_azure_component_specific_credentialtype_enums_removed[camel-azure:
 component-specific CredentialType enums removed]
+| ✅ Full
+| Automated via `ChangeType` for all 10 component-specific enums → 
`org.apache.camel.component.azure.common.CredentialType`
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_spring_ai_chat[camel-spring-ai-chat:
 camel-spring-ai-tools component removed]
+| ✅ Full
+| Automated via `ChangeDependencyGroupIdAndArtifactId` for 
`camel-spring-ai-tools` → `camel-ai-tool` (and `camel-spring-ai-tools-starter` 
→ `camel-ai-tool-starter` in the Spring Boot recipe). Tool route URIs are 
covered by the `spring-ai-tools:` → `ai-tool:` URI recipe (see below)
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_route_tools_now_use_ai_tool_2[camel-spring-ai-chat:
 tool routes `spring-ai-tools:` → `ai-tool:`]
+| ✅ Full
+| Automated via `ChangeComponentUriRecipe` for `spring-ai-tools:` → `ai-tool:` 
across Java, XML and YAML DSL, applied without a dependency gate so 
already-renamed projects are still migrated; dependency and starter renames are 
covered by the dedicated recipes
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_aws_migrated_from_apache_client_to_apache5_client[camel-aws:
 apache-client → apache5-client]
+| ✅ Full
+| Automated via `ChangeDependencyGroupIdAndArtifactId` for 
`software.amazon.awssdk:apache-client` → 
`software.amazon.awssdk:apache5-client`, gated on a `camel-aws*` dependency; 
explicit versions are bumped to 2.46.0 (the first AWS SDK release using 
apache5-client by default), BOM-managed versions are untouched
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_minio_upgraded_to_minio_9_0_3_breaking_changes[camel-minio:
 type renames (minio 8.x → 9.0)]
+| ⚠️ Partial
+| `CopySource` → `SourceObject` automated via `ChangeType`. Inner class 
renames (`ServerSideEncryptionCustomerKey` → 
`ServerSideEncryption.CustomerKey`, `http.Method` → `Http.Method`, 
`messages.Bucket` → `ListAllMyBucketsResult.Bucket`, `DeleteObject` → 
`DeleteRequest.Object`) not automatable — OpenRewrite `ChangeType` to inner 
classes is not idempotent. Requires manual migration.
+
+| 
https://camel.apache.org/manual/camel-4x-upgrade-guide-4_22.html#_camel_atmosphere_websocket_potential_breaking_change[camel-atmosphere-websocket:
 Exchange header values renamed]
+| ⚠️ Partial
+| Literal `websocket.*` → `CamelAtmosphereWebsocket*` header values automated 
via the 4.18.3 `RenameHeaders` custom recipe (gated on 
`camel-atmosphere-websocket`); symbolic `WebsocketConstants` usages need no 
change, cross-transport propagation of the now-`Camel*`-prefixed headers 
requires manual review
+
+
+|===
+
 == 4.21.0
 
 === Summary
diff --git a/rewrite.yml b/rewrite.yml
index 37b8e5e..5912cc9 100644
--- a/rewrite.yml
+++ b/rewrite.yml
@@ -61,7 +61,6 @@ recipeList:
   - org.openrewrite.java.recipes.NoMutableStaticFieldsInRecipes
   - org.openrewrite.java.recipes.RecipeEqualsAndHashCodeCallSuper
   - org.openrewrite.java.recipes.UseTreeRandomId
-  - org.openrewrite.java.recipes.migrate.RemoveTraitsUsageRecipes
   - org.openrewrite.staticanalysis.NeedBraces
   - org.openrewrite.staticanalysis.RemoveSystemOutPrintln
   - org.openrewrite.java.RemoveAnnotation:

Reply via email to