1
votes

I have seen how to inject an int array in spring bean. I was wondering if we can try injecting a 2d-array. I tried following code:

...
<bean id="myBean" class="com.rohit.spring.MyClass">
    <property name="myIntArray" value="{1,2,3},{4,5,6},{7,8,9}" />
</bean>
...

The class looks like:

Class MyCLass
{
    private Integer[][] myIntArray;

    public Integer[][] getMyIntArray(){
        return this.myIntArray;
    }
    public void setMyIntArray(Integer[][] myIntArray){
        this.myIntArray = myIntArray;
    }
}

The error thrown reads:

"Invalid property 'myIntArray' of bean class [com.rohit.spring.MyClass]: Bean property 'myIntArray' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?"

Any idea if it's not possible or if I'm doing something wrong?

2
You could create each 1 dimensional array as individual beans in the way that the other page tells you to, and then create another bean which is an array of those beans.Ben Green
Hi @Ben Green, yup that's one of the work arounds, but still, the question is - is it out of scope to inject a 2D array or I am not following the correct syntax. Cheers!Rohit Deshmukh

2 Answers

2
votes

You can do this:

<beans:bean id="someClass" class="com.you.SomeClass" >
   <beans:property name="myIntArray">
       <beans:list>
           <beans:list>
               <beans:value>1</beans:value>
               <beans:value>2</beans:value>
               <beans:value>3</beans:value>
           </beans:list>
           <beans:list>
               <beans:value>4</beans:value>
               <beans:value>5</beans:value>
               <beans:value>6</beans:value>
           </beans:list>
           <beans:list>
               <beans:value>7</beans:value>
               <beans:value>8</beans:value>
               <beans:value>9</beans:value>
           </beans:list>
       </beans:list>
   </beans:property>
</beans:bean>

Or:

<beans:bean id="someClass" class="com.you.SomeClass" >
   <beans:property name="myIntArray">
       <beans:array> 
           <beans:array>
               <beans:value>1</beans:value>
               <beans:value>2</beans:value>
               <beans:value>3</beans:value>
           </beans:array>
           <beans:array>
               <beans:value>4</beans:value>
               <beans:value>5</beans:value>
               <beans:value>6</beans:value>
           </beans:array>
           <beans:array>
               <beans:value>7</beans:value>
               <beans:value>8</beans:value>
               <beans:value>9</beans:value>
           </beans:array> 
       </beans:array>
   </beans:property>
</beans:bean>

UPDATE: Supply your own converter

Another way would be to use Converters. Here is an example implementation:

public class IntArrayConverter implements Converter<String, int[][]> {
    @Override
    public int[][] convert(String source) {
        if(isBlank(source)) {
            return new int[0][0];
        }

        String[] subArraysStrs = source.split(":");
        int[][] result = new int[subArraysStrs.length][];

        for(int i = 0; i < subArraysStrs.length; i++) {
            String subArrayStr = trim(subArraysStrs[i]);
            if(isBlank(subArrayStr)) {
                throw new IllegalArgumentException();
            }

            String[] subArrayElementStrs = subArrayStr.split(",");
            int[] subArray = new int[subArrayElementStrs.length];
            for(int j = 0; j < subArray.length; j++) {
                String elementStr = trim(subArrayElementStrs[j]);
                subArray[j] = Integer.parseInt(elementStr);
            }
            result[i] = subArray;
        }

        return result;
    }
}

Now, tell spring that it can use this converter by declaring the following in your configuration:

<bean id="conversionService"
        class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.example.IntArrayConverter" />
            </list>
        </property>
    </bean>

and then:

<bean class="com.you.SomeClass">
    <property name="myIntArray" value="1,2,3:4,5,6:7,8,9"></property>
</bean>

My Converter is implemented to be used without the curly braces around each sub-array for simplicity. That is, instead of

<property name="myIntArray" value="{1,2,3},{4,5,6},{7,8,9}"></property>

I am going with

<property name="myIntArray" value="1,2,3:4,5,6:7,8,9"></property>

If you want, you can modify the code to interpret any kind of string format. For more details about Converters, you can look here.

Note: The registered ConversionService will be availabel to your entire app. That is, it will be used whenever there is a need to convert a String into an int[][]. Also, even though you provide only one converter, all the default converters are registered anyway, so you won't lose their benefits.

1
votes

Yet another way

To complement the answer of Bhashit Parikh, yet another simple way of injecting an int[][] array via an XML configuration file is as follows:

<beans:bean id="someClass" class="com.you.SomeClass" >
    <beans:property name="myIntArray">
        <beans:list>
           <beans:value>1,2,3</beans:value>
           <beans:value>4,5,6</beans:value>
           <beans:value>7,8,9</beans:value>
        </beans:list>
    </beans:property>
</beans:bean>