Hello, I have done some investigating and found the following:
1. There was another exception before the previous exception that I didn't see last week, a NullPointerException for YESNOALLDESCRIPTIONS; 2. After looking into static fields a bit more, I found that those are initialized in the order of declaration, and if you look at BootstrapSupport more closely, you'll see that the INSTANCE singleton field is declared and initialized before the other static final fields I tried to use in the constructor are declared. That caused the NullPointerException, because it was trying to read that static variable before it was initialized. Once I moved the INSTANCE declaration after the other static field declarations the code worked without problems. 3. In the end, I moved the code for creating this list to the OverviewActionSupport, because as you can see we use a custom Localization engine, and we found it better to keep this logic centralized in our BaseActionSupport class, making the entire BootstrapSupport class obsolete. Kind regards, Nate -----Original Message----- From: Lukasz Lenart <lukaszlen...@apache.org> Sent: Sunday, 6 October 2024 07:55 To: Struts Users Mailing List <user@struts.apache.org> Subject: Re: Struts 6.4, Ognl and getters without an underlying field That should just work, I don't recall any changes affecting processing this. Could you enable DEBUG level and inspect logs before the error you get. Maybe there is a security WARNING you have missed. czw., 3 paź 2024 o 10:26 Nate Kerkhofs <nate.kerkh...@ikan.be> napisał(a): > > Hello, > > One small correction: it's a Struts 6.3 project, not 6.4. We were planning on > upgrading to 6.4 or a later 6.X version, but because we still need to upgrade > to 7.0 this release anyway we decided to skip any upgrades in between. > > Kind regards, > > Nate Kerkhofs > > -----Original Message----- > From: Nate Kerkhofs <nate.kerkh...@ikan.be> > Sent: Thursday, 3 October 2024 10:06 > To: Struts Users Mailing List <user@struts.apache.org> > Subject: Struts 6.4, Ognl and getters without an underlying field > > Hello, > > I have a Struts 6.4 page with a select, and I have a problem populating the > list attribute. > > <s:select id="searchView_showSecured" data-mdb-select-init="" > name="searchView.showSecured" theme="simple" list="yesNoAllList" > listKey="id" listValue="label" /> > > > What I'm trying to do is relatively simple: I have the following action code: > > public class MachineParameterOverviewBootstrapAction extends > OverviewActionSupport implements Expirable { ... > } > And this is the super action. Notably, this getter does NOT have an > underlying field property. > public class OverviewActionSupport extends BaseActionSupport { ... > public List<SelectOptionView> getYesNoAllList() { > return > BootstrapSupport.getInstance().getYesNoAllList(); > } > > } > > In the Tomcat log, I get this error: > > Caused by: tag 'select', field 'list', name 'searchView.showSecured': The > requested list key 'yesNoAllList' could not be resolved as a > collection/array/map/enumeration/iterator type. Example: people or > people.{name} - [unknown location] > at > org.apache.struts2.components.Component.fieldError(Component.java:284) > at > org.apache.struts2.components.Component.findValue(Component.java:363) > at > org.apache.struts2.components.ListUIBean.evaluateExtraParams(ListUIBean.java:78) > at > org.apache.struts2.components.Select.evaluateExtraParams(Select.java:101) > at > org.apache.struts2.components.UIBean.evaluateParams(UIBean.java:884) > at org.apache.struts2.components.UIBean.end(UIBean.java:550) > at > org.apache.struts2.views.jsp.ComponentTagSupport.doEndTag(ComponentTagSupport.java:40) > at > org.apache.jsp.jsp.machineparameter.machineParameterOverviewBootstrap_jsp._jspx_meth_s_005fselect_005f1(machineParameterOverviewBootstrap_jsp.java:11949) > at > org.apache.jsp.jsp.machineparameter.machineParameterOverviewBootstrap_jsp._jspService(machineParameterOverviewBootstrap_jsp.java:1209) > at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) > at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) > at > org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:466) > ... 118 more > > I assumed that Struts 6.4 would use getters and setters to interact with > properties on the page, because AFAIK that's what it did in Struts 2.3 and > 2.5, and hence I could just use a getter without having a field property with > the corresponding name on the action. Is that assumption incorrect? > > For completeness, this is BootstrapSupport.java: > > public final class BootstrapSupport extends ActionSupport { > > /** > * > */ > private static final long serialVersionUID = > 3159663106530217293L; > > private BootstrapSupport() { > loadYesNoAllOptionsMap(); > } > > private static final BootstrapSupport INSTANCE = new > BootstrapSupport(); > > /** > * The text provider, initialized with an instance of the > CustomTextProvider. > */ > private final transient TextProvider textProvider = new > CustomMessageResourcesFactory().createInstance(getClass(), > this); > > private List<SelectOptionView> yesNoAllList; > > private List<SelectOptionView> yesNoList; > > public static BootstrapSupport getInstance() { > return INSTANCE; > } > > /** > * This is used to help generate the yesnoall options dojo > string > */ > private static final int YNA_NO = > CommonUtils.DO_NOT_SHOW_ENTRIES; > private static final int YNA_YES = CommonUtils.SHOW_ENTRIES; > private static final int YNA_ALL = > CommonUtils.SHOW_ALL_ENTRIES; > > // Operating System description > private static final String[][] YESNOALLDESCRIPTIONS = { > { YNA_YES + "", > MasterCodeDescriptionKeys.MC_YESNOALL_YES }, > { YNA_NO + "", > MasterCodeDescriptionKeys.MC_YESNOALL_NO }, > { YNA_ALL + "", > MasterCodeDescriptionKeys.MC_YESNOALL_ALL } }; > // Operating System description > private static final String[][] YESNODESCRIPTIONS = { { > YNA_YES + "", MasterCodeDescriptionKeys.MC_YESNOALL_YES }, > { YNA_NO + "", > MasterCodeDescriptionKeys.MC_YESNOALL_NO } }; > > /** > * This method is automatically called by Struts, it injects > the value of the > * StrutsConstants.STRUTS_CUSTOM_I18N_RESOURCES. The values is > set as the static > * field of the CustomLocalizedTextUtil class, which is needed > when loading > * messages from the resource bundles. > * > * @param strutsCustomI18nResources The property value > */ > @Inject(StrutsConstants.STRUTS_CUSTOM_I18N_RESOURCES) > public void setStrutsCustomI18nResources(String > strutsCustomI18nResources) { > if > (CustomLocalizedTextUtil.getStrutsCustomI18nResources() == null) { > > CustomLocalizedTextUtil.setStrutsCustomI18nResources(strutsCustomI18nResources); > > CustomLocalizedTextUtil.clearDefaultResourceBundles(); > } > } > > /** > * @see com.opensymphony.xwork2.ActionSupport#getText(String) > */ > public String getText(String aTextName) { > return textProvider.getText(aTextName); > } > > /** > * This generates the Bootstrap String for the YesNoAll > Options. > */ > private void > createAutocompleteViewListForYesNoAllOptionsMap() { > yesNoAllList = new > ArrayList<SelectOptionView>(); > for (String[] yesNoAllOption : > YESNOALLDESCRIPTIONS) { > SelectOptionView > selectOptionView = new SelectOptionView(); > > selectOptionView.setLabel(getText(yesNoAllOption[1])); > > selectOptionView.setId(yesNoAllOption[0]); > > yesNoAllList.add(selectOptionView); > } > } > > /** > * This generates the Bootstrap String for the YesNoAll > Options. > */ > private void createAutocompleteViewListForYesNoOptionsMap() { > yesNoList = new ArrayList<SelectOptionView>(); > for (String[] yesNoOption : > YESNODESCRIPTIONS) { > SelectOptionView > selectOptionView = new SelectOptionView(); > > selectOptionView.setLabel(getText(yesNoOption[1])); > > selectOptionView.setId(yesNoOption[0]); > > yesNoList.add(selectOptionView); > } > } > > /** > * Load the Yes/No/All optionset map > */ > public void loadYesNoAllOptionsMap() { > > createAutocompleteViewListForYesNoAllOptionsMap(); > > createAutocompleteViewListForYesNoOptionsMap(); > } > > public List<SelectOptionView> getYesNoAllList() { > return yesNoAllList; > } > > public List<SelectOptionView> getYesNoList() { > return yesNoList; > } > > } > > Kind regards, > > Nate Kerkhofs > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@struts.apache.org > For additional commands, e-mail: user-h...@struts.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: user-unsubscr...@struts.apache.org For additional commands, e-mail: user-h...@struts.apache.org