Search code examples
xmlspringatlassian-crowd

How to initialize Iterable<Map.Entry<String, String>> in Spring XML configuration?


I would like to initialize a bean having the following property:

private Iterable<Map.Entry<String, String>> groupToAuthorityMappings;

In my context.xml, I expected to do it this way:

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
         xmlns="http://www.springframework.org/schema/security"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security-3.1.xsd"
         default-autowire="byName">

    <beans:bean id="crowdUserDetailsService"
        class="com.atlassian.crowd.integration.springsecurity.user.CrowdUserDetailsServiceImpl">
        ...
        <beans:property name="groupToAuthorityMappings">
            <beans:map>
                <beans:entry key="Manager" value="ROLE_ADMINISTRATOR,ROLE_USER"/>
            </beans:map>
        </beans:property>
        ...
    </beans:bean>
</beans:beans>

But I get the following error:

java.lang.IllegalStateException: Cannot convert value of type [java.util.LinkedHashMap] to required type [java.lang.Iterable] for property 'groupToAuthorityMappings': no matching editors or conversion strategy found

I cannot change the bean since it comes from a provided library. Does anybody know how I can achieve my goal?


Solution

  • If you're defining this data as a Map, you can use a factory-method to get an iterator over the entries:

    <util:map id='groupToAuthority>
        <beans:entry key="some-group" value="specific-authority-for-group" />
        ...
    </util:map>
    
    <bean class='ClassRequiringAnIterable'>
        <constructor-arg>
            <bean factory-bean='groupToAuthority' factory-method='entrySet'/>
        </constructor-arg>
    </bean>
    

    However, note that you require an Iterable<Map.Entry<String, String>>, and your sample defines a Map<String, List<String>>, so make sure that each group is mapped to exactly one role.