Using Collections in Spring - java

A collection object can be created from another collection object using constructor.
List<Student> list = new ArrayList<Student>(someStudentList);
Which can be done in Spring.
<bean id="stdArrayList" class="java.util.ArrayList">
<constructor-arg >
<list>
<ref bean="student1" />
<ref bean="student2" />
<ref bean="student3" />
</list>
</constructor-arg>
</bean>
<bean id="student1" class="mawia.test.Student"
....
How can I do this way of adding item in Spring?
Set<Student> set= new TreeSet<Student>();
set.add(new Student(5, "Mawia"));
...
So that I can use the constructor which accept a comparator object.
Set<Student> set= new TreeSet<Student>(new MyComparator());
set.add(new Student(5, "Mawia"));
...

I suspect the simplest approach would be to create a trivial subclass of TreeSet that provides a two-argument constructor:
public class MyTreeSet<T> extends TreeSet<T> {
public MyTreeSet(Comparator<? super T> cmp, Collection<? extends T> coll) {
super(cmp);
addAll(coll);
}
}
and use this as the type of your bean, passing both the comparator and the initial values as <constructor-arg> values.
<bean id="studentSet" class="com.example.MyTreeSet">
<constructor-arg index="0">
<bean class="com.example.MyComparator" />
</constructor-arg>
<constructor-arg index="1">
<list>
<ref bean="student1" />
<ref bean="student2" />
<ref bean="student3" />
</list>
</constructor-arg>
</bean>
Or instead of a subclass of TreeSet you could write your own FactoryBean.
To do it without writing any additional code you could use a second bean definition to do the adding
<bean id="studentSet" class="java.util.TreeSet">
<constructor-arg>
<bean class="com.example.MyComparator" />
</constructor-arg>
</bean>
<bean id="studentSetFiller" factory-bean="studentSet" factory-method="addAll">
<constructor-arg>
<list>
<ref bean="student1" />
<ref bean="student2" />
<ref bean="student3" />
</list>
</constructor-arg>
</bean>
but then any other bean into which you inject studentSet needs an additional depends-on="studentSetFiller" to make sure the set is populated before the target bean tries to use it.

You might be able to do it using the util schema like this;
<util:set id="emails" set-class="java.util.TreeSet">
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</util:set>
(taken from http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-util-set)
I'll test if its possible to add constructor args and confirm.

The TreeSet does not provide a combined constructor to pass Comparator as well as data. So I guess you can only do one via construtor injection.
Other part you should try via property injection if its exposed.

Related

Order of bean initialization in Spring

I have the following beans in my Spring config file:
<bean id="myList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="elem1"/>
<ref bean="elem2"/>
<ref bean="elem3"/>
<ref bean="elem4"/>
</list>
</constructor-arg>
</bean>
<bean id="elem4" class="myClass">
<property name="title" value="random4"/>
</bean>
<bean id="elem1" class="myClass">
<property name="title" value="random1"/>
</bean>
<bean id="elem3" class="myClass">
<property name="title" value="random3"/>
</bean>
<bean id="elem2" class="myClass">
<property name="title" value="random2"/>
</bean>
I have noticed that in my application the elements in myList are in the following order: elem4, elem1, elem3, elem2. I was expecting that the elements in my list will be in the order I set when I declared the ref beans ( elem1, elem2, elem3, elem4).
Is there an order in which Spring initializes beans?
Is there a way I can specify an order for the elements in my list?
The spring does respect the order you gave in the list. The elements in the list would exactly be the [elem1,elem2,elem3,elem4] as you specified. Otherwise, you are doing something wrong, can you show the code which prints you the different order?
The order of bean initialization however may be different and depends on bean dependencies, so, for example if you have two beans
<bean id="holder" class="my.HolderBean" lazy-init="false">
<property name="inner" ref="inner"/>
</bean>
<bean id="inner" class="my.InnerBean" lazy-init="false"/>
Then regardless of the xml definition order, the InnerBean will be initialized first, then during HolderBean initialization it will be injected into HolderBean.

Is it possible to create a collections with Spring configuration?

Suppose I have a class MyClass which can be instantiated either with String or it have predefined static instances inside a class.
Something like this:
public class MyClass {
public final static MyClass A = new MyClass("A");
public final static MyClass B = new MyClass("B");
public final static MyClass C = new MyClass("C");
...
public MyClass(String name) {
...
}
}
Is it possible to create an ArrayList<MyClass> bean in Spring config somehow? Something like
<bean id="sequence" class="...ArrayList">
<member class="...MyClass" value="A"/>
<member ... />
....
</bean>
UPDATE 1
Is it possible to write following way:
<bean id="sequence" class="...ArrayList">
<constructor-arg>
<list>
<bean class="...MyClass" constructor-arg="A"/>
<bean class="...MyClass" constructor-arg="B"/>
<bean class="...MyClass" constructor-arg="C"/>
</list>
</constructor-arg>
</bean>
You should have a look at the Collections section in the spring IOC documentation.
<bean id="moreComplexObject" class="example.ComplexObject">
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
</bean>
You could do:
<bean id="myClassA" class="org.foo.MyClass">
<constructor-arg>
<bean class="java.lang.String">
<constructor-arg value="A"/>
</bean>
<constructor-arg>
</bean>
<bean id="sequence" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="myClassA" />
...
</list>
</constructor-arg>
</bean>
Note, however, that the most common approach is to inject a list directly into a bean rather than wrapping a list within a list first.
Yes. You can even create it as a standalone bean. See this thread for two examples.

Spring: DRY with <list/>. Copy all values from listA to listB

I've configured in Spring listA (see below). It would be nice to have another one that contains all values from listA and expand it.
<bean id="listA" class="java.util.ArrayList">
<constructor-arg>
<list>
<value>a</value>
<value>b</value>
<value>...</value>
<value>z</value>
</list>
</constructor-arg>
</bean>
How to rewrite in Spring such Java code?
List listB = new ArrayList(listA);
listB.add("A");
...
listB.add("Z");
You can use collection merging:
<bean id="listA" class="java.util.ArrayList">
<constructor-arg index="0">
<list>
<value>a</value>
<value>b</value>
<value>...</value>
<value>z</value>
</list>
</constructor-arg>
</bean>
<bean id="listB" parent="listA">
<constructor-arg index="0">
<list merge="true">
<value>A</value>
<value>...</value>
<value>Z</value>
</list>
</constructor-arg>
</bean>

How to define a List bean in Spring?

I'm using Spring to define stages in my application. It's configured that the necessary class (here called Configurator) is injected with the stages.
Now I need the List of Stages in another class, named LoginBean. The Configurator doesn't offer access to his List of Stages.
I cannot change the class Configurator.
My Idea:
Define a new bean called Stages and inject it to Configurator and LoginBean.
My problem with this idea is that I don't know how to transform this property:
<property ...>
<list>
<bean ... >...</bean>
<bean ... >...</bean>
<bean ... >...</bean>
</list>
</property>
into a bean.
Something like this does not work:
<bean id="stages" class="java.util.ArrayList">
Can anybody help me with this?
Import the spring util namespace. Then you can define a list bean as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<util:list id="myList" value-type="java.lang.String">
<value>foo</value>
<value>bar</value>
</util:list>
The value-type is the generics type to be used, and is optional. You can also specify the list implementation class using the attribute list-class.
Here is one method:
<bean id="stage1" class="Stageclass"/>
<bean id="stage2" class="Stageclass"/>
<bean id="stages" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="stage1" />
<ref bean="stage2" />
</list>
</constructor-arg>
</bean>
<bean id="someBean"
class="com.somePackage.SomeClass">
<property name="myList">
<list value-type="com.somePackage.TypeForList">
<ref bean="someBeanInTheList"/>
<ref bean="someOtherBeanInTheList"/>
<ref bean="someThirdBeanInTheList"/>
</list>
</property>
</bean>
And in SomeClass:
class SomeClass {
List<TypeForList> myList;
#Required
public void setMyList(List<TypeForList> myList) {
this.myList = myList;
}
}
Another option is to use JavaConfig. Assuming that all stages are already registered as spring beans you just have to:
#Autowired
private List<Stage> stages;
and spring will automatically inject them into this list. If you need to preserve order (upper solution doesn't do that) you can do it in that way:
#Configuration
public class MyConfiguration {
#Autowired
private Stage1 stage1;
#Autowired
private Stage2 stage2;
#Bean
public List<Stage> stages() {
return Lists.newArrayList(stage1, stage2);
}
}
The other solution to preserve order is use a #Order annotation on beans. Then list will contain beans ordered by ascending annotation value.
#Bean
#Order(1)
public Stage stage1() {
return new Stage1();
}
#Bean
#Order(2)
public Stage stage2() {
return new Stage2();
}
Stacker posed a great answer, I would go one step farther to make it more dynamic and use Spring 3 EL Expression.
<bean id="listBean" class="java.util.ArrayList">
<constructor-arg>
<value>#{springDAOBean.getGenericListFoo()}</value>
</constructor-arg>
</bean>
I was trying to figure out how I could do this with the util:list but couldn't get it work due to conversion errors.
I think you may be looking for org.springframework.beans.factory.config.ListFactoryBean.
You declare a ListFactoryBean instance, providing the list to be instantiated as a property withe a <list> element as its value, and give the bean an id attribute. Then, each time you use the declared id as a ref or similar in some other bean declaration, a new copy of the list is instantiated. You can also specify the List class to be used.
<bean id="student1" class="com.spring.assin2.Student">
<property name="name" value="ram"></property>
<property name="id" value="1"></property>
<property name="listTest">
<list value-type="java.util.List">
<ref bean="test1"/>
<ref bean="test2"/>
</list>
</property>
</bean>
define those beans(test1,test2) afterwards :)
Inject list of strings.
Suppose you have Countries model class that take list of strings like below.
public class Countries {
private List<String> countries;
public List<String> getCountries() {
return countries;
}
public void setCountries(List<String> countries) {
this.countries = countries;
}
}
Following xml definition define a bean and inject list of countries.
<bean id="demoCountryCapitals" name="demoCountryCapitals" class="com.sample.pojo.Countries">
<property name="countries">
<list>
<value>Iceland</value>
<value>India</value>
<value>Sri Lanka</value>
<value>Russia</value>
</list>
</property>
</bean>
Reference link
Inject list of Pojos
Suppose if you have model class like below.
public class Country {
private String name;
private String capital;
.....
.....
}
public class Countries {
private List<Country> favoriteCountries;
public List<Country> getFavoriteCountries() {
return favoriteCountries;
}
public void setFavoriteCountries(List<Country> favoriteCountries) {
this.favoriteCountries = favoriteCountries;
}
}
Bean Definitions.
<bean id="india" class="com.sample.pojo.Country">
<property name="name" value="India" />
<property name="capital" value="New Delhi" />
</bean>
<bean id="russia" class="com.sample.pojo.Country">
<property name="name" value="Russia" />
<property name="capital" value="Moscow" />
</bean>
<bean id="demoCountryCapitals" name="demoCountryCapitals" class="com.sample.pojo.Countries">
<property name="favoriteCountries">
<list>
<ref bean="india" />
<ref bean="russia" />
</list>
</property>
</bean>
Reference Link.
Use the util namespace, you will be able to register the list as a bean in your application context. You can then reuse the list to inject it in other bean definitions.
As an addition to Jakub's answer, if you plan to use JavaConfig, you can also autowire that way:
import com.google.common.collect.Lists;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
<...>
#Configuration
public class MyConfiguration {
#Bean
public List<Stage> stages(final Stage1 stage1, final Stage2 stage2) {
return Lists.newArrayList(stage1, stage2);
}
}
You just remove id out of beans inside <list> tag. Like this:
<property name="listStaff">
<list>
<bean class="com.test.entity.Staff">
<constructor-arg name="name" value = "Jonh"/>
<constructor-arg name="age" value = "30"/>
</bean>
<bean class="com.test.entity.Staff">
<constructor-arg name="name" value = "Jam"/>
<constructor-arg name="age" value = "21"/>
</bean>
</list>
</property>
Use list-class attribute in util:list to make a standalone list of any particular type. for example if you want to make list of type ArrayList:
<util:list id="namesList" list-class="java.util.ArrayList" value-type="java.lang.String">
<value>Abhay</value>
<value>ankit</value>
<value>Akshansh</value>
<value>Db</value>
</util:list>
or if you want to make a list of type LinkedList then :
<util:list id="namesList" list-class="java.util.LinkedList" value-type="java.lang.String">
<value>Abhay</value>
<value>ankit</value>
<value>Akshansh</value>
<value>Db</value>
</util:list>
And this is how to inject set in some property in Spring:
<bean id="process"
class="biz.bsoft.processing">
<property name="stages">
<set value-type="biz.bsoft.AbstractStage">
<ref bean="stageReady"/>
<ref bean="stageSteady"/>
<ref bean="stageGo"/>
</set>
</property>
</bean>

spring: a bean that receives a list of Classes

I want to define in my Spring XML context a bean that has a property of the type List of classes: i.e. List<Class<?>> classes
How do I send that bean a number of classes, say java.lang.String and java.lang.Integer?
The list needs not be reusable, i.e. I will not refer to it in another bean.
With Spring, the simplest possibility usually works.....
<property name="classes">
<list>
<value>java.lang.String</value>
<value>java.lang.Integer</value>
</list>
</property>
<property name="classes">
<list>
<bean class="java.lang.Class" factory-method="forName">
<constructor-arg value="java.lang.String"/>
</bean>
</list>
</property>
Something like that...

Categories