1

I want to submit a form to my action class with Struts 2 classic getter/setter way. All other fields get their value, except for a boolean field, which stays being false when I check the checkbox it corresponds.

I have a checkbox like this in my jsp:

<div class="col-md-3">
   <input class="input-md" type="checkbox" id="soloIdaId" name="soloIda" />
</div>

And in my action class I have:

private boolean soloIda;

and its getter/setter. But it stays to be false when I checked it.

I noticed that in the queryString contains:

...&soloIda=on&... (I am testing with FF)

And, if I try to get the parameter of request, I get true:

HttpServletRequest request = ServletActionContext.getRequest();
String soloIdaParam = request.getParameter("soloIda"); //"true" when I debug

Don't know if this matters, but I am using my interceptor. But I always include the defaultStack, and I believe the default interceptor is handling this kind of job(using getter/setter to assign values to fields). So why?

Attaching my struts.xml here:

 <interceptors>
    <interceptor name="authentication"
        class="com.WindThunder.interceptor.LoginInterceptor">
    </interceptor>
    <interceptor name="query"
        class="com.WindThunder.interceptor.QueryInterceptor">
    </interceptor>
    <interceptor-stack name="authStack">
        <interceptor-ref name="authentication"></interceptor-ref>
        <interceptor-ref name="defaultStack"></interceptor-ref> <!-- this
          line is necessary for every stack!!!! -->
    </interceptor-stack>
    <interceptor-stack name="pageStack">
        <interceptor-ref name="query"></interceptor-ref>
        <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
</interceptors>

<action name="searchCiudad" class="com.WindThunder.action.VueloAction"
      method="searchCiudad">
<interceptor-ref name="pageStack"/>
  <result name="success">/listaCiudads.jsp</result>
  <result name="error">/common/error.jsp</result>
  <result name="vacio">/common/listaVacia.jsp</result>
</action>

And my QueryInterceptor.java:

@Override
public String intercept(ActionInvocation invocation) throws Exception {
    //get previous action name = pagePath. (/searchxxx.action)
    this.session = invocation.getInvocationContext().getSession();
    HttpServletRequest request = ServletActionContext.getRequest();
    String path = request.getRequestURI(); //contaits domain
    String pagePath = path.substring(path.lastIndexOf("/"));

    //get previous query string (param1=xx&param2=xx, or null)
    String queryString = request.getQueryString();
    addParamToSession(queryString, session);
    String prePage = "";
    if (!pagePath.equalsIgnoreCase("/login.action")){
        prePage = pagePath;
    }
    if (prePage != null && !prePage.equals("")){
        session.put("prePage",prePage);
    }
    return invocation.invoke();
}

Now I want to get the parameter "soloIda" directly from request and do some manual assignment, but I think it is Struts 1's way of working. Any idea why it is not working? I must be doing something wrong.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
WesternGun
  • 11,303
  • 6
  • 88
  • 157

1 Answers1

1

It's not your Interceptor's fault... it's just that checkboxes are an ugly thing.

Things to know:

  1. What browsers send for checkboxes when a value is not specified is browser-specific;
  2. Browsers don't send anything for unchecked values (this may be irrelevant in case of Booleans because the default is false, but still...)

Then you could force the value with

<input class = "input-md"
        type = "checkbox" 
          id = "soloIdaId" 
        name = "soloIda" 
       value = "true" />

and then you'd need to deal with unckecked values.

To handle this situation, Struts2 provides you the <s:checkbox /> (and the <s:checkboxlist />) tag, with its value and fieldValue attributes, and the hidden parameter (__checkbox_something) that the tag generates to send something even when the checkbox is not checked. This parameter is then read by the Checkbox Interceptor.

Eg. from the docs:

<s:checkbox cssClass = "input-md"
                  id = "soloIdaId"
                name = "soloIda" 
          fieldValue = "true"
               value = "aBoolean" 
/>

will translate to the following HTML (with Simple Theme and Boolean aBoolean = true;):

<input type = "checkbox" 
      class = "input-md"
         id = "soloIdaId"
       name = "soloIda" 
      value = "true" 
    checked = "checked"
/>
<input type = "hidden"  
         id = "__checkbox_soloIdaId" 
      value = "true" 
       name = "__checkbox_soloIda" 
/>

Read the Mkyong example on <s:checkbox /> and also this SO answer to better understand where to start.

Always consider using the framework specific tags (at least at first), that already handles many problems for you transparently.

Community
  • 1
  • 1
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • Sorry for late reply. I don't know why but `` is not following my Boostrap CSS rules while `` is fine. And at last, so I decided to use `` and get the parameters from `HttpServletSession` directly.... But anyway thanks. It's not a project for production just a homework to do so I am often getting my hands dirty right now. But I will accept your answer and save it for furture use coz you are providing great references and much info here. – WesternGun Oct 28 '15 at 12:27
  • 1
    @FaithReaper don't give up: I know *exactly* why it doesn't follow your Bootstrap CSS rules, [it's all explained here](http://stackoverflow.com/a/28558436/1654265). Then, if you are not using the Bootstrap Plugin (and you don't need to, if you already know how to write plain Bootstrap), simply add `theme="simple"` to your `` tags. That's it. I suggest you to try even if you've already moved on after this, in order to learn the best practices instead of the voodoo you've ended up with. Please consider **upvoting** the answer(s) that helped you, it's the best thank for their authors – Andrea Ligios Oct 28 '15 at 12:53
  • I tried `theme="simple"` and it worked, great! But I cannot submit my value to my action class, which is an `Integer`. When I tick this checkbox, I want to pass the `ID` of this flight to my class but it's not working(error in console: `Missing key [invalid.fieldvalue.reservaChecked] in bundles [[org/apache/struts2/struts-messages, com/opensymphony/xwork2/xwork-messages]]!` while I have set `fieldValue="true"`. But `` is working. Besides, I want it to be single-selected, not multiple-selcted. – WesternGun Oct 28 '15 at 20:41
  • You still haven't up-voted any answer :( BTW you should edit your question adding the details because in comment it is very difficult to get them; that said, I guess that with your last `` is a typo for ``, otherwise I'm lost. Also reservaChecked is not in your code, but it is in your error message, that however seems to be i18n related... meh – Andrea Ligios Oct 28 '15 at 21:57
  • I have voted up your answer, and no, it´s not a typo: `radio` is working for me but `checkbox` and `s:checkbox` is not. And, as I only want to select one option, and `radio` allows me to do it (and `checkbox` doesn't), so I chose `radio` at last. `reservaChecked` is a `List` I defined in my action class, to receive all checkbox/radio, if there's more than one `` with different values but same name. I may edit my question later and thanks anyway. – WesternGun Oct 28 '15 at 22:39
  • Absolutely: if you have multiple choices, use a checkbox, if you have a single choice, use a radio. Checkboxes on a single choice are just the wrong tools for the job. Thank you for the upvote, and consider opening a new question if the edit part changes this question substantially, otherwise just warn me of the edit – Andrea Ligios Oct 29 '15 at 09:16