Hi Nate,

Thanks for the detailed info and the PoC which enabled me to debug the issue!

The issue is introduced by [1] lines insertions which has changed the path of 
the execution to findValue(expr, class) instead of findValue(expr). 
findValue(expr, class) simply returns expr without evaluating it when class is 
String and expr doesn't have %{. Before this change Struts used to use 
findValue(expr) which evaluates expr.

@Lukasz, what's your idea? looks like a regression right? Because Radio value 
class looks like that can be Boolean according to Nate's sample.

Regards,
Yasser

[1] 
https://github.com/apache/struts/pull/577/files#diff-812c02fab412aaa588054c477048432288505ef1978d53d5b23ce9e5661f8492R83-R86

________________________________________
From: Nate Kerkhofs <nate.kerkh...@ikan.be>
Sent: Monday, November 27, 2023 4:17 PM
To: Struts Users Mailing List
Subject: RE: Struts 6.3 tags do not automatically evaluate the value field 
against the ognl stack

Hello,

I have a further update with a working proof of concept Github repository. It's 
a little bit janky because I usually use subversion instead of Git, but it 
should work:

https://github.com/ikannak/RadioPoC

If you do mvn jetty:run on the maven repository inside this project and then go 
to the url in the readme.md, you'll see that both the first and second radio 
button groups will have the "true" value selected, which matches what's in the 
action. If you then update the struts2.version in the pom.xml to 6.3.0.1, 
restart the Jetty server and reload the page, you'll see that the first radio 
button group, which uses value="lockedStatic" will now be fully unchecked, 
while the second radio button group with value="%{lockedOgnl}" will still be 
checked. So SOMETHING has changed between these versions, but I'm not sure what.

Kind regards,

Nate

-----Original Message-----
From: Nate Kerkhofs <nate.kerkh...@ikan.be>
Sent: Monday, 27 November 2023 10:16
To: user@struts.apache.org
Cc: Lukasz Lenart <lukaszlen...@apache.org>
Subject: RE: Struts 6.3 tags do not automatically evaluate the value field 
against the ognl stack

Hello Lukasz,

Apologies for this, I was under the impression that sending an email to the 
mailing list would automatically inform me of any updates to the email. I have 
subscribed to the user list now as well, which I was planning on doing today so 
I could stay updated about Struts 7. The Struts 7 release is most likely a hard 
blocker for our application because we intend to fully migrate to the Jakarta 
libraries in our next release, including Tomcat 11 and Spring 6, and we found 
that Struts 6 still uses the Javax libraries.

Yasser, thanks for the update. One thing I forgot to mention was that our 
application uses a custom Radiomap.ftl (included below) template that worked 
for versions 2.2 through 2.5, but no longer worked after that, though from what 
I can see that template did not do any interpretation as well. That said, I 
also tried without that ftl template, AND I created a quick and dirty project 
with literally just Struts 6, a basic Action.java and the dependencies without 
any custom template, and I had the same result. In addition, I tried it using 
default s:textfield input element as well, and that also did not evaluate the 
value as an OGNL object, instead interpreting it as a string literal unless I 
explicitly used %{} to evaluate it. I'll try to create a proof of concept 
Github project so you guys can evaluate this as well.

I doublechecked and it doesn't appear like we have any special interceptors, 
converters, listeners, filters or constants set that might explain the value 
thing. In our constants, we disabled DMI and devmode, exclude our rest API 
(which uses Spring), set our multipart maxSize to 10^8, changed the static 
Content path to /struts (a new change because apparently in Struts 6 it 
defaults to /static) and configure the file upload save dir. We have filters to 
set the Character Encoding to UTF-8 and set a ThreadLocal variable. We have 
interceptors for a custom back button, various error handling, verifying the 
license and handling authentication and authorization, none of which handle the 
Value. We have converters for Date, Integer, Time and TimeStamp objects. We 
have Listeners for the HttpSession and ServletContext objects, neither of which 
handle Values. We have custom Tags for rendering certain content based on user 
access rights. I can't really see any code that does anything special in this 
case. And regardless, it didn't work in a basically empty Struts 6 project 
either...

I also checked the documentation for the tag syntax at 
https://struts.apache.org/tag-developers/tag-syntax#value-is-an-object , and it 
explicitly says that value is interpreted as an ognl object.

Neither of these templates below properly set the checked property in Struts 6. 
The old template correctly set it in 2.5.

OLD TEMPLATE

<#--
/*
* $Id: radiomap.ftl,v 1.1 2009/03/19 10:51:54 pai Exp $
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<@s.iterator value="parameters.list">
   <#if parameters.listKey?exists>
       <#assign itemKey = stack.findValue(parameters.listKey)/>
   <#else>
       <#assign itemKey = stack.findValue('top')/>
   </#if>
   <#assign itemKeyStr = itemKey.toString() />
   <#if parameters.listValue?exists>
       <#assign itemValue = stack.findString(parameters.listValue)/>
   <#else>
       <#assign itemValue = stack.findString('top')/>
   </#if>
<input type="radio"<#rt/>
<#if parameters.name?exists>
name="${parameters.name?html}"<#rt/>
</#if>
id="${parameters.id?html}${itemKeyStr?html}"<#rt/>
<#if tag.contains(parameters.nameValue?default(''), itemKeyStr)> 
checked="checked"<#rt/> </#if> <#if itemKey?exists> 
value="${itemKeyStr?html}"<#rt/> </#if> <#if parameters.disabled?default(false)>
disabled="disabled"<#rt/>
</#if>
<#if parameters.tabindex?exists>
tabindex="${parameters.tabindex?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/scripting-events.ftl" /> <#include 
"/${parameters.templateDir}/simple/common-attributes.ftl" /> /><#rt/> <label 
for="${parameters.id?html}${itemKeyStr?html}" 
class="c-table-basic__radio-label"><#rt/>
   ${itemValue}<#t/>
</label>
</@s.iterator>

IN DEVELOPMENT TEMPLATE (being updated to work with the Freemarker updates like 
removal of ?html and ?default):

<#--
/*
 * $Id: radiomap.ftl,v 1.1 2009/03/19 10:51:54 pai Exp $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
-->
<@s.iterator value="parameters.list">
    <#if parameters.listKey??>
        <#assign itemKey = stack.findValue(parameters.listKey)/>
        <#assign itemKeyStr = stack.findString(parameters.listKey)/>
    <#else>
        <#assign itemKey = stack.findValue('top')/>
        <#assign itemKeyStr = stack.findString('top')>
    </#if>
    <#assign itemKeyStr = itemKey.toString() />
    <#if parameters.listValue??>
        <#assign itemValue = stack.findString(parameters.listValue)/>
    <#else>
        <#assign itemValue = stack.findString('top')/>
    </#if>
<input type="radio"<#rt/>
<#if parameters.name?has_content>
 name="${parameters.name?no_esc}"<#rt/>
</#if>
 id="${parameters.id}${itemKeyStr?replace(".", "_")}"<#rt/> <#if 
tag.contains(parameters.nameValue!'', itemKey)>  checked="checked"<#rt/> </#if> 
<#if itemKey??>  value="${itemKeyStr}"<#rt/> </#if> <#if 
parameters.disabled!false>  disabled="disabled"<#rt/> </#if> <#if 
parameters.tabindex?has_content>  tabindex="${parameters.tabindex}"<#rt/>
</#if>
<#if itemCssClass?has_content>
 class="${itemCssClass}"<#rt/>
</#if>
<#if itemCssStyle?has_content>
 style="${itemCssStyle}"<#rt/>
</#if>
<#if itemTitle?has_content>
 title="${itemTitle}"<#rt/>
<#else>
    <#if parameters.title?has_content>
 title="${parameters.title}"<#rt/>
    </#if>
</#if>
<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" /> 
<#include 
"/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" /> 
<#include 
"/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" /> 
<#global evaluate_dynamic_attributes = true/> <#include 
"/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" 
/> /><#rt/> <label for="${parameters.id}${itemKeyStr?replace(".", "_")}" 
class="c-table-basic__radio-label"><#rt/>
    ${itemValue}<#t/>
</label>
</@s.iterator>

Kind Regards,

Nate

-----Original Message-----
From: Lukasz Lenart <lukaszlen...@apache.org>
Sent: Saturday, 25 November 2023 15:04
To: Nate Kerkhofs <nate.kerkh...@ikan.be>
Cc: Struts Users Mailing List <user@struts.apache.org>
Subject: Re: Struts 6.3 tags do not automatically evaluate the value field 
against the ognl stack

Hello Nate,

I approved your message but to get replies from the members of the Struts User 
group please subscribe to the list [1] [1] https://struts.apache.org/mail.html

Cheers
Lukasz

pt., 24 lis 2023 o 16:32 Yasser Zamani <yasserzam...@apache.org> napisał(a):
>
> Hi Nate,
>
> Thanks for reaching out!
>
> What I can't understand is how your app evaluates the value. Because I see 
> the following in Struts UIBean.java since 2006:
>
>         // see if the value was specified as a parameter already
>         if (parameters.containsKey("value")) {
>             parameters.put("nameValue" , parameters.get("value"));
>         } else {
>
> which I think means that it doesn't evaluate value if you've already set it. 
> As far as I remember Struts evaluates name to calculate value if it's not 
> already set.
>
> Don't you have some specific magic in your app? Could you please see also 
> Struts logs for any WARN message?
>
> Regards,
> Yasser
>
> ________________________________________
> From: Nate Kerkhofs <nate.kerkh...@ikan.be>
> Sent: Friday, November 24, 2023 3:23 PM
> To: user@struts.apache.org
> Subject: Struts 6.3 tags do not automatically evaluate the value field
> against the ognl stack
>
> Greetings,
>
> I am currently upgrading a Struts 2.5 project to Struts 6.3, and I ran into 
> an issue with Struts 6.3 tags not evaluating the value against the ognl 
> stack. I have reproduced this issue both with the radio map included in the 
> struts2-core jar and with a custom radiomap.ftl, and also with an s:textfield 
> instead of an s:radio. In both cases, the value attribute on the source page 
> doesn't get resolved against the ognl stack, instead using the string literal 
> entered in the value attribute.
>
> I have about 140 s:radio components formatted like below, with "locked" being 
> a Boolean field in the Action java controller:
>
> <s:set var="lockedOptionMap" value="#{'true':getText('label.true'),
> 'false':getText('label.false')}" /> <s:radio
> label="%{getText('label.projectStream.locked')}"
> list="lockedOptionMap" id="locked" name="locked" value="locked" />
>
> In this case, none of the radios with a value set are setting their checked 
> status based on the boolean value because parameters.nameValue doesn't get 
> evaluated by ognl. If I remove the value attribute or make it an explicit 
> ognl expression using %{}, it does resolve the attribute against the ognl 
> stack and select the right item, but with the code above, the value got 
> resolved against the ognl ValueStack in 2.5, but that doesn't happen in 6.3. 
> Instead, it just sets nameValue to "locked" or whatever string literal 
> "value" is set to.
>
> I cannot find any mention of this breaking change in the migration guide, 
> though I did find an issue dating back to 2007 mentioning a similar problem: 
> https://issues.apache.org/jira/browse/WW-1907 which means that this either is 
> a regression or it a deliberate design decision to no longer evaluate this 
> property against the ognl stack.
>
> Either way, I'd like to know whether this is an intentional change, and if so 
> what the recommended way is to use a field on the ognl stack to configure the 
> value of a field: should I add an explicit %{} evaluation symbol around the 
> value attribute, or should I just leave out the value attribute entirely, 
> instead relying solely on the name attribute set on the tag?
>
> Kind regards,
>
> Nate Kerkhofs
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscr...@struts.apache.org
> For additional commands, e-mail: user-h...@struts.apache.org
>
B�KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB��[��X��ܚX�KK[XZ[�\�\�][��X��ܚX�P��]˘\X�K�ܙ�B��܈Y][ۘ[��[X[��K[XZ[�\�\�Z[��]˘\X�K�ܙ�B

Reply via email to