From 2a290bbcd258ff279a5a33d1bff486abe42147e9 Mon Sep 17 00:00:00 2001 From: Kush Batra Date: Fri, 17 Oct 2025 16:04:49 -0400 Subject: [PATCH 1/2] fix: flagsmith string to double conversion issue (#1557) --- .../FlagsmithProvider.java | 33 ++++++++++++++++--- .../FlagsmithProviderTest.java | 18 ++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java b/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java index 47a5bf0f8..91755a204 100644 --- a/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java +++ b/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java @@ -180,19 +180,42 @@ private ProviderEvaluation buildEvaluation( * @param expectedType the type we expect for this value * @param the type we want to convert to * @return A converted object + * @throws TypeMismatchError if the value cannot be converted to the expected type */ + @SuppressWarnings("unchecked") private T convertValue(Object value, Class expectedType) { boolean isPrimitive = expectedType == Boolean.class || expectedType == String.class || expectedType == Integer.class || expectedType == Double.class; - T flagValue = isPrimitive ? (T) value : (T) objectToValue(value); - if (flagValue.getClass() != expectedType) { - throw new TypeMismatchError( - "Flag value had an unexpected type " + flagValue.getClass() + ", expected " + expectedType + "."); + Object flagValue; + if (isPrimitive) { + if (expectedType == Double.class) { + if (value instanceof Double) { + flagValue = value; + } else if (value instanceof String) { + try { + flagValue = Double.parseDouble((String) value); + } catch (NumberFormatException e) { + throw new TypeMismatchError("Flag value string could not be parsed as Double: " + value); + } + } else { + throw new TypeMismatchError("Flag value had an unexpected type " + + (value != null ? value.getClass() : "null") + ", expected " + expectedType + "."); + } + } else { + flagValue = value; + } + } else { + flagValue = objectToValue(value); + } + + if (!expectedType.isInstance(flagValue)) { + throw new TypeMismatchError("Flag value had an unexpected type " + + (flagValue != null ? flagValue.getClass() : "null" + ", expected " + expectedType + ".")); } - return flagValue; + return (T) flagValue; } /** diff --git a/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java b/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java index 83e60c0d0..f44cbaf3e 100644 --- a/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java +++ b/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java @@ -159,6 +159,24 @@ void tearDown() throws IOException { mockFlagsmithErrorServer.shutdown(); } + @ParameterizedTest + @MethodSource("convertValueArguments") + void testConvertValue(Object input, Class expectedType, Object expected) throws Exception { + var method = flagsmithProvider.getClass().getDeclaredMethod("convertValue", Object.class, Class.class); + method.setAccessible(true); + Object result = method.invoke(flagsmithProvider, input, expectedType); + assertEquals(expected, result); + } + + private static Stream convertValueArguments() { + return Stream.of( + Arguments.of(true, Boolean.class, true), + Arguments.of("test", String.class, "test"), + Arguments.of(123, Integer.class, 123), + Arguments.of(3.14, Double.class, 3.14), + Arguments.of("3.14", Double.class, 3.14)); + } + @Test void shouldInitializeProviderWhenAllOptionsSet() { HashMap headers = new HashMap() { From deb218fb5b8ddf58e02c156b1bf53327749b423e Mon Sep 17 00:00:00 2001 From: Kush Batra Date: Mon, 27 Oct 2025 12:38:08 -0400 Subject: [PATCH 2/2] Addess review comments (#1557) --- .../FlagsmithProvider.java | 20 +++++++++++++++---- .../FlagsmithProviderTest.java | 4 +++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java b/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java index 91755a204..b3fffa62e 100644 --- a/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java +++ b/providers/flagsmith/src/main/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProvider.java @@ -190,6 +190,8 @@ private T convertValue(Object value, Class expectedType) { || expectedType == Double.class; Object flagValue; + String message = "Flag value had an unexpected type (" + + (value != null ? value.getClass() : "null") + "), expected (" + expectedType + ")."; if (isPrimitive) { if (expectedType == Double.class) { if (value instanceof Double) { @@ -201,8 +203,19 @@ private T convertValue(Object value, Class expectedType) { throw new TypeMismatchError("Flag value string could not be parsed as Double: " + value); } } else { - throw new TypeMismatchError("Flag value had an unexpected type " - + (value != null ? value.getClass() : "null") + ", expected " + expectedType + "."); + throw new TypeMismatchError(message); + } + } else if (expectedType == Integer.class) { + if (value instanceof Integer) { + flagValue = value; + } else if (value instanceof String) { + try { + flagValue = Integer.parseInt((String) value); + } catch (NumberFormatException e) { + throw new TypeMismatchError("Flag value string could not be parsed as Integer: " + value); + } + } else { + throw new TypeMismatchError(message); } } else { flagValue = value; @@ -212,8 +225,7 @@ private T convertValue(Object value, Class expectedType) { } if (!expectedType.isInstance(flagValue)) { - throw new TypeMismatchError("Flag value had an unexpected type " - + (flagValue != null ? flagValue.getClass() : "null" + ", expected " + expectedType + ".")); + throw new TypeMismatchError(message); } return (T) flagValue; } diff --git a/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java b/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java index f44cbaf3e..e1576b9ac 100644 --- a/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java +++ b/providers/flagsmith/src/test/java/dev.openfeature.contrib.providers.flagsmith/FlagsmithProviderTest.java @@ -173,8 +173,10 @@ private static Stream convertValueArguments() { Arguments.of(true, Boolean.class, true), Arguments.of("test", String.class, "test"), Arguments.of(123, Integer.class, 123), + Arguments.of("123", Integer.class, 123), Arguments.of(3.14, Double.class, 3.14), - Arguments.of("3.14", Double.class, 3.14)); + Arguments.of("3.14", Double.class, 3.14) + ); } @Test