Lukasz Lenart created WW-5790:
---------------------------------
Summary: REST two-phase body copy writes constructor defaults over
values already set on the target
Key: WW-5790
URL: https://issues.apache.org/jira/browse/WW-5790
Project: Struts 2
Issue Type: Bug
Components: Plugin - REST
Reporter: Lukasz Lenart
Follow-up to [WW-5789|https://issues.apache.org/jira/browse/WW-5789], which
covered the handlers that do not read the body at all.
When {{struts.parameters.requireAnnotations=true}} and the selected
content-type handler does not implement
{{AuthorizationAwareContentTypeHandler}},
{{ContentTypeInterceptor.applyTwoPhaseDeserialize}} creates a fresh instance of
the target with its no-arg constructor, lets the handler fill it from the body,
and then copies every non-null property from that instance onto the real
target. The copy cannot tell a value the body supplied from a value the
constructor assigned, so a property the body omits is still copied when it has
a non-null constructor default. That overwrites whatever was on the target
before the {{rest}} interceptor ran: a value bound by {{params}}, or one loaded
in {{prepare()}}.
Affected handlers: {{XStreamHandler}} (shipped, registered by the application)
and any application-provided handler that does not declare the marker. The
handlers shipped as default ({{JacksonJsonHandler}}, {{JacksonXmlHandler}},
{{JuneauXmlHandler}}) are not affected, they authorize during deserialization.
Example: a ModelDriven model declares {{private String status = "new";}}. The
request carries {{status=approved}} as a query parameter and an XML body that
only contains {{name}}. After the stack runs, {{status}} is {{new}}.
Possible direction: compare each property of the filled instance against a
second, untouched fresh instance and copy only what the handler changed,
threading that baseline through the nested-bean recursion. A body value that
happens to equal the constructor default would then not be applied over a
differing existing value, which is the same ambiguity the copy already has for
null.
Tests to add in {{ContentTypeInterceptorIntegrationTest}}: a non-aware handler
that fills part of a model with a constructor default, asserting the omitted
property keeps its prior value.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)