This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/CAMEL-25366 in repository https://gitbox.apache.org/repos/asf/camel.git
commit d520057508cecfd412b89bf96ee7a8a4af2fc2c0 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Oct 6 08:11:24 2026 +0200 CAMEL-25366: camel-core - Type converter from String or Number to BigDecimal There was no type converter to BigDecimal, so converting the String "1000.01" returned null and simple ${bodyAs(java.math.BigDecimal)}, ${convertTo(${body}, java.math.BigDecimal)} and resultType BigDecimal were empty. Add toBigDecimal next to toBigInteger; a double or float is converted from its decimal text. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../converter/CamelBaseBulkConverterLoader.java | 16 ++++++++++++- .../apache/camel/converter/ObjectConverter.java | 26 ++++++++++++++++++++++ .../camel/converter/ObjectConverterTest.java | 17 ++++++++++++++ .../apache/camel/language/simple/SimpleTest.java | 10 +++++++++ .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 4 ++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/core/camel-base/src/generated/java/org/apache/camel/converter/CamelBaseBulkConverterLoader.java b/core/camel-base/src/generated/java/org/apache/camel/converter/CamelBaseBulkConverterLoader.java index 5fd9e96156ac..ff3ecc3fad1a 100644 --- a/core/camel-base/src/generated/java/org/apache/camel/converter/CamelBaseBulkConverterLoader.java +++ b/core/camel-base/src/generated/java/org/apache/camel/converter/CamelBaseBulkConverterLoader.java @@ -41,7 +41,7 @@ public final class CamelBaseBulkConverterLoader implements TypeConverterLoader, @Override public int size() { - return 129; + return 130; } @Override @@ -371,6 +371,15 @@ public final class CamelBaseBulkConverterLoader implements TypeConverterLoader, if (value instanceof java.lang.StringBuilder) { return org.apache.camel.converter.ObjectConverter.toString((java.lang.StringBuilder) value); } + } else if (to == java.math.BigDecimal.class) { + if (value instanceof java.lang.Object) { + Object obj = org.apache.camel.converter.ObjectConverter.toBigDecimal(value); + if (obj == null) { + return Void.class; + } else { + return obj; + } + } } else if (to == java.math.BigInteger.class) { if (value instanceof java.lang.Object) { Object obj = org.apache.camel.converter.ObjectConverter.toBigInteger(value); @@ -612,6 +621,7 @@ public final class CamelBaseBulkConverterLoader implements TypeConverterLoader, registry.addConverter(new TypeConvertible<>(java.lang.StringBuffer.class, java.lang.String.class), this); registry.addConverter(new TypeConvertible<>(java.io.ByteArrayOutputStream.class, java.lang.String.class), this); registry.addConverter(new TypeConvertible<>(java.lang.StringBuilder.class, java.lang.String.class), this); + registry.addConverter(new TypeConvertible<>(java.lang.Object.class, java.math.BigDecimal.class), this); registry.addConverter(new TypeConvertible<>(java.lang.Object.class, java.math.BigInteger.class), this); registry.addConverter(new TypeConvertible<>(java.lang.CharSequence.class, java.net.URI.class), this); registry.addConverter(new TypeConvertible<>(byte[].class, java.nio.ByteBuffer.class), this); @@ -944,6 +954,10 @@ public final class CamelBaseBulkConverterLoader implements TypeConverterLoader, if (from == java.lang.StringBuilder.class) { return this; } + } else if (to == java.math.BigDecimal.class) { + if (from == java.lang.Object.class) { + return this; + } } else if (to == java.math.BigInteger.class) { if (from == java.lang.Object.class) { return this; diff --git a/core/camel-base/src/main/java/org/apache/camel/converter/ObjectConverter.java b/core/camel-base/src/main/java/org/apache/camel/converter/ObjectConverter.java index 9c3bc24cfde7..c06ed01e9a4d 100644 --- a/core/camel-base/src/main/java/org/apache/camel/converter/ObjectConverter.java +++ b/core/camel-base/src/main/java/org/apache/camel/converter/ObjectConverter.java @@ -353,4 +353,30 @@ public final class ObjectConverter { return toNumber(str); } + /** + * Returns the converted value, or null if the value is null + */ + @Converter(order = 41, allowNull = true) + public static BigDecimal toBigDecimal(Object value) { + if (org.apache.camel.util.ObjectHelper.isNaN(value)) { + return null; + } + if (value instanceof String str) { + return new BigDecimal(str); + } + + if (value instanceof BigDecimal bd) { + return bd; + } else if (value instanceof BigInteger bi) { + return new BigDecimal(bi); + } else if (value instanceof Double || value instanceof Float) { + // use the decimal text of the value, as the binary value of 0.1 is not exactly 0.1 + return new BigDecimal(value.toString()); + } else if (value instanceof Number number) { + return BigDecimal.valueOf(number.longValue()); + } else { + return null; + } + } + } diff --git a/core/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java b/core/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java index e818aee68263..28b68040aef8 100644 --- a/core/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/converter/ObjectConverterTest.java @@ -153,6 +153,23 @@ public class ObjectConverterTest { assertEquals(BigInteger.ONE, ObjectConverter.toBigInteger(1.9d)); } + @Test + public void testToBigDecimal() { + assertEquals(new BigDecimal("1000.01"), ObjectConverter.toBigDecimal("1000.01")); + assertEquals(new BigDecimal("4"), ObjectConverter.toBigDecimal("4")); + assertEquals(BigDecimal.valueOf(4), ObjectConverter.toBigDecimal(Integer.valueOf("4"))); + assertEquals(BigDecimal.valueOf(4), ObjectConverter.toBigDecimal(Long.valueOf("4"))); + assertEquals(new BigDecimal("14350442579497085228"), + ObjectConverter.toBigDecimal(new BigInteger("14350442579497085228"))); + // the decimal text of the value, not the exact binary value of the double or float + assertEquals(new BigDecimal("0.1"), ObjectConverter.toBigDecimal(0.1d)); + assertEquals(new BigDecimal("0.1"), ObjectConverter.toBigDecimal(0.1f)); + assertNull(ObjectConverter.toBigDecimal(new Date())); + assertNull(ObjectConverter.toBigDecimal(Double.NaN)); + assertNull(ObjectConverter.toBigDecimal(Float.NaN)); + assertThrows(NumberFormatException.class, () -> ObjectConverter.toBigDecimal("abc")); + } + @Test public void testToString() { assertEquals("ABC", ObjectConverter.toString(new StringBuffer("ABC"))); diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java index 67f3b96d87de..3e29ee9a5e56 100644 --- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java @@ -19,6 +19,7 @@ package org.apache.camel.language.simple; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.ArrayList; @@ -679,6 +680,15 @@ public class SimpleTest extends LanguageTestSupport { assertIsInstanceOf(ClassNotFoundException.class, e.getCause()); } + @Test + public void testBodyAsBigDecimal() { + exchange.getIn().setBody("1000.01"); + assertExpression("${bodyAs(java.math.BigDecimal)}", new BigDecimal("1000.01")); + assertExpression("${convertTo(${body}, java.math.BigDecimal)}", new BigDecimal("1000.01")); + Expression expression = context.resolveLanguage("simple").createExpression("${body}"); + assertEquals(new BigDecimal("1000.01"), expression.evaluate(exchange, BigDecimal.class)); + } + @Test public void testMandatoryBodyAs() { assertExpression("${mandatoryBodyAs(String)}", "<hello id='m123'>world!</hello>"); 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 0eaa9c32cd09..f944390839d6 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 @@ -1283,6 +1283,10 @@ interfaces are tried before the super class at each level, and `java.lang.Object * Converting a `String` to a `Number` now returns an `Integer` for all values within the `Integer` range (including `Integer.MAX_VALUE`, which returned a `Long` before), and supports exponent notation such as `1e5`. * Converting a `BigDecimal`, or a `double` larger than a `long`, to `BigInteger` no longer loses precision. +* A `String` or a `Number` can now be converted to `BigDecimal`. There was no such type converter before, so the +conversion returned `null`: `${bodyAs(java.math.BigDecimal)}` was empty for a body of `"1000.01"`, and a bean method +with a `BigDecimal` parameter could not be called with a `String` body. A `double` or `float` is converted from its +decimal text, so `0.1` becomes `0.1`. * Converting a `byte[]` to `char` no longer sign-extends bytes above 127. * Converting a `String` to `ByteBuffer` now uses the charset from the `CamelCharsetName` header or exchange property (like the other converters), and falls back to the default charset.
