James
James

Reputation: 264

Inject the value of an enum into a property using spring

I have an enum similar to the below

public enum MyEnum {
ABC("some string"), 
DEF("some string"), 
GHI("another string");

String value;

private MyEnum(String value) {
    this.value = value;
}

public String value() {
    return this.value;
}}

And I would like to make a util:map using the value of the enum as the key not the enum itself. So the map would look like this:

"some string" -> "mapped output 1"
"another string" -> "mapped output 2"

I know I can use util:constant to get the enum but i need the value the enum represents.

So my config file at the minute looks like this:

<util:constant id="firstKey" static-field="package.MyEnum.ABC"/>
<util:constant id="secondKey" static-field="package.MyEnum.GHI" />


<util:map id="myMap">
    <entry key-ref="firstKey" value="mapped output 1" />
    <entry key-ref="secondKey" value="mapped output 2" /></util:map>

Is there a way I can get .value() or even get access to the value property to use it as the key?

I tried declaring the key type to be string in the hope spring would work it out but it seems to have just ignored this.

Using spring 2.5.1 and I cannot modify the enum

Upvotes: 5

Views: 26269

Answers (2)

Ian Roberts
Ian Roberts

Reputation: 122394

If you don't have access to the expression language you'll have to fall back to an explicit MethodInvokingFactoryBean

<bean id="firstKey" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetObject"><util:constant static-field="package.MyEnum.ABC"/></property>
  <property name="targetMethod" value="value" />
</bean>

You could shorten the repetitive XML a bit with an abstract parent bean definition.

<bean name="enumValue" abstract="true"
      class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetMethod" value="value" />
</bean>

<bean id="firstKey" parent="enumValue">
  <property name="targetObject"><util:constant static-field="package.MyEnum.ABC"/></property>
</bean>

You could also skip the MethodInvokingFactoryBean and just use

<util:constant id="MyEnum_ABC" static-field="package.MyEnum.ABC" />
<bean id="firstKey" factory-bean="MyEnum_ABC" factory-method="value" />

but that means declaring separate top-level beans for each enum constant as well as for their value(), whereas using MIFB allows you to use anonymous inner beans.

Upvotes: 8

Manuel Quinones
Manuel Quinones

Reputation: 4246

Here is how to get the value injected below is the spring configuration in spring 2.5.

<bean id="abcEnum" class="com.ex.springbasicex.enums.MyEnum"   factory-method="valueOf">
    <constructor-arg>
        <value>ABC</value>
    </constructor-arg>
</bean>

<bean id="defEnum" class="com.ex.springbasicex.enums.MyEnum" factory-method="valueOf">
    <constructor-arg>
        <value>DEF</value>
    </constructor-arg>
</bean>

<bean id="abcString" class="java.lang.String" factory-method="valueOf">
    <constructor-arg>
        <ref bean="abcEnum"></ref>
    </constructor-arg>
</bean>
<bean id="defString" class="java.lang.String" factory-method="valueOf">
    <constructor-arg>
        <ref bean="defEnum"></ref>
    </constructor-arg>
</bean>

<util:map id="myMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key-ref="abcString" value="mapped output 1"  />
    <entry key-ref="defString" value="mapped output 2" />
</util:map>

In order for this to work you need the toString method on your enum.

public enum MyEnum {

ABC("some string a"), 
DEF("some string b"), 
GHI("another string");

String value;

private MyEnum(String value) {
    this.value = value;
}

public String value() {
    return this.value;
}

public String toString() {
    return this.value;
}
}

Upvotes: 3

Related Questions