Trying to use validate method on Struts 2.3.4 but got below error:
java.lang.NullPointerException
at com.action.LogonAction.validate(LogonAction.java:66) more......
Action class:
public class LogonAction extends ActionSupport{
private Logon logon;
public Logon getLogon() {
return logon;
}
public void setLogon(Logon logon) {
this.logon = logon;
}
public String execute(){
return SUCCESS;
}
public void validate(){
if(logon.getUserName() == null || logon.getUserName().equals("")){
addFieldError("logon.userName", "userName required");
}
}
Logon.class:
public class Logon {
private String password;
private String userName;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
struts.xml:
<struts>
<package name="struts2" namespace="/" extends="struts-default">
<action name="login" class="com.action.LogonAction">
<result name="input">Login.jsp</result>
<result name="success">success.jsp</result>
</action>
</package>
jsp:
<s:form action="login" method="post">
<table>
<tr>
<td>User name:<s:textfield name="userName"/>
<tr>
<td><s:submit type="button" value="submit" label="Submit" /></td>
</tr>
</table>
</s:form>
Is there any way to fix this other than using the new version of Struts2? Because I found one post said that Struts 2.3.4 have validate method bug.
You have NullPointerException
in the code below
if(logon.getUserName() == null || logon.getUserName().equals("")){
this can only happen if logon
is null
.
If you have only one action in the action class that populates properties from the submitted form, you can just bind the input controls to action class properties via OGNL.
<s:form action="login" method="post">
<table>
<tr>
<td>User name:<s:textfield name="logon.userName" />
<tr>
<td><s:submit type="button" value="submit" label="Submit" /></td>
</tr>
</table>
Here, logon.userName
is OGNL expression that evaluates to render a value
of the textfield. Unless you explicitly specify a value
attribute the expression is called.
It uses a call getLogon().getUserName()
on the action instance. Since you didn't initialize the logon
property before the result is executed then it will throw another NullPointerException
but it's caught internally and ignored. The texttfield tag renders nothing in this case. And you might feel that it works!?
Because when you submit the form it uses a value from the name
attribute of the textfield and passes it as a request parameter. This parameter name then parses for OGNL. It's the same OGNL expression logon.userName
, but Struts will use getLogon().setUserName()
on the action instance to set the value of the parameter.
The reasonable question why it doesn't throw exception, i.e. why the call to getLogon()
returns a Logon
instance? This is Struts2 magic. It can handle null
values between calls getLogon()
and setUserName()
. By default it creates an object if it's not yet created. You can control this behavior using a constant in struts.xml
.
But, in my point of view you should create it yourself or with the container that has DI, that provides the beans configuration like Spring.
private Logon logon = new Logon();
Struts2 mostly used to map many actions to the same action class and not only to execute
method. Thus having a bean initialized will safely keep you of the errors reproduced internally or externally when actions are called.