Skip to content

Ensure that ConversionService.canConvert(Enum) no longer throws an exception - #34532

Closed
moonfruit wants to merge 1 commit into
spring-projects:mainfrom
moonfruit:to-enum-convert-factory
Closed

Ensure that ConversionService.canConvert(Enum) no longer throws an exception#34532
moonfruit wants to merge 1 commit into
spring-projects:mainfrom
moonfruit:to-enum-convert-factory

Conversation

@moonfruit

@moonfruit moonfruit commented Mar 4, 2025

Copy link
Copy Markdown
Contributor

In my project, I use the following code to find an appropriate method to execute for a given class. It throws an IllegalArgumentException: The target type java.lang.Enum does not refer to an enum when there is a more appropriate “method”: asString(CharSequence).

public class MyTest {

    public static void main(String[] args) throws AccessException {
        EvaluationContext evaluationContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        ReflectiveMethodResolver methodResolver = new ReflectiveMethodResolver();
        MethodExecutor asString = methodResolver.resolve(evaluationContext, MyTest.class, "asString",
                Collections.singletonList(TypeDescriptor.valueOf(String.class)));
        TypedValue result = asString.execute(evaluationContext, MyTest.class, "value");
        System.out.println(result);
    }

    public static String asString(Enum<?> left) {
        return left.name();
    }

    public static String asString(CharSequence left) {
        return left.toString();
    }
}

After doing some research I realized that the root cause was that StringToEnumConverterFactory.getConverter(Enum.class) threw an exception when it couldn't convert and resolve the concrete Enum. This directly causes ConversionService.canConvert(String.class,Enum.class) to throw an exception. I don't think the method canConvert() should throw an exception, it returns true if it can convert and false if it can't. That's what this method is for, to avoid throwing an exception when calling the convert method directly.

So I've modified StringToEnumConverterFactory and IntegerToEnumConverterFactory a little and hopefully this PR will be accepted.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 4, 2025
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Mar 5, 2025
@moonfruit

This comment was marked as outdated.

@sbrannen sbrannen self-assigned this Sep 3, 2026

@sbrannen sbrannen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @moonfruit,

Congratulations on submitting your first PR for the Spring Framework! 👍

And thanks for bringing this to our attention.

I agree that canConvert() ideally should not throw an exception. To address that, I've requested some changes in the PR (see other comments). In addition, let's have IntegerToEnumConverterFactory and StringToEnumConverterFactory implement ConditionalConverter. Their implementations could then look something like this:

	@Override
	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return (ConversionUtils.resolveEnumType(targetType.getType()) != null);
	}

If you feel comfortable making these changes, go for it!

Otherwise, just let me know, and I can take it from here.

Cheers,

Sam

@sbrannen
sbrannen marked this pull request as draft September 6, 2026 19:13
@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue type: enhancement A general enhancement type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on type: enhancement A general enhancement labels Sep 6, 2026
@sbrannen sbrannen added this to the 7.0.10 milestone Sep 6, 2026
@moonfruit
moonfruit force-pushed the to-enum-convert-factory branch from 9034e73 to 910e4ed Compare September 7, 2026 02:34
@moonfruit

Copy link
Copy Markdown
Contributor Author

Hi @sbrannen,

I've updated the PR with all the requested changes:

  • Renamed ConversionUtils.getEnumType(...) to resolveEnumType(...) and added Javadoc pointing out that it returns null if the enum type cannot be resolved.
  • Removed the NonConvertableToEnum converter. StringToEnumConverterFactory and IntegerToEnumConverterFactory now implement ConditionalConverter, with matches(...) implemented as you suggested, and their getConverter(...) methods keep the original Assert.notNull(...) semantics.
  • Applied your suggested test, canConvertToEnumDoesNotThrowForNonEnumTargetType().

GenericConversionServiceTests and checkstyleMain/checkstyleTest pass locally for spring-core.

@moonfruit
moonfruit force-pushed the to-enum-convert-factory branch from 910e4ed to 3ea78d4 Compare September 7, 2026 02:39
@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 7, 2026

@sbrannen sbrannen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good now. Thanks for making the requested changes! 👍

However, your commit is failing the DCO check. So please address that.

@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Sep 7, 2026
@sbrannen
sbrannen marked this pull request as ready for review September 7, 2026 08:57
Signed-off-by: MoonFruit <dkmoonfruit@gmail.com>
@moonfruit
moonfruit force-pushed the to-enum-convert-factory branch from 3ea78d4 to 643a9a0 Compare September 8, 2026 08:01
@moonfruit

Copy link
Copy Markdown
Contributor Author

Sorry about that — the commit was missing the Signed-off-by trailer. I have amended the commit to add the sign-off and force-pushed the branch; the DCO check is passing now. No changes were made to the code itself.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 8, 2026
@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Sep 8, 2026
sbrannen added a commit that referenced this pull request Sep 8, 2026
Prior to this commit, ConversionService#canConvert(Class, Class)
threw an IllegalArgumentException when invoked with Enum.class as the
target type (i.e., `canConvert(String.class, Enum.class)`), because
ConverterFactory#getConverter() in StringToEnumConverterFactory and
IntegerToEnumConverterFactory eagerly resolved the concrete enum type.

To address that, StringToEnumConverterFactory and
IntegerToEnumConverterFactory now implement ConditionalConverter so
that matches() can reject non-concrete-enum targets before
getConverter() is ever invoked.

Closes gh-34532

Signed-off-by: MoonFruit <dkmoonfruit@gmail.com>

Co-authored-by: Sam Brannen <104798+sbrannen@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixed via e2fae06

@github-actions github-actions Bot closed this Sep 8, 2026
@sbrannen

sbrannen commented Sep 8, 2026

Copy link
Copy Markdown
Member

This has been merged into 7.0.x and main.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants