Friday, 29 June 2018

How to Inject Map having Dependent Object in key and value using DI by Setter method

Enjoying This Tutorial?

Subscribe to Ram N Java for high-quality, practical Java and Spring tutorials!

SUBSCRIBE NOW

Introduction

In Spring Framework, configuring collection dependencies often involves key-value mappings where both the keys and values are custom bean references rather than primitive types. Spring provides robust XML configuration tags like <map> and <entry> with attributes such as key-ref and value-ref to inject complex java.util.Map structures using setter-based dependency injection.

Why Inject Dependent Objects in Map Keys and Values?

  • Complex Domain Associations: Allows mapping distinct entity objects (e.g., a Department key to an Employee value) directly through configuration.
  • key-ref & value-ref Attributes: Eliminates boilerplate lookup code by wiring independent Spring bean definitions into map entries seamlessly.
  • Decoupled Architecture: Keeps configuration of individual collaborators modular and easily reusable across other beans in the application context.

Step-by-Step Code Example

Here is an example showing how to configure and inject a Map where both key and value are dependent collaborator objects:

1. The Model Classes

package com.ram.model;

import java.util.Map;

// Key Object
public class Department {
    private String deptName;

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Department [deptName=" + deptName + "]";
    }
}

// Value Object
public class Employee {
    private String empName;

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    @Override
    public String toString() {
        return "Employee [empName=" + empName + "]";
    }
}

// Consumer Class holding the Map
public class Organization {
    private Map<Department, Employee> deptHeadMap;

    // Setter method for map injection
    public void setDeptHeadMap(Map<Department, Employee> deptHeadMap) {
        this.deptHeadMap = deptHeadMap;
    }

    public void display() {
        for (Map.Entry<Department, Employee> entry : deptHeadMap.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }
    }
}

2. Configuring applicationContext.xml

Use key-ref and value-ref inside the <entry> element to reference existing bean definitions:

<!-- Dependent Bean Definitions -->
<bean id="deptIT" class="com.ram.model.Department">
    <property name="deptName" value="Information Technology" />
</bean>

<bean id="empRam" class="com.ram.model.Employee">
    <property name="empName" value="Ram" />
</bean>

<!-- Organization Bean with Map Setter Injection -->
<bean id="organization" class="com.ram.model.Organization">
    <property name="deptHeadMap">
        <map>
            <entry key-ref="deptIT" value-ref="empRam" />
        </map>
    </property>
</bean>

3. Loading and Executing the Application

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Organization org = (Organization) context.getBean("organization");
org.display();

Key Takeaway

Spring makes wiring complex data structures easy through <entry key-ref="..." value-ref="..."/>. This allows full decoupling of key and value object configurations while letting Spring's IoC container inject complete, ready-to-use maps into your beans.


Click here to watch on Youtube: 
https://www.youtube.com/watch?v=tzuWplk3OF8&list=UUhwKlOVR041tngjerWxVccw

Click the below Image to Enlarge: 
How to Inject Map having Dependent Object in key and value using DI by Setter method

How to Inject Map having Dependent Object in key and value using DI by Setter method

How to Inject Map having Dependent Object in key and value using DI by Setter method

How to Inject Map having Dependent Object in key and value using DI by Setter method

How to Inject Map having Dependent Object in key and value using DI by Setter method
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ram.core</groupId>
    <artifactId>SpringDemo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>SpringDemo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <spring.version>5.0.2.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Spring 5 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

Fruit.java

package com.ram.model;

public class Fruit
{
    private String name;
    private String color;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getColor()
    {
        return color;
    }

    public void setColor(String color)
    {
        this.color = color;
    }

    @Override
    public String toString()
    {
        return "Fruit [name=" + name + ", color=" + color + "]";
    }

}

FruitSeller.java

package com.ram.model;

public class FruitSeller
{
    private String name;
    private String emailId;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getEmailId()
    {
        return emailId;
    }

    public void setEmailId(String emailId)
    {
        this.emailId = emailId;
    }

    @Override
    public String toString()
    {
        return "FruitSeller [name=" + name + ", emailId=" + emailId + "]";
    }

}

FruitInfo.java

package com.ram.core;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.ram.model.Fruit;
import com.ram.model.FruitSeller;

public class FruitInfo
{
    private Map<FruitSeller, Fruit> mapOfFruitSellerAndFruit;

    public Map<FruitSeller, Fruit> getMapOfFruitSellerAndFruit()
    {
        return mapOfFruitSellerAndFruit;
    }

    public void setMapOfFruitSellerAndFruit(
            Map<FruitSeller, Fruit> mapOfFruitSellerAndFruit)
    {
        this.mapOfFruitSellerAndFruit = mapOfFruitSellerAndFruit;
    }

    public void displayFruitInfo()
    {
        System.out.println("FruitInfo [mapOfFruitSellerAndFruit="
                + mapOfFruitSellerAndFruit + "]");

        Set<Entry<FruitSeller, Fruit>> set = mapOfFruitSellerAndFruit
                .entrySet();

        Iterator<Entry<FruitSeller, Fruit>> itr = set.iterator();
        while (itr.hasNext())
        {
            Entry<FruitSeller, Fruit> entry = itr.next();
            System.out.println("FruitSeller = " + entry.getKey() + ", Fruit = "
                    + entry.getValue());
        }

    }

}

applicationContext.xml

<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-4.3.xsd">


    <bean id="fruitSeller1" class="com.ram.model.FruitSeller">
        <property name="name" value="Peter"></property>
        <property name="emailId" value="Peter@yahoo.com"></property>
    </bean>

    <bean id="fruitSeller2" class="com.ram.model.FruitSeller">
        <property name="name" value="John"></property>
        <property name="emailId" value="John@gmail.com"></property>
    </bean>

    <bean id="fruit1" class="com.ram.model.Fruit">
        <property name="name" value="Apple"></property>
        <property name="color" value="Red"></property>
    </bean>

    <bean id="fruit2" class="com.ram.model.Fruit">
        <property name="name" value="Grapes"></property>
        <property name="color" value="Violet"></property>
    </bean>

    <bean id="fruitInfo" class="com.ram.core.FruitInfo">

        <property name="mapOfFruitSellerAndFruit">
            <map>
                <entry key-ref="fruitSeller1" value-ref="fruit1"></entry>
                <entry key-ref="fruitSeller2" value-ref="fruit2"></entry>
            </map>
        </property>

    </bean>

</beans>

App.java

package com.ram.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
    public static void main(String[] args)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");

        System.out.println("---------------------------------------");

        FruitInfo fruitInfo = (FruitInfo) context.getBean("fruitInfo");
        System.out.println(
                "Got fruitInfo object from the ApplicationContext(Spring container)");
        fruitInfo.displayFruitInfo();
    }

}

Output

May 17, 2018 8:47:52 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Thu May 17 08:47:52 IST 2018]; root of context hierarchy
May 17, 2018 8:47:52 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
---------------------------------------
Got fruitInfo object from the ApplicationContext(Spring container)
FruitInfo [mapOfFruitSellerAndFruit={FruitSeller [name=Peter, emailId=Peter@yahoo.com]=Fruit [name=Apple, color=Red], FruitSeller [name=John, emailId=John@gmail.com]=Fruit [name=Grapes, color=Violet]}]
FruitSeller = FruitSeller [name=Peter, emailId=Peter@yahoo.com], Fruit = Fruit [name=Apple, color=Red]
FruitSeller = FruitSeller [name=John, emailId=John@gmail.com], Fruit = Fruit [name=Grapes, color=Violet]

Click the below link to download the code:
https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_Setter_DI_Map_KVDependentObject.zip?attredirects=0&d=1

Github Link:
https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_Setter_DI_Map_KVDependentObject

Bitbucket Link:
https://bitbucket.org/ramram43210/spring/src/00d9c316f5df8a9bcb6603e70c0baf4d24d6fdcd/Spring_2018/SpringDemo_Setter_DI_Map_KVDependentObject/?at=master

See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    Enjoying This Tutorial?

    Subscribe to Ram N Java for high-quality, practical Java and Spring tutorials!

    SUBSCRIBE NOW

    Introduction

    In Spring Framework applications, configuring a java.util.Map where the key is a simple literal (such as a String) and the value is a custom dependent object bean reference is a very common scenario. Spring makes this simple and expressive in XML using the <map> and <entry> tags along with the key and value-ref attributes via setter-based dependency injection.

    Why Inject Dependent Objects in Map Values?

    • Key-Based Bean Lookup: Allows mapping straightforward string keys (like department codes or role titles) directly to complex collaborator beans.
    • value-ref Attribute: Seamlessly wires independent Spring bean definitions as map values without writing custom population code.
    • Clean Separation: Allows collaborator beans to be declared independently and injected into maps across multiple beans cleanly.

    Step-by-Step Code Example

    Here is an example showing how to inject a Map<String, Employee> where the value is a dependent Employee bean:

    1. The Model Classes

    package com.ram.model;
    
    import java.util.Map;
    
    // Dependent Object (Value)
    public class Employee {
        private String name;
        private String role;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    
        @Override
        public String toString() {
            return "Employee [name=" + name + ", role=" + role + "]";
        }
    }
    
    // Consumer Class holding the Map
    public class Organization {
        private Map<String, Employee> employeesMap;
    
        // Setter method for dependency injection
        public void setEmployeesMap(Map<String, Employee> employeesMap) {
            this.employeesMap = employeesMap;
        }
    
        public void display() {
            for (Map.Entry<String, Employee> entry : employeesMap.entrySet()) {
                System.out.println("Key: " + entry.getKey() + " -> " + entry.getValue());
            }
        }
    }

    2. Configuring applicationContext.xml

    Use key for the string identifier and value-ref to point to the dependent bean definition:

    <!-- Dependent Bean Definitions -->
    <bean id="emp1" class="com.ram.model.Employee">
        <property name="name" value="Ram" />
        <property name="role" value="Technical Lead" />
    </bean>
    
    <bean id="emp2" class="com.ram.model.Employee">
        <property name="name" value="Peter" />
        <property name="role" value="Developer" />
    </bean>
    
    <!-- Organization Bean with Map Setter Injection -->
    <bean id="organization" class="com.ram.model.Organization">
        <property name="employeesMap">
            <map>
                <entry key="LEAD" value-ref="emp1" />
                <entry key="DEV" value-ref="emp2" />
            </map>
        </property>
    </bean>

    3. Loading and Executing with ApplicationContext

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    Organization org = (Organization) context.getBean("organization");
    org.display();

    Key Takeaway

    Configuring <entry key="..." value-ref="..."/> provides a clean and readable pattern to map literal keys to full Spring-managed bean instances through setter injection, keeping your application modular and maintainable.


    Click here to watch on Youtube:
    https://www.youtube.com/watch?v=ImiOMkRaARU&list=UUhwKlOVR041tngjerWxVccw

    Click the below Image to Enlarge:

    How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    How to Inject Map having Dependent Object in value using dependency injection by Setter method?

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.ram.core</groupId>
        <artifactId>SpringDemo</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>SpringDemo</name>
        <url>http://maven.apache.org</url>

        <properties>
            <spring.version>5.0.2.RELEASE</spring.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>

            <!-- Spring 5 dependencies -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>
    </project>

    Fruit.java

    package com.ram.model;

    public class Fruit
    {
        private String name;
        private String color;

        public String getName()
        {
            return name;
        }

        public void setName(String name)
        {
            this.name = name;
        }

        public String getColor()
        {
            return color;
        }

        public void setColor(String color)
        {
            this.color = color;
        }

        @Override
        public String toString()
        {
            return "Fruit [name=" + name + ", color=" + color + "]";
        }

    }

    FruitShop.java

    package com.ram.core;

    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;

    import com.ram.model.Fruit;

    public class FruitShop
    {
        private String shopName;
        private Map<Integer, Fruit> mapOfAvailableFruits;

        public String getShopName()
        {
            return shopName;
        }

        public void setShopName(String shopName)
        {
            this.shopName = shopName;
        }

        public Map<Integer, Fruit> getMapOfAvailableFruits()
        {
            return mapOfAvailableFruits;
        }

        public void setMapOfAvailableFruits(
                Map<Integer, Fruit> mapOfAvailableFruits)
        {
            this.mapOfAvailableFruits = mapOfAvailableFruits;
        }

        public void displayFruitShopInfo()
        {
            System.out.println("Fruit ShopName = " + shopName);

            Set<Entry<Integer, Fruit>> set = mapOfAvailableFruits.entrySet();
            Iterator<Entry<Integer, Fruit>> itr = set.iterator();
            while (itr.hasNext())
            {
                Entry<Integer, Fruit> entry = itr.next();
                System.out.println("Fruit Id = " + entry.getKey()
                        + ", Fruit Info = " + entry.getValue());
            }

        }

    }

    applicationContext.xml

    <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-4.3.xsd">


        <bean id="fruit1" class="com.ram.model.Fruit">
            <property name="name" value="Apple"></property>
            <property name="color" value="Red"></property>
        </bean>

        <bean id="fruit2" class="com.ram.model.Fruit">
            <property name="name" value="Grapes"></property>
            <property name="color" value="Violet"></property>
        </bean>

        <bean id="fruitShop" class="com.ram.core.FruitShop">

            <property name="shopName" value="Fruit Mart"></property>
            <property name="mapOfAvailableFruits">
                <map>
                    <entry key="1" value-ref="fruit1"></entry>
                    <entry key="2" value-ref="fruit2"></entry>
                </map>
            </property>

        </bean>

    </beans>

    App.java

    package com.ram.core;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class App
    {
        public static void main(String[] args)
        {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    "applicationContext.xml");

            System.out.println("---------------------------------------");

            FruitShop fruitShop = (FruitShop) context.getBean("fruitShop");
            System.out.println(
                    "Got fruitShop object from the ApplicationContext(Spring Container)");
            fruitShop.displayFruitShopInfo();
        }

    }

    Output

    May 16, 2018 9:01:22 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
    INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Wed May 16 09:01:22 IST 2018]; root of context hierarchy
    May 16, 2018 9:01:22 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
    ---------------------------------------
    Got fruitShop object from the ApplicationContext(Spring Container)
    Fruit ShopName = Fruit Mart
    Fruit Id = 1, Fruit Info = Fruit [name=Apple, color=Red]
    Fruit Id = 2, Fruit Info = Fruit [name=Grapes, color=Violet]

    Click the below link to download the code:
    https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_Setter_DI_Map_ValueDependentObject.zip?attredirects=0&d=1

    Github Link:
    https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_Setter_DI_Map_ValueDependentObject

    Bitbucket Link:
    https://bitbucket.org/ramram43210/spring/src/00d9c316f5df8a9bcb6603e70c0baf4d24d6fdcd/Spring_2018/SpringDemo_Setter_DI_Map_ValueDependentObject/?at=master

    See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • Tutorials