2

I am struggling to get the JSON response from my Struts2 Action class, I think i am missing something. The following set up I have in my Project.

in my module level action definition , The configuration looks like :

<package name="customer" namespace="/" extends="struts-default,json-default">
   <action name="getCustomer" method="getCustomerBusiness" class="CustomerAction">
      <result type="json"/>
   </action>
</package>

in my Struts.xml I have

 <result-types>
    <result-type name="json" class="org.apache.struts2.json.JSONResult"/>
 </result-types>

 <interceptors>
    <interceptor name="json" class="org.apache.struts2.json.JSONInterceptor"/>
 </interceptors>

In My Action Class:

  public class CustomerAction extends ActionSupport implements ServletRequestAware,
        ServletResponseAware, ModelDriven {
    private List<CustomerBean> cpbeanList;

    public List<CustomerBean> getCpbeanList() {
        return cpbeanList;
    }

    public void setCpbeanList(List<CustomerBean> cpbeanList) {
        this.cpbeanList = cpbeanList;
    }

    public String getCustomerBusiness() {
        cpbeanList = new ArrayList<CustomerPortfolioBean>();
        // jsonData = new LinkedHashMap<String, Object>();
        CustomerBean cb1 = new CustomerPortfolioBean();
        cb1.setBusinessNm("IBM");
        cb1.setBusinessAddr("475 Anton Blvd");
        cb1.setBusinessPh("00000000");
        cb1.setBusinessCity("Costamesa");
        cb1.setBusinessStateCd("CA");
        c1.setBusinessZip("92704");

        similarly cb2, cb3, cb4.

        cpbeanList.add(cb1);
        cpbeanList.add(cb2);
        cpbeanList.add(cb3);
        cpbeanList.add(cb4);
        return SUCCESS;
    }

}

The JSON request http://localhost:8080/customer/getCustomer returns me empty array {} In the firebug ...I am able to see.

Also I am trying the out put as data table input in JQuery. which doesn't have row because of this.

Any one's help is greatly appreciated.

Roman C
  • 49,761
  • 33
  • 66
  • 176

2 Answers2

2

Your action's superclass implements ModelDriven, hence so does your subclass. It's the model that will be serialized as JSON. If the model is empty, there's nothing to be serialized, so you get nothing back.

Your subclass should override getModel() and return the data you want to be serialized to JSON.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
1

Since

  • The ModelDriven Interceptor pushes the model on top of the ValueStack
  • The Json Result serializes the whole action

and knowing that

  • The Json Result has a root parameter that can be configured to restrict the Json serialization to a single element instead of that to the whole action's attributes
  • The root parameter accepts OGNL

we can make the assumption that it could be instructed to go backwards,
to be less restrictive (from a modelDriven point of view), instead of more restrictive as usual.

You could try to do something like

<result type="json">
    <param name="root">
        [1]
    </param>
</result>

or even better (since it is not guaranteed that [1] is the action)

<result type="json">
    <param name="root">
        #action
    </param>
</result>

to discover if it's actually possible to serialize the whole action while maintaining the Model on top of the ValueStack.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • how can I access multiple fieldError as well as actionError, right now I am using fieldErrors – Govinda Sakhare Jan 28 '16 at 11:10
  • Just a note: `[1]` can be potentially dangerous because it might not point to action. – Aleksandr M Jan 28 '16 at 11:14
  • Sir can I have two root. fieldErrors and actionErrors – Govinda Sakhare Jan 28 '16 at 11:22
  • 1
    @piechuckerr: you can't have two roots. Have you tried, did it work ? IF it works, just return the action, and in the page where before you consumed `fieldErrors`, (eg looping `data`), just write `data.fieldErrors`, `data.actionErrors`, etc... Since action and field errors are on the **base** class, they won't be serialized unless you set a parameter that will force the serialization on the whole hierarchy: `false`. But apart from this being another question, let us know if the answer provided works :) – Andrea Ligios Jan 28 '16 at 13:53
  • 1
    @AleksandrM absolutely, IF they both works, the second is the safe one :) I'll edit the answer if OP confirm this works – Andrea Ligios Jan 28 '16 at 13:56
  • @piechuckerr thank you for the bounty. I've rejected the suggested edit because it was changing completely the meaning of the answer... I've not got what have you done, have you used #action or fieldErrors as root ? In the latter (that is not what I've described in my answer), please copy/paste that snippet in a new answer to this question, and I'll be happy to upvote it – Andrea Ligios Jan 29 '16 at 12:51
  • I've used root. will you tell me any book/blog etc to understand struts2 thoroughly? btw Thank you for helping me 'again'. – Govinda Sakhare Jan 29 '16 at 13:35
  • I know you've used root :) I mean: what value has root ? #action ? Or fieldErrors ? – Andrea Ligios Jan 29 '16 at 13:38