Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ParameterizedContainer throws IllegalAccessException when there is more than one parameter #27410

Closed
david-hamilton-bah opened this issue Jul 19, 2021 · 4 comments
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@david-hamilton-bah
Copy link

david-hamilton-bah commented Jul 19, 2021

I recently upgraded an application from spring-boot 2.1.17 to 2.4.2 and am getting the following error on startup.

java.lang.IllegalStateException: Error processing condition on my.package.MyConfigurationClass.personToUserConverter
	at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60)
	at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
	at 
	.....
Caused by: java.lang.IllegalArgumentException: Mismatched number of generics specified
	at org.springframework.util.Assert.isTrue(Assert.java:121)
	at org.springframework.core.ResolvableType.forClassWithGenerics(ResolvableType.java:1088)
	at org.springframework.core.ResolvableType.forClassWithGenerics(ResolvableType.java:1074)
	at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:240)
	at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:231)
	at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:221)
	at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:169)
	at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:144)
	at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)

The following (simplified) bean definition demonstrates the issue.

    @ConditionalOnMissingBean(value = {Person.class, User.class}, parameterizedContainer = Converter.class)
    @Bean
    Converter<Person, User> personToUserConverter() {
        return new PersonToPepUserConverter();
    }

This is fully working when the parameterizedContainer only has one parameter, but fails when there are multiple. Looking through the history, this looks to be caused by #17594

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 19, 2021
@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Jul 19, 2021
@philwebb
Copy link
Member

The parameterizedContainer attribute was primarily added to support classes like ServletRegistrationBean bean. The idea being that we'd detect beans of a specific type or their wrapper. For example, MyServlet or ServletRegistrationBean<MyServlet> would both match a @ConditionalOnBean(value=MyServlet.class, parameterizedContainer=ServletRegistrationBean.class).

It looks like you are trying to do something slightly different. I'm guessing you want to register the PersonToPepUserConverter only if a Converter<Person, User> bean is missing. There's no out-of-the-box condition annotation to do that I'm afraid. You might be able to write your own Condition that calls beanFactory.getBeanNamesForType with a different ResolvableType.

I'm not sure why things appeared to work in Spring Boot 2.1.17. I suspect the condition wasn't quite doing what you expected.

@philwebb
Copy link
Member

I should also mention that bean conditions such as @ConditionalOnMissingBean only work with auto-configuration class. You shouldn't be used with user @Configuration. See this javadoc comment:

The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

@philwebb
Copy link
Member

I don't think we can change the existing design. I'm going to close this one with the recommendation that you write a custom Condition implementation.

@philwebb philwebb added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Aug 16, 2021
@david-hamilton-bah
Copy link
Author

Thanks, @philwebb. We ended up forcing the client applications to either use the default bean name or specify the converter's bean name via property if using a custom one. That got us past the issue. I suspect you're right about the parameterizedContainer in 2.1.17, but it did work for both conditions where it was supplied or not. However, it was probably very fragile and could have broken if some other similar converter was defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

3 participants