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)

Reply via email to