views:

2318

answers:

3

Hi all,

I've an Enum class

public enum MyEnum{
    ABC;
}

than my 'Mick' class has this property

private Map<MyEnum, OtherObj> myMap;

I've this spring xml configuration.

<util:map id="myMap">
    <entry key="ABC" value-ref="myObj" />
</util:map>

<bean id="mick" class="com.x.Mick">
    <property name="myMap" ref="myMap" />
</bean>

and this is fine.
I'd like to replace this xml configuration with Spring annotations.
Do you have any idea on how to autowire the map?

The problem here is that if I switch from xml config to the @Autowired annotation (on the myMap attribute of the Mick class) Spring is throwing this exception

nested exception is org.springframework.beans.FatalBeanException: Key type [class com.MyEnum] of map [java.util.Map] must be assignable to [java.lang.String]

Spring is no more able to recognize the string ABC as a MyEnum.ABC object.
Any idea?

Thanks

A: 

Should be:

public class Mick {

  private Map<MyEnum, OtherObj> myMap;

  @Autowired
  public void setMyMap(Map<MyEnum, OtherObj> myMap) {
    this.myMap = myMap;
  }
}

Have a look at http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

Updated

The problem is that according to the util schema, you cannot specify the key or value types. You can however to implement a MapFactoryBean of your own (just inherit from org.springframework.beans.factory.config.MapFactoryBean). One ceveat - notice that the generic definition (even thought erased in runtime) doesn't get in the way.

David Rabinowitz
Hi David, I know about the @Autowired annotation. Here the problem is that if I autowire the map Spring is no more able to recognize the string ABC as a MyEnum.ABC object. With XML configuration it works fine, with annotations configuration it's throwing this Exceptionnested exception is org.springframework.beans.FatalBeanException: Key type [class com.MyEnum] of map [java.util.Map] must be assignable to [java.lang.String]
al nik
I've updated my answer.
David Rabinowitz
A: 

The <util:map> element has key-type, resp. value-type attributes, that represents the class of the keys, resp. the values. If you specify the fully qualified class of your enum in the key-type attribute, the keys are then parsed into that enum when creating the map.

Spring verifies during injection that the map's key and value types -as declared in the class containing the map- are assignment-compatible with the key and value types of the map bean. This is actually where you get the exception from.

Gaetan
A: 

This worked for me...

My Spring application context:

<util:map id="myMap">
  <entry key="#{T(com.acme.MyEnum).ELEM1}" value="value1" />
  <entry key="#{T(com.acme.MyEnum).ELEM2}" value="value2" />
</util:map>

My class where the Map gets injected:

public class MyClass {

    private @Resource Map<MyEnum, String> myMap;
}

The important things to note are that in the Spring context I used SpEL (Spring Expression Language) which is only available since version 3.0. And in my class I used @Resource, neither @Inject (it didn't work for me) nor @Autowired (I didn't try this). The only difference I'm aware of between @Resource and @Autowired, is that the former auto-inject by bean name while the later does it by bean type.

Enjoy!

Cristian Ebbens