6

I am trying to send value of a field to Struts2 back-end through JavaScript but it returns NullpointerException.

<input type="hidden" id="employee.payslip.id" name="employee.payslip.id" value="5"/>
....

Once form is submitted the request will be sent to the following JavaScript method to be sent to back-end.

 function payslipPayment(){

     var formValues = $('#myform').serialize();
     ....
     xmlhttp.open("get","../payslip/pay?"+formValues,false);
     xmlhttp.send();

 }

the request will be created and sent as following

http://localhost/payslip/pay/employee.payslip.id=5&employee.payslip.year=2013&....

But in back-end when I try to show the value it returns NullPointerException.

Java:

public class payslip {

 private Employee employee;

 public String pay{
    System.out.println("Id:"+employee.payslip.id):
    System.out.println("Year:"+employee.payslip.year;
    ...
 }

 getter and setter 

}

Classes:

public class Employee {
   private Payslip payslip;
   ....
   getter and setter
}

public class Payslip{
  private long id;
  ...
  getter and setter
}
Roman C
  • 49,761
  • 33
  • 66
  • 176
J888
  • 1,944
  • 8
  • 42
  • 76
  • the problem is serialize in js, and unserialize in java. so you should think is the serialized pass to java correctly and is java unserialize correctly after it got the right string – farmer1992 Oct 31 '13 at 06:01
  • the problem is that I do not know how to figure that out? – J888 Oct 31 '13 at 22:16
  • 1
    What framework are you using to parse the parameter in HTTP request to the Java classes? – leesei Nov 07 '13 at 04:11
  • 1
    Should `http://localhost/payslip/pay/employee.payslip.id = 5` be `http://localhost/payslip/pay/employee.payslip.id=5` (no space)? – leesei Nov 07 '13 at 04:12
  • @leesei that was my typo, in application there is no space. – J888 Nov 07 '13 at 04:14
  • is it possible to use some JS framework like jQuery? – Code2Interface Nov 07 '13 at 05:44
  • @panky1986 sure go ahead please – J888 Nov 07 '13 at 05:54
  • 1
    The shown URL 'http://localhost/payslip/pay/' does not have '?' but the code does so it should be fine. I am guessing 'pay' action is mapped to 'payslip' class and the 'pay' method. Also that by `employee.payslip.id` you actually mean `employee.getPayslip().getId()`. They should work just fine. Can you say if `employee` reference itself is null or if `getPayslip()` returns null ? – Ravindra HV Nov 08 '13 at 12:37
  • @J888 Can you provide the full error stacktrace?? – Pratik Shah Nov 12 '13 at 09:21

8 Answers8

3

Null pointer exception means employee or payslip is not initialized. If youre using struts2 then using param interceptor and model driven approach should solve your issue.

Code2Interface
  • 495
  • 2
  • 7
  • That's what I wanted to say as well. However its not clear why the current approach is not working. – Ravindra HV Nov 09 '13 at 11:56
  • @RavindraHV Guys, does that mean sending the request to action directly and not using javascript, if not would you give me an example plz – J888 Nov 12 '13 at 01:10
  • @J888 You still need to hit the action on the server end. You can use HTML-Forms or JavaScript-XHR. Both are fine from a server perspective. In model driven, the model (bean) is explicitly defined (and instantiated per request). If you have any setters in the action that is not intended to be set by requests, by using model driven, a request parameter with the same name as the field will not be assigned unintentionally. As such its always a safer option. – Ravindra HV Nov 12 '13 at 16:58
2
  • You need to convert your form to json (like here) and send to the back end
  • Then - in java you need to deserialize the json to a java object (for example, with Jackson)
Community
  • 1
  • 1
Alexey Grigorev
  • 2,415
  • 28
  • 47
2

You can do like Alexey has said or you can follow this approach. You can use the interfaces ServletRequestAware and ServletResponseAware and then use request.getParameter() to get the value that is passed. Below is an example of how to do this.

Action class struts config

<action name="hello" method="execute"
            class="com.home.struts2.HelloAction">
            <result name="success">hello.jsp</result> 
        </action>

Action Class

 public class HelloAction extends ActionSupport implements ServletRequestAware,ServletResponseAware{
        HttpServletResponse response;
        HttpServletRequest request;

        public String execute() {

             System.out.println("AjaxCall" + request.getParameter("param"));
              String infoXml = "Parameter passed: " + request.getParameter("param");
              response.setContentType("text/html");
                response.setHeader("Cache-Control", "no-cache");
                try {
                    response.getWriter().write(infoXml);
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }

                return null;

        }

        public void setServletResponse(HttpServletResponse response) {
            this.response = response;
        }

        public void setServletRequest(HttpServletRequest request) {
            this.request = request;
        }

        public HttpServletRequest getServletRequest() {
            return this.request;
        }

    }

JavaScript

var xmlHttp;
function sendreq(){  

        var URL = "hello.action?param=sandy";
        try{
            xmlHttp=new XMLHttpRequest();
        }catch (e){
            try{
                xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
            }catch (e){
                try{
                    xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
                }catch (e){
                    alert("Your browser does not support AJAX!");
                    return false;
                }
            }
        }

        xmlHttp.onreadystatechange = showMessage;

        xmlHttp.open("GET", URL, true);

        xmlHttp.send(null);
    }
karthick
  • 11,998
  • 6
  • 56
  • 88
  • thanks, does that work if 10 different values are being passed ? – J888 Nov 07 '13 at 05:55
  • It will all you have to do is pass it properly in the get call and retrieve it using request.getParameter() – karthick Nov 07 '13 at 05:59
  • JS: var URL = "hello.action?param=sandy&param2=xxx"; Java: request.getParameter('param2') – karthick Nov 07 '13 at 05:59
  • I suppose in that case I need to have 10 of this line System.out.println("AjaxCall" + request.getParameter("param")); for each value am I right? Isn't it possible to pass them as object by any chance? – J888 Nov 07 '13 at 06:00
  • you can simply pass the 10 different values as a string separated by a pipe or any identifier and get that string in java in one parameter and split it using the identifier. This is one option or you can use a json – karthick Nov 07 '13 at 06:01
2

Are you using a framework, or just a plain servlet? If you're using a framework like struts, then all of these answers are way too complicated.

I think you are using just a mapped servlet by the looks of it, which means the answer above is correct about passing named parameters through the url. You can hide these named parameters a little more using post, rather than get though.

Here's how I would do it using just a servlet. Though, if I were you and doing a full project, I would use JSF, for easier passing of data.

java

public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    String payslipID = request.getParameter("payslipid");
}

js

<script>
var payslipid = $('#employee_payslip_id')
xmlhttp.open("POST","../payslip/pay",false);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("payslipid="+payslipid);
</script>

As mentioned in the other post though, you would have to get (and place in post or get get data) all the parameters individually unless you did some separated list of strings. This isn't really a ridiculous thing to do that because you will need to separate all of those values into their own variables in the java anyway.

EDIT:

The above answer actually says what you need to do but maybe it would help to make it more clear. In your struts configuration files where you define the action such as

<action class="org.example.Payslip" name="payslip">
            <interceptor-ref name="params"/>
            <result name="success">/success.jsp</result>
</action>

Make sure to have the params interceptor there. It will make it so the server maps the params to the setters. Then you won't need to do the getparameter call for each thing you send.

Also the url should be something like .../payslip.action!pay?payslipid=1234&employeeid=1234 if you have it mapped like above. This tell it to use the payslip.class and the pay function.

dhockey
  • 312
  • 1
  • 11
  • 1
    Actually, I am using Struts2, thats why struts2 is defined as a tag of question and I have heaps of parameters not just payslipid – J888 Nov 07 '13 at 22:27
  • Sorry, I didn't notice the struts tag. I am working on a really big struts project, so I think I may have address your problem now above. – dhockey Nov 12 '13 at 19:18
  • 1
    thats great thanks, but the only problem is that I would be forced to use a long list of variables in my action class, so if I want to send them to another class need to have a long list of parameters in my function call or create a new object and put them all in that objects variables, is there any way around it ? – J888 Nov 14 '13 at 05:17
  • 1
    a long list of parameters in my function call otherclass.mymethod(var1,var2,var3,var4,.....) – J888 Nov 14 '13 at 05:25
  • 1
    what you are mentioning is related to struts1 not 2 –  Nov 14 '13 at 07:51
2

Struts2 uses params interceptor to populate form values submitted by HTTP request.

It's recommended to use POST method, so if you have sensitive data and you want it is not reflected in the URL.

Parameter names are used by the interceptor to pass through OGNL runtime to evaluate the expression which should find reference in the valueStack.

You've got NullPointerException because you didn't initialize or inject the dependencies to the object which reference is evaluated by OGNL. Because you are using nested beans, all nested properties should be accessible and initialized (or at least Struts2 knows how to create these objects), and belong to the action class that is placed on the top of the value stack.

Roman C
  • 49,761
  • 33
  • 66
  • 176
2
  1. Implement the serializable interface for Employee & Payslip. Also, make sure both have empty constructors.

  2. Enable struts2 devMode for additional logs. After enabling you'll see OGNL exceptions, about which field in particular is giving the issue. That error must be very straight forward to handle. http://www.mkyong.com/struts2/struts-2-development-mode-example/

  3. I guess there's some issue with the interceptor stack used for that action, just try using defaultStack.

<action name="payslip/pay" class="...">
    <interceptor-ref name="defaultStack"/>
    <result name="success">/success.jsp</result>
    <result name="input">/error.jsp</result>
</action>
coding_idiot
  • 13,526
  • 10
  • 65
  • 116
2

add input param in action tag; that lets you communicate the parameter from struts action class to the form/.jsp

struts.xml

<action name="..." class="UserAction">
 <param name="id"></param>
 <result name="input">/WEB-INF/jsp/User.jsp</result>
</action>

Action class

public class UserAction {
private int id;

// this is called by the struts.xml to set the value
public void setId(int id) {
this.id = id;
}

//a getter is needed as well to display value in the .jsp

}

since, it's a hidden variable not part of valuestack you can try passing it this way.

if this is not your problem; I think you have to inject the bean into the Action Class. @Inject Employee; bean into Action class would help.

Also debug the valuestack.

user1769790
  • 1,183
  • 3
  • 11
  • 23
1

You need to use ModelDriven interface. Implement the ModelDriven and override its method then return your object using method of modelDriven.

Struts2 Documentation