- Amir Boroumand | Software engineer based in Pittsburgh, PA/
- blog/
- Spring overwrites map keys with bean name from value/
Spring overwrites map keys with bean name from value
·2 mins
Overview #
I recently encountered a strange behavior in Spring where it overwrites map keys with the value bean names. In this article, I’ll demonstrate how this issue happens and how to solve it.
Code Example #
OrderType.java #
public enum OrderType {
ONLINE, STORE, WAREHOUSE;
}
OrderSubmissionStrategy.java #
public interface OrderSubmissionStrategy {}
OnlineOrderSubmissionStrategy.java #
public class OnlineOrderSubmissionStrategy implements OrderSubmissionStrategy {}
WarehouseOrderSubmissionStrategy.java #
public class WarehouseOrderSubmissionStrategy implements OrderSubmissionStrategy {}
Let’s define a Map bean by annotating a method that returns our map with @Bean
.
@Configuration
public class AppConfiguration {
@Bean
public Map<OrderType, OrderSubmissionStrategy> strategyMap() {
Map<OrderType, OrderSubmissionStrategy> strategyMap = new HashMap<>();
strategyMap.put(OrderType.ONLINE, onlineOrderSubmissionStrategy());
strategyMap.put(OrderType.WAREHOUSE, warehouseOrderSubmissionStrategy());
return strategyMap;
}
@Bean
public OrderSubmissionStrategy onlineOrderSubmissionStrategy() {
return new OnlineOrderSubmissionStrategy();
}
@Bean
public OrderSubmissionStrategy warehouseOrderSubmissionStrategy() {
return new WarehouseOrderSubmissionStrategy();
}
}
Now, let’s use this inject bean into another class using @Autowired
.
@Component
public class OrderSubmissionStrategyFactory {
@Autowired
private Map<OrderType, OrderSubmissionStrategy> strategyMap;
public void printStrategyMap() {
strategyMap.entrySet().forEach(entry-> {
System.out.println(entry.getKey() + " " + entry.getValue());
});
}
}
When we invoke the printStrategyMap()
method, notice that the map keys have been overwritten with the bean names from the values:
[onlineOrderSubmissionStrategy, onlineOrderSubmissionStrategy]
[warehouseOrderSubmissionStrategy, warehouseOrderSubmissionStrategy]
Solution #
It turns out that using @Autowired
for injecting a map causes this strange behavior so the solution is to use @Resource
instead.
@Component
public class OrderSubmissionStrategyFactory {
@Resource
private Map<OrderType, OrderSubmissionStrategy> strategyMap;
public void printStrategyMap() {
strategyMap.entrySet().forEach(entry-> {
System.out.println(entry.getKey() + " " + entry.getValue());
});
}
}
Now the output is what we expect.
[ONLINE, onlineOrderSubmissionStrategy]
[WAREHOUSE, warehouseOrderSubmissionStrategy]