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¶meter.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¶meter.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¶meter.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¶meter.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: