4

I have an instance of the following class what i would like to edit in a from, and then save it back at the backend.

public class NestedClass {
    List<InnerClass> inners = new LinkedList<InnerClass>();

    //getter and setter

    public class InnerClass {
        private String innerField;

        //getter and setter
   }
}

EDIT: sample code edited to meet @Slava Semushin's advice.

When i instantiate the class and pass it to the model i can read the values with the following jsp snippet:

<form:input path="inners[0].innerField" /><br/>
<form:input path="inners[1].innerField" /><br/>

But when i pass it back i get the following exception:

Invalid property 'inners[0]' of bean class [com.sodacrm.webapp.forms.NestedClass]: Illegal attempt to get property 'inners' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'inners' of bean class [com.sodacrm.webapp.forms.NestedClass]: Could not instantiate property type [com.sodacrm.webapp.forms.NestedClass$InnerClass] to auto-grow nested property path: java.lang.InstantiationException: com.sodacrm.webapp.forms.NestedClass$InnerClass
org.springframework.beans.InvalidPropertyException: Invalid property 'inners[0]' of bean class [com.sodacrm.webapp.forms.NestedClass]: Illegal attempt to get property 'inners' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'inners' of bean class [com.sodacrm.webapp.forms.NestedClass]: Could not instantiate property type [com.sodacrm.webapp.forms.NestedClass$InnerClass] to auto-grow nested property path: java.lang.InstantiationException: com.sodacrm.webapp.forms.NestedClass$InnerClass

The real class what i'm using is 3 levels deep and i don't want to put the inner classes to separate files because they are strongly belong to their outter classes...

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Szilard
  • 73
  • 2
  • 6
  • Any reason `InnerClass` is not defined as `static`? – Pavel Horal May 27 '14 at 12:06
  • It's probably the inner class not being static and or missing getters/setter and or autogrow not being set. That being said there really is no shame in using a transfer object. It's generally more secure and single responsibility to go DTO albeit less DRY. – Adam Gent May 27 '14 at 12:14
  • I am facing the same issue, how did you manage to solve it? – Stef Oct 03 '15 at 18:13

2 Answers2

0

How do you define getter for inners member? Check that it always returns valid list:

List<InnerClass> inners = new LinkedList<InnerClass>();

OR

public List<InnerClass> getInners() {
    if (inners == null) {
        inners = new LinkedList<InnerClass>();
    }
    return inners;
}
Slava Semushin
  • 14,904
  • 7
  • 53
  • 69
  • You're right I forgot to set the list. But when i set it the same exception occurs... – Szilard Mar 28 '14 at 15:02
  • FYI - when talking about data binding, spring will create instance of your collection as well as auto grow its components. Initializing collections is not necessary. Check `DataBinder#setAutoGrowNestedPaths` (enabled by default). http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/validation/DataBinder.html#setAutoGrowNestedPaths%28boolean%29 – Pavel Horal May 27 '14 at 12:02
0

The reason is the inner class. Spring instantiates the inner class purely given the inner class type, this class does not have a reference to the instance of the NestedClass and because of this the instantiation fails (since instances of InnerClass can only exists within the context of a instance of NestedClass)

The fix unfortunately is to move either the InnerClass out of scope of the NestedClass or to declare it as a static inner class. Also you don't need to instantiate the inners list, it will be automatically be instantiated to an ArrayList.

This may be worth a Jira ticket though as it seems like a good enhancement to make to the Spring framework.

Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • If the model object is propertly initialized and `autoGrowNestedPaths` is disabled, binding will work. However it is not possible to do dynamic forms in this way. – Pavel Horal May 27 '14 at 12:06