List Map Mapping in Spring MVC

I’m not sure if this is a difficult problem, but as a beginner, it seems a bit complicated to me. I have an object based on which I need to show some values ​​in the user interface and allow the user to select some of them, I need to send the data back to another controller when the user clicks the submit button. Here is the structure of my data object

public class PrsData{ private Map<String, List<PrsCDData>> prsCDData; } public class PrsCDData{ private Map<String, Collection<ConfiguredDesignData>> configuredDesignData; } public ConfiguredDesignData{ // simple fields } 

I set the object in the model before displaying the view, for example

 model.addAttribute("prsData", productData.getPrData()); 

In the form I have the following settings

 <form:form method="post" commandName="prsData" action="${addProductToCartAction}" > <form:hidden path="prsCDData['${prsCDDataMap.key}'] [${status.index}].configuredDesignData['${configuredDesignDataMap.key}'] [${configuredDesignDataStatus.index}].code"/> <form:hidden path="prsCDData['${prsCDDataMap.key}'] [${status.index}].configuredDesignData['${configuredDesignDataMap.key}'] [${configuredDesignDataStatus.index}].description"/> </form:form> 

This is what I have in AddProductToCartController

 public String addToCart(@RequestParam("productCodePost") final String code, @ModelAttribute("prsData") final PrsData prsData, final Model model, @RequestParam(value = "qty", required = false, defaultValue = "1") final long qty) 

When I submit the form, I get the following exception

 org.springframework.beans.NullValueInNestedPathException: Invalid property 'prsCDData[Forced][0]' of bean class [com.product.data.PrsData]: Cannot access indexed value of property referenced in indexed property path 'prsCDData[Forced][0]': returned null 

It seems to be trying to access the values ​​on this controller while I try to pass the value to this controller and trying to create the same object with the selected values

Can someone tell me where I am doing wrong and what I need to take care of

Edit

I did some more research and found out that Spring does not support auto-populating a list / map for custom objects and based on the answer I tried to change the implementation, for example

 public class PrsData{ private Map<String, List<PrsCDData>> prsCDData; // lazy init public PrsData() { this.prsCDData = MapUtils.lazyMap(new HashMap<String, List<PrsCDData>>(), FactoryUtils.instantiateFactory(PrsCDData.class)); } } public class PrsCDData{ private Map<String, Collection<ConfiguredDesignData>> configuredDesignData; public PrsCDData() { this.configuredDesignData = MapUtils.lazyMap(new HashMap<String, List<ConfiguredDesignData>>(), FactoryUtils.instantiateFactory(ConfiguredDesignData.class)); } } 

but I get the following exception

 org.springframework.beans.InvalidPropertyException: Invalid property 'prsCDData[Forced][0]' of bean class [com.data.PrsData]: Property referenced in indexed property path 'prsCDData[Forced][0]' is neither an array nor a List nor a Set nor a Map; returned value was [ com.data.PrsCDData@6043a24d ] 

I'm not sure what I'm doing wrong, it seems like either my JSTL expression is not suitable

+7
source share
1 answer

Explanation: if your controller has @ModelAttribute("user") User user , and you load the corresponding page containing <form:form commandName="user"> , an empty user is created.

All its attributes are null or empty in the case of a list or map. Moreover, its empty lists / maps were created using autostart implementation. What does it mean? Let them say that we have an empty List<Coconut> coconuts . If I do coconuts.get(someIndex).setDiameter(50) , it will work instead of throwing an exception because the list automatically grows and creates a coconut instance for the given index.
Thanks to this autostart, the form feed with the following input will work like a charm:

 <form:input path="coconuts[${someIndex}].diameter" /> 

Now back to your problem: Spring MVC Startup works with a chain of objects, each of which contains a map / list ( see this post ). But, given your exception, it seems like Spring is not auto-updating the possible objects contained in the autorun list / map. In Map<String, List<PrsCDData>> prsCDData List<PrsCDData> is a simple empty list without autoload, which leads to your Exception.

So the solution should use some kind of Apache Common LazyList or Spring AutoPopulatingList .
You must implement your own autoload map, which creates an instance of LazyList / AutoPopulatingList for this index. Do it from scratch or using some kind of Apache Common LazyMap / MapUtils.lazyMap (until I found the Spring equivalent for LazyMap).

Sample solution using Apache Commons collections:

 public class PrsData { private Map<String, List<PrsCDData>> prsCDData; public PrsData() { this.prsCDData = MapUtils.lazyMap(new HashMap<String,List<Object>>(), new Factory() { public Object create() { return LazyList.decorate(new ArrayList<PrsCDData>(), FactoryUtils.instantiateFactory(PrsCDData.class)); } }); } } 
+7
source

All Articles