Spring

INJECTION OF MAP(JAVA COLLECTION) USING SETTER AND CONSTRUCTOR DEPENDENCY INJECTION

 

 

In our previous tutorial we learned how to inject java collection java.util.Set using spring framework, In this tutorial, we will learn how to inject java collection java.util.Map using Setter and Constructor Injection.

Setter Injection using Map values: As we know map contains key-value pair so In setter injection using a Map, we define a tag like this in our configuration file.

<property name=”name of variable”>


<map>


<entry>


<key>


<value>name of key 1</value>


</key>


<value>name of value 1</value>


</entry>


<entry>


<key>


<value>name of key 2</value>


</key>


<value>name of value 2</value>


</entry>


<entry>


<key>


<value>name of key …n</value>


</key>


<value>name of value…n</value>


</entry>


</map>


</property>


 

and a set method which contains a map as a parameter into which we want to inject our dependency.

Example:

As in our previous tutorial of “injection of Set” we passed a list of objects, In this example, we will pass a map and as you know map doesn’t contain duplicate items and have key-value pairs, so if we try to pass two duplicate items it will consider it as a single item only as it replaces it with the first one.

Phone.java


package com.codegeekslab.device;

import java.util.Map;

public interface Phone {

public void openApp(Map&amp;amp;amp;amp;amp;lt;String,Integer&amp;amp;amp;amp;amp;gt; contactDetails, String app);

}

BasicPhone.java


package com.codegeekslab.type;

import java.util.Map;
import java.util.Map.Entry;

import com.codegeekslab.device.Phone;

public class BasicPhone implements Phone {

public void openApp(Map&amp;amp;amp;amp;amp;lt;String,Integer&amp;amp;amp;amp;amp;gt; contactDetails, String app) {
for(Entry&amp;amp;amp;amp;amp;lt;String, Integer&amp;amp;amp;amp;amp;gt; details:contactDetails.entrySet())
System.out.println("calling "+details.getKey()+"("+details.getValue()+")"+" via "+app);
}

}

SmartPhone.java


package com.codegeekslab.type;

import java.util.Map;
import java.util.Map.Entry;

import com.codegeekslab.device.Phone;

public class SmartPhone implements Phone {

public void openApp(Map&amp;amp;amp;amp;amp;lt;String,Integer&amp;amp;amp;amp;amp;gt; contactDetails, String app) {
for(Entry&amp;amp;amp;amp;amp;lt;String, Integer&amp;amp;amp;amp;amp;gt; details:contactDetails.entrySet())
System.out.println("calling "+details.getKey()+"("+details.getValue()+")"+" via "+app);
}

}

CallingApp.java


package com.codegeekslab.app;

import java.util.Map;
import java.util.Set;

import com.codegeekslab.device.Phone;

public class CallingApp {

private Phone phone;

private Map&amp;amp;amp;amp;amp;lt;String, Integer&amp;amp;amp;amp;amp;gt; contactDetails;

private String app;

// for setter injection
public void setPhone(Phone phone) {
this.phone = phone;
}

public Phone getPhone() {
return phone;
}

public String getApp() {
return app;
}

public void setApp(String app) {
this.app = app;
}

public Map&amp;amp;amp;amp;amp;lt;String, Integer&amp;amp;amp;amp;amp;gt; getContactDetails() {
return contactDetails;
}

public void setContactDetails(Map&amp;amp;amp;amp;amp;lt;String, Integer&amp;amp;amp;amp;amp;gt; contactDetails) {
this.contactDetails = contactDetails;
}

public void makeCall() {
phone.openApp(contactDetails, app);
}

}

beans.xml


&amp;amp;amp;amp;amp;lt;beans xmlns="http://www.springframework.org/schema/beans"
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-2.5.xsd"&amp;amp;amp;amp;amp;gt;

&amp;amp;amp;amp;amp;lt;bean id="BasicPhone" class="com.codegeekslab.type.BasicPhone" /&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;bean id="SmartPhone" class="com.codegeekslab.type.SmartPhone" /&amp;amp;amp;amp;amp;gt;

&amp;amp;amp;amp;amp;lt;bean id="CallingApp" class="com.codegeekslab.app.CallingApp"&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;property name="phone" ref="SmartPhone"&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;/property&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;property name="contactDetails"&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;map&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;mom&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;12345&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;dad&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;67890&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;gf&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/key&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;value&amp;amp;amp;amp;amp;gt;9999999&amp;amp;amp;amp;amp;lt;/value&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/entry&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/map&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/property&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;property name="app" value="whatsapp"&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;/property&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/bean&amp;amp;amp;amp;amp;gt;
&amp;amp;amp;amp;amp;lt;/beans&amp;amp;amp;amp;amp;gt;

Test.java


package com.codegeekslab.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.codegeekslab.app.CallingApp;
public class Test {

public static void main(String[] args) {
ApplicationContext context =new GenericXmlApplicationContext("beans.xml");
CallingApp callingApp = (CallingApp) context.getBean("CallingApp");
callingApp.makeCall();

}
}

output


Mar 28, 2017 1:29:31 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Mar 28, 2017 1:29:31 PM org.springframework.context.support.GenericXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericXmlApplicationContext@5e9f23b4: startup date [Tue Mar 28 13:29:31 IST 2017]; root of context hierarchy
calling mom(12345) via whatsapp
calling dad(67890) via whatsapp
calling gf(9999999) via whatsapp

As you can see from the output “calling key(value) via whatsapp” is getting called 3 times as we are passing a map of 3 key-value pairs as name and number into the set method public void setContactDetails(Map<String, Integer> contactDetails) {..} of CallingApp class through beans.xml.

In this example, we are injecting 3 items into all set methods of CallingApp class

  1. Dependent Object using <property name=”phone” ref=”SmartPhone”></property>.
  2. Map of key-value pairs as String and Integer values using <property name=”number”><map><entry><key><value>mom</value></key><value>12345</value></entry></property >.
  3. String Value using <property name=”app” value=”whatsapp”></property>.

Constructor Injection using Map values: In setter injection using a map, we define a tag

 

<constructor-arg>


<map>


<entry>


<key>


<value>mom</value>


</key>


<value>12345</value>


</entry>


<entry>


<key>


<value>dad</value>


</key>


<value>67890</value>


</entry>


<entry>


<key>


<value>gf</value>


</key>


<value>9999999</value>


</entry>


</map>


</constructor-arg>

in the XML file and a constructor with a parameter as map into which we want to inject our dependency.


Let’s implement the same above example using constructor injection.

All files will remain same except beans.xml and CallingApp.java

CallingApp.java


package com.codegeekslab.app;

import java.util.Map;
import java.util.Set;

import com.codegeekslab.device.Phone;

public class CallingApp {

private Phone phone;

private Map&amp;lt;String, Integer&amp;gt; contactDetails;

private String app;

public CallingApp(Phone phone, Map&amp;lt;String, Integer&amp;gt; contactDetails, String app) {
super();
this.phone = phone;
this.contactDetails = contactDetails;
this.app = app;
}

public void makeCall() {
phone.openApp(contactDetails, app);
}

}

beans.xml


&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"
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-2.5.xsd"&amp;gt;

&amp;lt;bean id="BasicPhone" class="com.codegeekslab.type.BasicPhone" /&amp;gt;
&amp;lt;bean id="SmartPhone" class="com.codegeekslab.type.SmartPhone" /&amp;gt;

&amp;lt;bean id="CallingApp" class="com.codegeekslab.app.CallingApp"&amp;gt;
&amp;lt;constructor-arg ref="SmartPhone" /&amp;gt;
&amp;lt;constructor-arg&amp;gt;
&amp;lt;map&amp;gt;
&amp;lt;entry&amp;gt;
&amp;lt;key&amp;gt;
&amp;lt;value&amp;gt;mom&amp;lt;/value&amp;gt;
&amp;lt;/key&amp;gt;
&amp;lt;value&amp;gt;12345&amp;lt;/value&amp;gt;
&amp;lt;/entry&amp;gt;
&amp;lt;entry&amp;gt;
&amp;lt;key&amp;gt;
&amp;lt;value&amp;gt;dad&amp;lt;/value&amp;gt;
&amp;lt;/key&amp;gt;
&amp;lt;value&amp;gt;67890&amp;lt;/value&amp;gt;
&amp;lt;/entry&amp;gt;
&amp;lt;entry&amp;gt;
&amp;lt;key&amp;gt;
&amp;lt;value&amp;gt;gf&amp;lt;/value&amp;gt;
&amp;lt;/key&amp;gt;
&amp;lt;value&amp;gt;9999999&amp;lt;/value&amp;gt;
&amp;lt;/entry&amp;gt;
&amp;lt;/map&amp;gt;
&amp;lt;/constructor-arg&amp;gt;
&amp;lt;constructor-arg value="whatsapp" /&amp;gt;
&amp;lt;/bean&amp;gt;
&amp;lt;/beans&amp;gt;

output


Mar 28, 2017 2:54:08 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Mar 28, 2017 2:54:09 PM org.springframework.context.support.GenericXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericXmlApplicationContext@5e9f23b4: startup date [Tue Mar 28 14:54:09 IST 2017]; root of context hierarchy
calling mom(12345) via whatsapp
calling dad(67890) via whatsapp
calling gf(9999999) via whatsapp

As like setter injection you can see from the output “calling key(value) via whatsapp” is getting called 3 times as we are passing a map of 3 key-value pairs as name and number into the constructor  public CallingApp(Phone phone, Map<String, Integer> contactDetails, String app)  {..} of CallingApp class through beans.xml.

In this example, we are injecting 3 items into all set methods of CallingApp class

  1. Dependent Object using <constructor-arg ref=”SmartPhone” />.
  2. Map of key-value pairs as String and Integer values using <constructor-arg><map><entry><key><value>mom</value></key><value>12345</value></entry></constructor-arg>.
  3. String Value using <constructor-arg value=”whatsapp” />.

That’s all in how to inject collection using spring framework, In our next tutorial we will learn a new concept in spring framework that is Autowiring.

 

Leave a Reply

Your email address will not be published. Required fields are marked *