This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new b9b31e7b6a6d CAMEL-25320: camel-core - the separator of
@PropertyInject is a plain string, not a regular expression (#27396)
b9b31e7b6a6d is described below
commit b9b31e7b6a6d0f10efcb3f035e22426b5dde9334
Author: allthingssecurity <[email protected]>
AuthorDate: Tue Oct 6 14:51:46 2026 +0530
CAMEL-25320: camel-core - the separator of @PropertyInject is a plain
string, not a regular expression (#27396)
* CAMEL-25320: camel-core - the separator of @PropertyInject is a plain
string, not a regular expression
@PropertyInject split the property value into an array, a collection or a
map
with String.split(separator), which takes a regular expression. A separator
such as | split the value into single characters (and a map value could not
be converted), and . gave no values at all.
Quote the separator.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* CAMEL-25320: camel-core - Mark the separator change as breaking and say
in the javadoc that it is a plain string
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../main/java/org/apache/camel/PropertyInject.java | 2 +-
.../impl/engine/CamelPostProcessorHelper.java | 12 ++-
.../impl/engine/PropertyInjectSeparatorTest.java | 103 +++++++++++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 9 ++
4 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/core/camel-api/src/main/java/org/apache/camel/PropertyInject.java
b/core/camel-api/src/main/java/org/apache/camel/PropertyInject.java
index 915880e39087..32d800687643 100644
--- a/core/camel-api/src/main/java/org/apache/camel/PropertyInject.java
+++ b/core/camel-api/src/main/java/org/apache/camel/PropertyInject.java
@@ -43,7 +43,7 @@ public @interface PropertyInject {
/**
* Used for splitting the property value into an array/list of values. For
example to use comma to separate the
- * values.
+ * values. The separator is a plain string, not a regular expression.
*/
String separator() default "";
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelPostProcessorHelper.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelPostProcessorHelper.java
index fd242b6ab0ac..471dcc499865 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelPostProcessorHelper.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelPostProcessorHelper.java
@@ -28,6 +28,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.regex.Pattern;
import org.apache.camel.BeanConfigInject;
import org.apache.camel.BeanInject;
@@ -333,6 +334,11 @@ public class CamelPostProcessorHelper implements
CamelContextAware {
}
}
+ private static String[] splitUsingSeparator(String value, String
separator) {
+ // the separator is a plain string, not a regular expression
+ return value.split(Pattern.quote(separator));
+ }
+
private static Map<String, Object> convertMapUsingSeparator(
CamelContext camelContext, Type genericType, String value, String
separator)
throws NoTypeConversionAvailableException {
@@ -348,7 +354,7 @@ public class CamelPostProcessorHelper implements
CamelContextAware {
}
}
Map<String, Object> values = new LinkedHashMap<>();
- String[] arr = value.split(separator);
+ String[] arr = splitUsingSeparator(value, separator);
for (String s : arr) {
String v = s.trim(); // trim values as user may have whitespace
noise
if (v.contains("=")) {
@@ -375,7 +381,7 @@ public class CamelPostProcessorHelper implements
CamelContextAware {
}
boolean set = type.isAssignableFrom(Set.class);
Collection<Object> values = set ? new LinkedHashSet<>() : new
ArrayList<>();
- String[] arr = value.split(separator);
+ String[] arr = splitUsingSeparator(value, separator);
for (String s : arr) {
String v = s.trim(); // trim values as user may have whitespace
noise
values.add(camelContext.getTypeConverter().mandatoryConvertTo(ct,
v));
@@ -385,7 +391,7 @@ public class CamelPostProcessorHelper implements
CamelContextAware {
private static Object[] convertArrayUsingSeparator(CamelContext
camelContext, Class<?> type, String value, String separator)
throws NoTypeConversionAvailableException {
- String[] arr = value.split(separator);
+ String[] arr = splitUsingSeparator(value, separator);
Object[] values = new Object[arr.length];
Class<?> ct = type.getComponentType();
for (int i = 0; i < arr.length; i++) {
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/PropertyInjectSeparatorTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/PropertyInjectSeparatorTest.java
new file mode 100644
index 000000000000..1b4a1902fa44
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/PropertyInjectSeparatorTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.impl.engine;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.PropertyInject;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * The separator of {@link PropertyInject} splits the property value: it is a
separator, not a regular expression.
+ */
+class PropertyInjectSeparatorTest extends ContextTestSupport {
+
+ private final Properties myProp = new Properties();
+
+ @Override
+ protected Registry createCamelRegistry() throws Exception {
+ Registry jndi = super.createCamelRegistry();
+ jndi.bind("myProp", myProp);
+ return jndi;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.getPropertiesComponent().setLocation("ref:myProp");
+ return context;
+ }
+
+ @Test
+ void pipeSeparatedList() throws Exception {
+ myProp.put("hosts", "serverA|serverB");
+
+ assertEquals(List.of("serverA", "serverB"), inject("hosts"));
+ }
+
+ @Test
+ void dotSeparatedArray() throws Exception {
+ myProp.put("parts", "a.b.c");
+
+ assertEquals(List.of("a", "b", "c"), Arrays.asList((Object[])
inject("parts")));
+ }
+
+ @Test
+ void pipeSeparatedMap() throws Exception {
+ myProp.put("servers", "serverA=4444|serverB=5555");
+
+ assertEquals(Map.of("serverA", 4444, "serverB", 5555),
inject("servers"));
+ }
+
+ @Test
+ void semicolonSeparatedList() throws Exception {
+ myProp.put("ports", "4444;5555");
+
+ assertEquals(List.of(4444, 5555), inject("ports"));
+ }
+
+ private Object inject(String fieldName) throws Exception {
+ Field field = MyBean.class.getField(fieldName);
+ PropertyInject propertyInject =
field.getAnnotation(PropertyInject.class);
+ return new
CamelPostProcessorHelper(context).getInjectionPropertyValue(field.getType(),
field.getGenericType(),
+ propertyInject.value(), "", propertyInject.separator());
+ }
+
+ public static class MyBean {
+
+ @PropertyInject(value = "hosts", separator = "|")
+ public List<String> hosts;
+
+ @PropertyInject(value = "parts", separator = ".")
+ public String[] parts;
+
+ @PropertyInject(value = "servers", separator = "|")
+ public Map<String, Integer> servers;
+
+ @PropertyInject(value = "ports", separator = ";")
+ public List<Integer> ports;
+ }
+}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 93dfb7d63f0f..03ddbbe59e7c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -181,6 +181,15 @@ This can break an application that has such an invalid
value configured and work
good enough, as it now fails when starting. To keep the previous result,
correct the configured value, or remove the
property so the `defaultValue` is used.
+=== @PropertyInject - the separator is a plain string (Breaking change)
+
+The `separator` of `@PropertyInject`, which splits the value into an array, a
collection or a map, was used as a
+regular expression: a separator such as `|` split the value into single
characters, and `.` gave no values at all.
+It is now a plain string, as documented ("for example to use comma to separate
the values"). An application that
+escaped a separator to work around this (for example `separator = "\\|"`) must
now use the separator itself
+(`separator = "|"`). A separator that relied on a regular expression (such as
`+separator = "\\s*;\\s*"+`) is no
+longer supported; use the plain separator (the values are trimmed).
+
=== Aggregate EIP - optimistic locking retry delay
When optimistic locking is enabled without configuring an
`optimisticLockRetryPolicy`, the retry delay between