Skip to content

CollectionsToCollectionsConverter no longer handles java.util.Collections$EmptyList -> java.util.Collections$EmptyList [SPR-7293] #11952

@spring-projects-issues

Description

@spring-projects-issues

Jamie Goodfellow opened SPR-7293 and commented

Prior to 3.0.3, this class was capable of converting from a java.util.Collections$EmptyList to java.util.Collections$EmptyList. Starting from 3.0.3, this operation results in the exception: java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList

The following Test case was verified to pass in 3.0.2 and fail in 3.0.3:

package org.springframework.core.convert.support;

import java.util.Collections;
import java.util.List;

import org.junit.Test;
import org.springframework.core.convert.TypeDescriptor;

public class CollectionToCollectionConverterTest {

@Test
public void testCollectionsEmptyList() throws Exception {
	CollectionToCollectionConverter converter = new CollectionToCollectionConverter(new GenericConversionService());
	
	TypeDescriptor type = new TypeDescriptor(getClass().getField("list"), Class.forName("java.util.Collections$EmptyList"));
	
	converter.convert(list, type, type);
}

public List list = Collections.emptyList();

}

This specific situation is a problem because Spring Security uses this mechanism to convert the filterChainMap in the filterChainProxy, and elements with filters="none" set the filter chain to Collections.EMPTY_LIST. The Spring Security stack trace showing this error is:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChainProxy': Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.util.LinkedHashMap' to required type 'java.util.Map' for property 'filterChainMap'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "{/resources/=[], /ui/error/session*=[], /favicon.ico=[], /=[org.springframework.security.web.context.SecurityContextPersistenceFilter@a30589, org.springframework.security.web.authentication.logout.LogoutFilter@c07930, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@544b02, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@87286, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@96d92e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@18c5b4f, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@1beb7ec, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1cfb56, org.springframework.security.web.session.SessionManagementFilter@b8f952, org.springframework.security.web.access.ExceptionTranslationFilter@1f88953, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1cbf6bb, org.springframework.security.web.authentication.switchuser.SwitchUserFilter@1b3a74d]}" from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "[]" from type 'java.util.Collections$EmptyList' to type 'java.util.Collections$EmptyList'; nested exception is java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:574)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at com.truecontext.common.test.web.XmlWebApplicationContextLoader.loadContext(XmlWebApplicationContextLoader.java:47)
at com.truecontext.common.test.web.XmlWebApplicationContextLoader.loadContext(XmlWebApplicationContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
... 24 more
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.util.LinkedHashMap' to required type 'java.util.Map' for property 'filterChainMap'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "{/resources/=[], /ui/error/session*=[], /favicon.ico=[], /=[org.springframework.security.web.context.SecurityContextPersistenceFilter@a30589, org.springframework.security.web.authentication.logout.LogoutFilter@c07930, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@544b02, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@87286, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@96d92e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@18c5b4f, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@1beb7ec, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1cfb56, org.springframework.security.web.session.SessionManagementFilter@b8f952, org.springframework.security.web.access.ExceptionTranslationFilter@1f88953, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1cbf6bb, org.springframework.security.web.authentication.switchuser.SwitchUserFilter@1b3a74d]}" from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "[]" from type 'java.util.Collections$EmptyList' to type 'java.util.Collections$EmptyList'; nested exception is java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:457)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:499)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:493)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1363)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
... 36 more
Caused by: org.springframework.core.convert.ConversionFailedException: Unable to convert value "{/resources/=[], /ui/error/session*=[], /favicon.ico=[], /=[org.springframework.security.web.context.SecurityContextPersistenceFilter@a30589, org.springframework.security.web.authentication.logout.LogoutFilter@c07930, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@544b02, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@87286, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@96d92e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@18c5b4f, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@1beb7ec, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1cfb56, org.springframework.security.web.session.SessionManagementFilter@b8f952, org.springframework.security.web.access.ExceptionTranslationFilter@1f88953, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1cbf6bb, org.springframework.security.web.authentication.switchuser.SwitchUserFilter@1b3a74d]}" from type 'java.util.LinkedHashMap' to type 'java.util.Map'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "[]" from type 'java.util.Collections$EmptyList' to type 'java.util.Collections$EmptyList'; nested exception is java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:40)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:183)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:141)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:447)
... 42 more
Caused by: org.springframework.core.convert.ConversionFailedException: Unable to convert value "[]" from type 'java.util.Collections$EmptyList' to type 'java.util.Collections$EmptyList'; nested exception is java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:40)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:183)
at org.springframework.core.convert.support.MapToMapConverter.convert(MapToMapConverter.java:68)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
... 45 more
Caused by: java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.Collections$EmptyList
at org.springframework.core.CollectionFactory.createCollection(CollectionFactory.java:256)
at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:61)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
... 48 more

I believe this used to work because a check was made to see if the source was assignable to the target type. If so, the source was returned. I would either put this logic back in, or in the CollectionsFactory, specially handle the Collections$EmptyList list type.


Affects: 3.0.3, 3.0.6, 3.1 RC2

Referenced from: commits 7eeb654, e0d922d, 27b0403

Backported to: 3.0.7

3 votes, 8 watchers

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions