This is an automated email from the ASF dual-hosted git repository.
Croway 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 594cea1 Fix five defects in the Camel 4.22 upgrade recipes- #125
594cea1 is described below
commit 594cea17ae3860c504ac189eb81d63d5fbdd5a14
Author: Federico Mariani <[email protected]>
AuthorDate: Tue Aug 25 13:40:44 2026 +0200
Fix five defects in the Camel 4.22 upgrade recipes- #125
---
.../src/main/resources/META-INF/rewrite/4.22.yaml | 20 +++
.../upgrade/springboot/CamelSpringBoot422Test.java | 138 +++++++++++++++++++++
camel-upgrade-recipes/pom.xml | 8 --
.../java/org/apache/camel/upgrade/RecipesUtil.java | 49 ++++++++
.../camel418_3/RenameHeaderInJavaMethod.java | 10 +-
.../camel418_3/RenameHeaderInSimpleExpression.java | 65 +++++-----
.../upgrade/camel418_3/RenameHeaderInXmlDsl.java | 84 ++++++++++---
.../upgrade/camel418_3/RenameHeaderInYamlDsl.java | 31 ++++-
.../camel/upgrade/camel46/XmlDsl46Recipe.java | 6 +-
.../ReplacePropertyInComponentYaml.java | 13 +-
.../src/main/resources/META-INF/rewrite/4.22.yaml | 15 ---
.../apache/camel/upgrade/CamelUpdate415Test.java | 24 ++++
.../apache/camel/upgrade/CamelUpdate422Test.java | 32 +----
.../apache/camel/upgrade/CamelUpdate46Test.java | 13 ++
.../camel418_3/RenameHeaderInJavaMethodTest.java | 32 +++++
.../RenameHeaderInSimpleExpressionTest.java | 97 ++++++++++++++-
.../camel418_3/RenameHeaderInXmlDslTest.java | 101 +++++++++++++++
.../camel418_3/RenameHeaderInYamlDslTest.java | 28 +++++
release_notes.adoc | 4 +-
19 files changed, 647 insertions(+), 123 deletions(-)
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
index 2e5e17c..73796a1 100644
---
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
@@ -23,6 +23,7 @@ recipeList:
- org.apache.camel.upgrade.camel421.CamelSpringBootMigrationRecipe
- org.apache.camel.upgrade.camel422.CamelMigrationRecipe
- org.apache.camel.upgrade.camel422.migrateSpringAiToolsStarterDependency
+ - org.apache.camel.upgrade.camel422.migrateAiToolStarterDependency
---
##
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
@@ -36,3 +37,22 @@ recipeList:
newGroupId: org.apache.camel.springboot
newArtifactId: camel-ai-tool-starter
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-langchain4j-tools-deprecated
+type: specs.openrewrite.org/v1beta/recipe
+name: org.apache.camel.upgrade.camel422.migrateAiToolStarterDependency
+displayName: Use camel-ai-tool-starter instead of camel-ai-tool
+description: Replaces the plain camel-ai-tool dependency with
camel-ai-tool-starter, so that a Spring Boot application gets the component
auto-configuration. The plain artifact is what the Camel recipe adds when
migrating langchain4j-tools routes. Only modules that use Spring Boot are
rewritten, so the plain Camel modules of a multi-module build keep the
non-starter artifact.
+preconditions:
+ # FindDependency marks the pom that declares the dependency, so the swap is
scoped to the modules
+ # that actually use Spring Boot rather than to every module of a
multi-module build
+ - org.openrewrite.maven.search.FindDependency:
+ groupId: org.springframework.boot
+ artifactId: '*'
+recipeList:
+ - org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId:
+ oldGroupId: org.apache.camel
+ oldArtifactId: camel-ai-tool
+ newGroupId: org.apache.camel.springboot
+ newArtifactId: camel-ai-tool-starter
+ newVersion: 4.22.0
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
index 24345b1..9ffcd36 100644
---
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
@@ -78,4 +78,142 @@ class CamelSpringBoot422Test implements RewriteTest {
);
}
+ @Test
+ void migrateAiToolStarterDependency() {
+ // spring-boot-starter is pinned to the version the migration targets,
so that the assertion
+ // covers the ai-tool swap only and is not disturbed by the Spring
Boot upgrade in the same chain
+ //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.springframework.boot</groupId>
+
<artifactId>spring-boot-starter</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-ai-tool</artifactId>
+ <version>4.22.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.springframework.boot</groupId>
+
<artifactId>spring-boot-starter</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+
<groupId>org.apache.camel.springboot</groupId>
+
<artifactId>camel-ai-tool-starter</artifactId>
+ <version>4.22.0</version>
+ </dependency>
+ </dependencies>
+ </project>
+ """
+ )
+ );
+ }
+
+ @Test
+ void aiToolStarterIsNotDuplicated() {
+ //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.springframework.boot</groupId>
+
<artifactId>spring-boot-starter</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-ai-tool</artifactId>
+ <version>4.22.0</version>
+ </dependency>
+ <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.springframework.boot</groupId>
+
<artifactId>spring-boot-starter</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+
<groupId>org.apache.camel.springboot</groupId>
+
<artifactId>camel-ai-tool-starter</artifactId>
+ <version>4.22.0</version>
+ </dependency>
+ </dependencies>
+ </project>
+ """
+ )
+ );
+ }
+
+ @Test
+ void doesNotSwapAiToolInNonBootModule() {
+ //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-ai-tool</artifactId>
+ <version>4.22.0</version>
+ </dependency>
+ </dependencies>
+ </project>
+ """
+ )
+ );
+ }
}
diff --git a/camel-upgrade-recipes/pom.xml b/camel-upgrade-recipes/pom.xml
index 263b43d..23a5564 100644
--- a/camel-upgrade-recipes/pom.xml
+++ b/camel-upgrade-recipes/pom.xml
@@ -635,14 +635,6 @@
<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/RecipesUtil.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/RecipesUtil.java
index 0c32182..e6b769b 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/RecipesUtil.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/RecipesUtil.java
@@ -22,6 +22,7 @@ import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.tree.*;
import org.openrewrite.marker.Markers;
import org.openrewrite.marker.SearchResult;
+import org.openrewrite.xml.XmlIsoVisitor;
import org.openrewrite.xml.tree.Xml;
import org.openrewrite.yaml.YamlIsoVisitor;
import org.openrewrite.yaml.tree.Yaml;
@@ -84,6 +85,54 @@ public class RecipesUtil {
return false;
}
+ // ---------------- Camel XML DSL precondition
+ private static final Set<String> CAMEL_XML_DSL_ROOT_TAGS = Set.of(
+ "routes", "route", "routeConfiguration", "routeTemplate",
"templatedRoute",
+ "rests", "rest", "restConfiguration", "camelContext",
"routeContext", "bean", "beans");
+
+ private static final String SPRING_BEANS_NAMESPACE =
"springframework.org/schema/beans";
+
+ /**
+ * Matches documents whose root element belongs to the Camel XML DSL, so
that Simple expressions are
+ * not rewritten in unrelated XML such as Spring bean definitions, where
${...} is a property placeholder.
+ */
+ public static TreeVisitor<?, ExecutionContext> camelXmlDslPrecondition() {
+ return new XmlIsoVisitor<ExecutionContext>() {
+ @Override
+ public Xml.Document visitDocument(Xml.Document document,
ExecutionContext ctx) {
+ if (isCamelXmlDsl(document.getRoot())) {
+ return SearchResult.found(document);
+ }
+ return document;
+ }
+ };
+ }
+
+ public static boolean isCamelXmlDsl(Xml.@Nullable Tag root) {
+ if (root == null) {
+ return false;
+ }
+
+ // <bean> and <beans> are shared with Spring, whose namespace rules
the document out
+ if (declaresNamespace(root, SPRING_BEANS_NAMESPACE)) {
+ return false;
+ }
+
+ // A Camel namespace is conclusive, whatever the root element is
+ if (declaresNamespace(root, "camel.apache.org")) {
+ return true;
+ }
+
+ // Camel XML DSL files are commonly written without any namespace, so
fall back on the root element
+ return CAMEL_XML_DSL_ROOT_TAGS.contains(root.getName());
+ }
+
+ private static boolean declaresNamespace(Xml.Tag root, String
namespaceFragment) {
+ return root.getAttributes().stream()
+ .anyMatch(a -> a.getKeyAsString().startsWith("xmlns")
+ &&
a.getValueAsString().contains(namespaceFragment));
+ }
+
//---------------- annotations helpers
public static J.Annotation createAnnotation(
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 6575d32..ff1ce27 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
@@ -68,7 +68,8 @@ public class RenameHeaderInJavaMethod extends Recipe {
@Override
public String getDescription() {
- return "Renames header references in Message.setHeader() and
Message.getHeader() method calls. " +
+ return "Renames header references in Message.setHeader(),
Message.getHeader(), and in the " +
+ "setHeader(), removeHeader() and header() DSL methods. " +
"Only migrates string literals in safe contexts. Does NOT
migrate dynamic header names or Map.get() calls.";
}
@@ -88,6 +89,10 @@ public class RenameHeaderInJavaMethod extends Recipe {
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);
+ // header("name") builds a predicate/expression on the header, it is
declared on BuilderSupport
+ // and therefore available on RouteBuilder and the expression clauses
+ private static final MethodMatcher BUILDER_HEADER_MATCHER =
+ new MethodMatcher("org.apache.camel.builder.BuilderSupport
header(String)", true);
private final String oldHeaderName;
private final String newHeaderName;
@@ -133,7 +138,8 @@ public class RenameHeaderInJavaMethod extends Recipe {
getMethodMatcher(MATCHER_GET_HEADER_3_ARGS).matches(mi) ||
getMethodMatcher(MATCHER_GET_HEADER_SUPPLIER).matches(mi) ||
DSL_SET_HEADER_MATCHER.matches(mi) ||
- DSL_REMOVE_HEADER_MATCHER.matches(mi);
+ DSL_REMOVE_HEADER_MATCHER.matches(mi) ||
+ BUILDER_HEADER_MATCHER.matches(mi);
}
}
}
diff --git
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpression.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpression.java
index f62c3e4..0c92f81 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpression.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpression.java
@@ -24,11 +24,13 @@ import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.tree.J;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Renames header references in Simple expressions like ${header.oldName} or
${headers.oldName}.
- * This recipe only transforms strings inside simple() method calls to avoid
false positives.
+ * The whole placeholder is matched, so any string literal carrying a Simple
expression is covered,
+ * whether it is passed to simple(), to log(), or to an endpoint URI.
*/
public class RenameHeaderInSimpleExpression extends Recipe {
@@ -65,8 +67,9 @@ public class RenameHeaderInSimpleExpression extends Recipe {
@Override
public String getDescription() {
- return "Renames header references in Simple expressions like
${header.oldName} → ${header.newName}. " +
- "Only migrates expressions inside simple() method calls.";
+ return "Renames header references in Simple expressions like
${header.oldName} → ${header.newName}, " +
+ "in every string literal carrying a Simple expression:
simple(), log(), endpoint URIs and the like. " +
+ "Only the complete ${header.oldName} placeholder is matched, so
plain occurrences of the name are left alone.";
}
@Override
@@ -75,58 +78,48 @@ public class RenameHeaderInSimpleExpression extends Recipe {
}
private static class SimpleExpressionVisitor extends
AbstractCamelJavaVisitor {
- private final String oldHeaderName;
- private final String newHeaderName;
private final Pattern headerPattern;
private final Pattern headersPattern;
+ private final String replacement;
SimpleExpressionVisitor(String oldHeaderName, String newHeaderName) {
- this.oldHeaderName = oldHeaderName;
- this.newHeaderName = newHeaderName;
-
// Escape dots in header name for regex, but keep them in the
pattern
String escapedOldName = Pattern.quote(oldHeaderName);
// Match ${header.oldName} or ${headers.oldName}
this.headerPattern = Pattern.compile("(\\$\\{header\\.)" +
escapedOldName + "(\\})");
this.headersPattern = Pattern.compile("(\\$\\{headers\\.)" +
escapedOldName + "(\\})");
+ this.replacement = "$1" + Matcher.quoteReplacement(newHeaderName)
+ "$2";
}
@Override
- protected J.MethodInvocation
doVisitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
- J.MethodInvocation mi = super.doVisitMethodInvocation(method, ctx);
-
- // Check if this is a simple() method call (any class, method name
"simple")
- if (mi.getSimpleName().equals("simple")) {
- // Get the first argument (the Simple expression string)
- if (!mi.getArguments().isEmpty() && mi.getArguments().get(0)
instanceof J.Literal) {
- J.Literal literal = (J.Literal) mi.getArguments().get(0);
-
- if (literal.getValue() instanceof String) {
- String expression = (String) literal.getValue();
- String newExpression = expression;
-
- // Replace ${header.oldName} with ${header.newName}
- newExpression =
headerPattern.matcher(newExpression).replaceAll("$1" + newHeaderName + "$2");
+ protected J.Literal doVisitLiteral(J.Literal literal, ExecutionContext
ctx) {
+ J.Literal l = super.doVisitLiteral(literal, ctx);
- // Replace ${headers.oldName} with ${headers.newName}
- newExpression =
headersPattern.matcher(newExpression).replaceAll("$1" + newHeaderName + "$2");
+ if (!(l.getValue() instanceof String)) {
+ return l;
+ }
- // If changed, update the literal
- if (!expression.equals(newExpression)) {
- J.Literal newLiteral =
literal.withValue(newExpression)
- .withValueSource("\""
+ newExpression + "\"");
+ String expression = (String) l.getValue();
+ String newExpression = rename(expression);
+ if (expression.equals(newExpression)) {
+ return l;
+ }
-
java.util.List<org.openrewrite.java.tree.Expression> newArgs = new
java.util.ArrayList<>(mi.getArguments());
- newArgs.set(0, newLiteral);
+ l = l.withValue(newExpression);
- return mi.withArguments(newArgs);
- }
- }
- }
+ // The placeholder needs no escaping, so the same replacement can
be applied to the
+ // source representation, which keeps the original quoting style
intact
+ if (l.getValueSource() != null) {
+ l = l.withValueSource(rename(l.getValueSource()));
}
- return mi;
+ return l;
+ }
+
+ private String rename(String value) {
+ String renamed =
headerPattern.matcher(value).replaceAll(replacement);
+ return headersPattern.matcher(renamed).replaceAll(replacement);
}
}
}
diff --git
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDsl.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDsl.java
index 0f889cd..d71e8b0 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDsl.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDsl.java
@@ -17,16 +17,23 @@
package org.apache.camel.upgrade.camel418_3;
import org.apache.camel.upgrade.AbstractCamelXmlVisitor;
+import org.apache.camel.upgrade.RecipesUtil;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Option;
+import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.marker.Markers;
import org.openrewrite.xml.tree.Xml;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
- * Renames header references in XML DSL <setHeader name="..."> and <header
name="..."> elements.
+ * Renames header references in XML DSL <setHeader name="..."> and <header
name="..."> elements,
+ * and in the Simple expressions carried by element text and attribute values.
*/
public class RenameHeaderInXmlDsl extends Recipe {
@@ -64,21 +71,31 @@ public class RenameHeaderInXmlDsl extends Recipe {
@Override
public String getDescription() {
return "Renames header references in XML DSL <setHeader name=\"...\">,
<header name=\"...\">, " +
- "and <removeHeader name=\"...\"> elements.";
+ "and <removeHeader name=\"...\"> elements, and the
${header.oldName} placeholder wherever it " +
+ "appears in element text (<simple>) or in an attribute value.";
}
@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
- return new XmlHeaderVisitor(oldHeaderName, newHeaderName);
+ return Preconditions.check(RecipesUtil.camelXmlDslPrecondition(),
+ new XmlHeaderVisitor(oldHeaderName,
newHeaderName));
}
private static class XmlHeaderVisitor extends AbstractCamelXmlVisitor {
private final String oldHeaderName;
private final String newHeaderName;
+ private final Pattern headerPattern;
+ private final Pattern headersPattern;
+ private final String replacement;
XmlHeaderVisitor(String oldHeaderName, String newHeaderName) {
this.oldHeaderName = oldHeaderName;
this.newHeaderName = newHeaderName;
+
+ String escapedOldName = Pattern.quote(oldHeaderName);
+ this.headerPattern = Pattern.compile("(\\$\\{header\\.)" +
escapedOldName + "(\\})");
+ this.headersPattern = Pattern.compile("(\\$\\{headers\\.)" +
escapedOldName + "(\\})");
+ this.replacement = "$1" + Matcher.quoteReplacement(newHeaderName)
+ "$2";
}
@Override
@@ -87,27 +104,54 @@ public class RenameHeaderInXmlDsl extends Recipe {
// Check if this is a setHeader, header, or removeHeader tag
String tagName = t.getName();
- if ("setHeader".equals(tagName) || "header".equals(tagName) ||
"removeHeader".equals(tagName)) {
- // Look for the "name" attribute with oldHeaderName value
- return t.withAttributes(ListUtils.map(t.getAttributes(), attr
-> {
- if ("name".equals(attr.getKeyAsString()) &&
- oldHeaderName.equals(attr.getValueAsString())) {
- // Replace with new header name
- return attr.withValue(
- new Xml.Attribute.Value(
- attr.getValue().getId(),
- "",
- Markers.EMPTY,
- attr.getValue().getQuote(),
- newHeaderName
- )
- );
- }
+ boolean headerTag = "setHeader".equals(tagName) ||
"header".equals(tagName) || "removeHeader".equals(tagName);
+
+ t = t.withAttributes(ListUtils.map(t.getAttributes(), attr -> {
+ String value = attr.getValueAsString();
+ if (value == null) {
return attr;
- }));
+ }
+
+ // The "name" attribute of a header element holds the header
name itself
+ if (headerTag && "name".equals(attr.getKeyAsString()) &&
oldHeaderName.equals(value)) {
+ return withValue(attr, newHeaderName);
+ }
+
+ // Any other attribute may carry a Simple expression, e.g.
<log message="${header.x}"/>
+ String renamed = rename(value);
+ return value.equals(renamed) ? attr : withValue(attr, renamed);
+ }));
+
+ // Element text holds Simple expressions too, e.g.
<simple>${header.x}</simple>.
+ // Only leaf elements have text content of their own.
+ if (t.getChildren().isEmpty()) {
+ Optional<String> value = t.getValue();
+ if (value.isPresent()) {
+ String renamed = rename(value.get());
+ if (!value.get().equals(renamed)) {
+ t = t.withValue(renamed);
+ }
+ }
}
return t;
}
+
+ private static Xml.Attribute withValue(Xml.Attribute attr, String
newValue) {
+ return attr.withValue(
+ new Xml.Attribute.Value(
+ attr.getValue().getId(),
+ "",
+ Markers.EMPTY,
+ attr.getValue().getQuote(),
+ newValue
+ )
+ );
+ }
+
+ private String rename(String value) {
+ String renamed =
headerPattern.matcher(value).replaceAll(replacement);
+ return headersPattern.matcher(renamed).replaceAll(replacement);
+ }
}
}
diff --git
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDsl.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDsl.java
index ff6ea84..9429c07 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDsl.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDsl.java
@@ -25,8 +25,12 @@ import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.yaml.tree.Yaml;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
- * Renames header references in YAML DSL setHeader.name, header.name, and
removeHeader.name entries.
+ * Renames header references in YAML DSL setHeader.name, header.name, and
removeHeader.name entries,
+ * and in the Simple expressions carried by scalar values.
*/
public class RenameHeaderInYamlDsl extends Recipe {
@@ -63,7 +67,8 @@ public class RenameHeaderInYamlDsl extends Recipe {
@Override
public String getDescription() {
- return "Renames header references in YAML DSL setHeader.name,
header.name, and removeHeader.name entries.";
+ return "Renames header references in YAML DSL setHeader.name,
header.name, and removeHeader.name entries, " +
+ "and the ${header.oldName} placeholder wherever it appears in a
scalar value.";
}
@Override
@@ -75,10 +80,18 @@ public class RenameHeaderInYamlDsl extends Recipe {
private static class YamlHeaderVisitor extends AbstractCamelYamlVisitor {
private final String oldHeaderName;
private final String newHeaderName;
+ private final Pattern headerPattern;
+ private final Pattern headersPattern;
+ private final String replacement;
YamlHeaderVisitor(String oldHeaderName, String newHeaderName) {
this.oldHeaderName = oldHeaderName;
this.newHeaderName = newHeaderName;
+
+ String escapedOldName = Pattern.quote(oldHeaderName);
+ this.headerPattern = Pattern.compile("(\\$\\{header\\.)" +
escapedOldName + "(\\})");
+ this.headersPattern = Pattern.compile("(\\$\\{headers\\.)" +
escapedOldName + "(\\})");
+ this.replacement = "$1" + Matcher.quoteReplacement(newHeaderName)
+ "$2";
}
@Override
@@ -103,9 +116,23 @@ public class RenameHeaderInYamlDsl extends Recipe {
}
}
+ // Any scalar may carry a Simple expression, e.g. simple:
"${header.x}"
+ if (e.getValue() instanceof Yaml.Scalar) {
+ Yaml.Scalar scalarValue = (Yaml.Scalar) e.getValue();
+ String renamed = rename(scalarValue.getValue());
+ if (!scalarValue.getValue().equals(renamed)) {
+ return e.withValue(scalarValue.withValue(renamed));
+ }
+ }
+
return e;
}
+ private String rename(String value) {
+ String renamed =
headerPattern.matcher(value).replaceAll(replacement);
+ return headersPattern.matcher(renamed).replaceAll(replacement);
+ }
+
/**
* Check if this entry is within a setHeader, header, or removeHeader
mapping.
*/
diff --git
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel46/XmlDsl46Recipe.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel46/XmlDsl46Recipe.java
index 137a0b5..4040fa9 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel46/XmlDsl46Recipe.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/camel46/XmlDsl46Recipe.java
@@ -17,8 +17,10 @@
package org.apache.camel.upgrade.camel46;
import org.apache.camel.upgrade.AbstractCamelXmlVisitor;
+import org.apache.camel.upgrade.RecipesUtil;
import org.jspecify.annotations.Nullable;
import org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.xml.XPathMatcher;
@@ -51,7 +53,7 @@ public class XmlDsl46Recipe extends Recipe {
@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
- return new AbstractCamelXmlVisitor() {
+ return Preconditions.check(RecipesUtil.camelXmlDslPrecondition(), new
AbstractCamelXmlVisitor() {
@Override
public Xml.@Nullable Tag doVisitTag(final Xml.Tag tag, final
ExecutionContext ctx) {
@@ -88,6 +90,6 @@ public class XmlDsl46Recipe extends Recipe {
return t;
}
- };
+ });
}
}
diff --git
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ReplacePropertyInComponentYaml.java
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ReplacePropertyInComponentYaml.java
index 37c4747..1cfc6f3 100644
---
a/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ReplacePropertyInComponentYaml.java
+++
b/camel-upgrade-recipes/src/main/java/org/apache/camel/upgrade/customRecipes/ReplacePropertyInComponentYaml.java
@@ -80,7 +80,8 @@ public class ReplacePropertyInComponentYaml extends Recipe {
@Override
public String getDescription() {
- return "ARenames property of the component.";
+ return "Renames a property of the component in the YAML DSL, both in
the parameters mapping and " +
+ "when the property is inlined in the endpoint uri.";
}
@Override
@@ -124,6 +125,16 @@ public class ReplacePropertyInComponentYaml extends Recipe
{
}
}
+ // The same options can be inlined in the uri, e.g. uri:
"netty-http:https://host/path?keyStoreFile=..."
+ if (valuePrefix != null && "uri".equals(e.getKey().getValue())
&& e.getValue() instanceof Yaml.Scalar) {
+ Yaml.Scalar uriScalar = (Yaml.Scalar) e.getValue();
+ String newUri =
RecipesUtil.replacePropertyInUrl(uriScalar.getValue(), component,
oldPropertyKey,
+ newPropertyKey, valuePrefix);
+ if (newUri != null) {
+ return e.withValue(uriScalar.withValue(newUri));
+ }
+ }
+
return e;
}
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
index 075e4b2..81ea9ad 100644
--- 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
@@ -33,7 +33,6 @@ recipeList:
- 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
@@ -130,20 +129,6 @@ recipeList:
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
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate415Test.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate415Test.java
index c9deab9..177b921 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate415Test.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate415Test.java
@@ -410,6 +410,30 @@ public class CamelUpdate415Test implements RewriteTest {
/**
* <a
href="https://camel.apache.org/manual/camel-4x-upgrade-guide-4_15.html#_data_formats">Data
Formats</a> in DSL
*/
+ @Test
+ void nettyKeyStoreInlineUriTestYaml() {
+ //language=yaml
+ rewriteRun(yaml(
+ """
+ - route:
+ id: route-3277
+ from:
+ uri: "netty-http:tcp:12345?keyStoreFile=/testFile"
+ steps:
+ - to:
+ uri: "netty:tcp:12346?trustStoreFile=/testFile"
+ """,
+ """
+ - route:
+ id: route-3277
+ from:
+ uri:
"netty-http:tcp:12345?keyStoreResource=file:/testFile"
+ steps:
+ - to:
+ uri:
"netty:tcp:12346?trustStoreResource=file:/testFile"
+ """));
+ }
+
@Test
void nettyKeyStoreTestYaml() {
//language=yaml
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
index b87305e..a2fdd95 100644
---
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
@@ -34,7 +34,7 @@ public class CamelUpdate422Test implements RewriteTest {
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"))
+ "jakarta.xml.bind-api"))
.typeValidationOptions(TypeValidation.none())
.expectedCyclesThatMakeChanges(1);
}
@@ -260,36 +260,6 @@ public class CamelUpdate422Test implements RewriteTest {
);
}
- @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() {
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate46Test.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate46Test.java
index 165ea32..0d2b1c2 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate46Test.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/CamelUpdate46Test.java
@@ -157,6 +157,19 @@ public class CamelUpdate46Test implements RewriteTest {
"""));
}
+ @Test
+ void xmlPropertiesNotMigratedInSpringBeans() {
+ //language=xml
+ rewriteRun(xml(
+ """
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="beanFromProps" class="com.acme.MyBean">
+ <property name="msg1" value="messageString1"/>
+ </bean>
+ </beans>
+ """));
+ }
+
@DisabledIfSystemProperty(named = CamelTestUtil.PROPERTY_USE_RECIPE,
matches = ".+")
@Test
void renamedDependencies() {
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethodTest.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethodTest.java
index ea0e286..b656d1c 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethodTest.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInJavaMethodTest.java
@@ -251,4 +251,36 @@ public class RenameHeaderInJavaMethodTest implements
RewriteTest {
)
);
}
+
+ @Test
+ void headerPredicateMigration() {
+ //language=java
+ rewriteRun(
+ java(
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .filter(header("kafka.TOPIC").isEqualTo("orders"))
+ .to("mock:result");
+ }
+ }
+ """,
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+
.filter(header("CamelKafkaTopic").isEqualTo("orders"))
+ .to("mock:result");
+ }
+ }
+ """
+ )
+ );
+ }
+
}
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpressionTest.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpressionTest.java
index b41ecdf..4a6ccd9 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpressionTest.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInSimpleExpressionTest.java
@@ -184,7 +184,7 @@ public class RenameHeaderInSimpleExpressionTest implements
RewriteTest {
}
@Test
- void doesNotMigrateNonSimpleStrings() {
+ void migratesSimpleExpressionHeldInAVariable() {
//language=java
rewriteRun(
java(
@@ -193,12 +193,23 @@ public class RenameHeaderInSimpleExpressionTest
implements RewriteTest {
class Test extends RouteBuilder {
public void configure() {
- String expression = "${header.kafka.TOPIC}"; // Not
inside simple() call
- System.out.println("Expression:
${header.kafka.TOPIC}");
+ String expression = "${header.kafka.TOPIC}";
+ from("direct:start")
+ .setBody(simple(expression));
+ }
+ }
+ """,
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ String expression = "${header.CamelKafkaTopic}";
+ from("direct:start")
+ .setBody(simple(expression));
}
}
"""
- // No change expected
)
);
}
@@ -242,4 +253,82 @@ public class RenameHeaderInSimpleExpressionTest implements
RewriteTest {
)
);
}
+
+ @Test
+ void logMessageMigration() {
+ //language=java
+ rewriteRun(
+ java(
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .log("topic is ${header.kafka.TOPIC}");
+ }
+ }
+ """,
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .log("topic is ${header.CamelKafkaTopic}");
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void endpointUriMigration() {
+ //language=java
+ rewriteRun(
+ java(
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .toD("mock:${header.kafka.TOPIC}");
+ }
+ }
+ """,
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .toD("mock:${header.CamelKafkaTopic}");
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void plainOccurrenceOfTheNameIsLeftAlone() {
+ //language=java
+ rewriteRun(
+ java(
+ """
+ import org.apache.camel.builder.RouteBuilder;
+
+ class Test extends RouteBuilder {
+ public void configure() {
+ from("direct:start")
+ .log("kafka.TOPIC and
${header.kafka.TOPIC.suffix}");
+ }
+ }
+ """
+ )
+ );
+ }
+
}
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDslTest.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDslTest.java
index a57d7fd..2b17611 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDslTest.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInXmlDslTest.java
@@ -201,4 +201,105 @@ public class RenameHeaderInXmlDslTest implements
RewriteTest {
)
);
}
+
+ @Test
+ void simpleExpressionInElementTextMigration() {
+ //language=xml
+ rewriteRun(
+ xml(
+ """
+ <routes xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start"/>
+ <setBody>
+ <simple>${header.kafka.TOPIC}</simple>
+ </setBody>
+ </route>
+ </routes>
+ """,
+ """
+ <routes xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start"/>
+ <setBody>
+ <simple>${header.CamelKafkaTopic}</simple>
+ </setBody>
+ </route>
+ </routes>
+ """
+ )
+ );
+ }
+
+ @Test
+ void simpleExpressionInAttributeMigration() {
+ //language=xml
+ rewriteRun(
+ xml(
+ """
+ <routes xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start"/>
+ <log message="topic is ${header.kafka.TOPIC}"/>
+ </route>
+ </routes>
+ """,
+ """
+ <routes xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start"/>
+ <log message="topic is ${header.CamelKafkaTopic}"/>
+ </route>
+ </routes>
+ """
+ )
+ );
+ }
+
+
+ @Test
+ void doesNotMigrateNonCamelXml() {
+ //language=xml
+ rewriteRun(
+ xml(
+ """
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="example" class="com.example.Example">
+ <property name="topic" value="${header.kafka.TOPIC}"/>
+ </bean>
+ </beans>
+ """
+ )
+ );
+ }
+
+ @Test
+ void migratesCamelRoutesNestedInBeans() {
+ //language=xml
+ rewriteRun(
+ xml(
+ """
+ <beans>
+ <route>
+ <from uri="direct:start"/>
+ <setHeader name="kafka.TOPIC">
+ <constant>my-topic</constant>
+ </setHeader>
+ </route>
+ </beans>
+ """,
+ """
+ <beans>
+ <route>
+ <from uri="direct:start"/>
+ <setHeader name="CamelKafkaTopic">
+ <constant>my-topic</constant>
+ </setHeader>
+ </route>
+ </beans>
+ """
+ )
+ );
+ }
+
}
diff --git
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDslTest.java
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDslTest.java
index 242daa9..e7dbec0 100644
---
a/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDslTest.java
+++
b/camel-upgrade-recipes/src/test/java/org/apache/camel/upgrade/camel418_3/RenameHeaderInYamlDslTest.java
@@ -232,4 +232,32 @@ public class RenameHeaderInYamlDslTest implements
RewriteTest {
)
);
}
+
+ @Test
+ void simpleExpressionInScalarMigration() {
+ //language=yaml
+ rewriteRun(
+ yaml(
+ """
+ - route:
+ from:
+ uri: "direct:start"
+ steps:
+ - setBody:
+ simple: "${header.kafka.TOPIC}"
+ - log: "topic is ${header.kafka.TOPIC}"
+ """,
+ """
+ - route:
+ from:
+ uri: "direct:start"
+ steps:
+ - setBody:
+ simple: "${header.CamelKafkaTopic}"
+ - log: "topic is ${header.CamelKafkaTopic}"
+ """
+ )
+ );
+ }
+
}
diff --git a/release_notes.adoc b/release_notes.adoc
index 04d4daa..d523aa6 100644
--- a/release_notes.adoc
+++ b/release_notes.adoc
@@ -27,8 +27,8 @@ The following table lists migration topics and indicates the
level of coverage (
| 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)
+| ❌ None
+| No migration is required. The change is to the `javaType` declared in the
component metadata for the `CamelOpenAIResponse` exchange property; the runtime
type was always the nested SDK class. `com.openai.models.ChatCompletion` exists
only in openai-java 0.8.1, while every `camel-openai` release ships 4.13.0 or
newer, so no project can hold the old import
|
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