Moxy unmarshalling of lists ignores defined setter method
Custom setter methods (defined via @XmlAccessMethods) are not called for Collection-valued properties.
During marshalling, the assigned get-method is called as expected to retrieve the value and the generated XML file is correct. However, during unmarshalling, no value is set.
This behavior occurs independently of the XmlAccessorType and field visibility for both sets and lists. It is not affected by switching to an external bindings file.
For atomic fields (no collection), both getter and setter methods are used (in marshalling and unmarshalling, respectively).
The attached MWE shows the difference in behavior between a field of type String and a field of type List<String>. Both fields are correctly marshalled to XML, but only baz receives a value during unmarshalling, bars remains set to null.
If this is working as intended (e.g. because the @XmlAccessMethods annotation cannot be used for list-valued properties), I was unable to locate this restriction anywhere in the documentation - it would also be quite unexpected behavior for me. In that case, some documentation on how to achieve an equivalent result, if currently possible, would help a lot.
Tested on version: 4.0.0
Example code: Foo.zip
Sorry I created my test case based on provided Foo.zip with separated Foo.java entity and test class TestBug.java and @XmlAccessMethods(getMethodName = "getFormattedBar", setMethodName = "formatAndSetBar") works OK to me.
moxy-bug-1798-MoxyUnmarshallingOfListsIgnoresDefinedSetterMethod.tar.gz
Thank you for looking into it! After a comparison of your and my code it seems that the following happens during unmarshalling:
- The Unmarshaller calls the designated getter method, presumably to reuse existing collection instances.
- Any matching elements are added either to the returned list, or to a new list, if the first step returned null
- The designated setter is called with the populated collection
The error appears because in my example code the getter call in step 1 throws an Exception (List#add is called while bars is still null). This Exception is caught, but then the remaining steps never happen.
While ideally getters should not throw Exceptions at all, I would assume that the intended behavior in such a case would be the same as if the getter returning null - i.e. a new List is created and used by the Unmarshaller. Alternatively, the exception could also be re-thrown (possibly wrapped in something else). Either way, silently swallowing it and skipping unmarshalling for this property does not seem like the way to go.