Struts 6.4, Ognl and getters without an underlying field

Nate Kerkhofs <[email protected]>
Newsgroups gmane.comp.jakarta.struts.user
Message-ID <AM0P191MB08042091E8084C8442DB1159EB712@AM0P191MB0804.EURP191.PROD.OUTLOOK.COM>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.