Im trying some ajax call with Struts2 and the JQuery library. This is the code of the jsp :
<s:div id="my_result" >
Nothing
</s:div>
<s:form action="UserManager" theme="simple">
<s:textfield name="nickname" />
<s:password name="password" />
<s:label cssClass="menu_span">
<sj:submit targets="my_result" value="Login" />
</s:label>
</s:form>
this is the code of the bean/action with the xml :
public class UserManager extends ActionSupport {
private String nickname;
private String password;
#Override
public String execute() throws Exception {
String output="i have insered "+this.getNickname()+" and "+this.getPassword();
System.out.println(output);
return output;
}
public String getNickname() { return nickname; }
public void setNickname(String newValue) { nickname=newValue; }
public String getPassword() { return password; }
public void setPassword(String newValue) { password=newValue; }
}
<package name="model" extends="struts-default">
<action name="UserManager" class="model.UserManager">
<result>index.jsp</result>
</action>
</package>
If i return SUCCESS on the UserManager bean, it load on my_result the same calling page. Else, if i return output i get Messages:
No result defined for action model.UserManager and result i have insered aaa and bbb
messagge (with nickname=aaa and password=bbb).
What's happened? How can i return that string? I think it's a struts.xml fault
Cheers
UPDATE
public class UserManager extends ActionSupport {
private String nickname;
private String password;
private String error;
#Override
public String execute() throws Exception {
error="i have insered "+this.getNickname()+" and "+this.getPassword();
return SUCCESS;
}
public String getNickname() { return nickname; }
public void setNickname(String newValue) { nickname=newValue; }
public String getPassword() { return password; }
public void setPassword(String newValue) { password=newValue; }
public String getError() { return error; }
public void setError(String newValue) { error=newValue; }
}
<s:div id="my_result" >
<s:property value="error" />
</s:div>
<s:form action="UserManager" theme="simple">
<s:textfield name="nickname" />
<s:password name="password" />
<s:label cssClass="menu_span">
<sj:submit targets="my_result" value="Login" />
</s:label>
</s:form>
UPDATE 2
<package name="model" extends="json-default">
<action name="UserManager" class="model.UserManager">
<result type="json" />
</action>
</package>
The return value that you return in the execute() method must be one of the mapped as values.
As you have not a result name like this:
<result name="resultName"></result>
It will use the default one: "success". You have to return "success" value in execute() method.
The result value of the execute method is the name of the result mapped. To send a message you have to add a String attribute in your Action (and a getter to obtain it), and in the execute method do something like
this.message = "my message";
Edit: how to get the message with ajax:
If you have set the message in your action in an attribute called "String message" and you have a getter for that attribute (public String getMessage()) you can get this information accesing this property in the object you get in the ajax call. If you do the ajax call for example with jquery you can get it in this way:
$.ajax({
url: '/yourAjaxUrl',
success: function(data) {
var message = data.message;
alert('The message is '+message);
$('#my_result').html(message);
}
});
Edit:
In the struts xml in your package tag you have to define the json type:
<result-types>
<result-type name="json" class="com.googlecode.jsonplugin.JSONResult">
...
</result-types>
and add the json-plugin.jar which can be downloaded here
more info in http://code.google.com/p/jsonplugin/wiki/Documentation
Related
This is my controller Login.java
import com.opensymphony.xwork2.ActionSupport;
public class Login extends ActionSupport {
private String userName;
private String password;
public Login() {
}
public String execute() {
return SUCCESS;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
This is my Login-Validation.xml
<?xml version="1.0"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="userName">
<field-validator type="requiredstring">
<message>User Name is required.</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="password.required" />
</field-validator>
</field>
</validators>
This is my struts.xml
<action name="NewLogin">
<result>login.jsp</result>
</action>
<action name="LoginAction" class="com.strut.Login">
<result name="success">success.jsp</result>
<result name="input">fail.jsp</result>
</action>
I am using struts2-core 2.5.16 as the maven plugin.
The issue is the controller is not considering my validation.xml. It directly passes to the execute method and goes to the success page.
I have placed the controller and validation xml within the same package.
Could someone help me with it? Thanks in advance.
Your file that named "Login-Validation.xml" is error.
Solution:
1. The validation xml file should be named the "Login-validation.xml".
2. The <result name="input" >fail.jsp</result> had been changed to <result name="input" >login.jsp</result>. This will be better and logical.
I am trying to get model validation working with my spring boot mvc application. I am using freemarker as view templates. My problem is now that even though model validation works as expected the model errors are not shown in my view.
Here is some example code. The Model:
public class TestModel {
#Size(min=2, max=10)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The Controller
#Controller
#RequestMapping("/test")
public class OrderController extends BaseController {
#RequestMapping(value = "new/greenhouse", method = RequestMethod.GET)
public String get(#ModelAttribute TestModel testModel) {
testModel.setName("Hello world");
return "test.ftl";
}
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String post(#ModelAttribute #Valid TestModel testModel, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// The bindingResult contains the "correct" errors
return "test.ftl";
}
return "redirect:/";
}
}
The view:
<#import "../layout.ftl" as layout />
<#import "/spring.ftl" as spring />
<#import "../freemarker.ftl" as ftl />
<#layout.defaultLayout>
<form action="/test" method="post">
<#ftl.csrfToken />
Name:
<#spring.formInput "testModel.Name" />
<#spring.showErrors "<br>" /> <#-- Does not print the error as status.errorMessages is not populated -->
<#-- This will at least display the default Message -->
<#list spring.status.errors.allErrors as error>
<span class="has-error">${error.defaultMessage} </span>
</#list>
</form>
</#layout.defaultLayout>
Any idea why status.errorMessages does not get populated?
So I finally found the solution to this:
The property name in the Freemarker view has to be lowercase (as is the private member name in the model class). The correct view would look like this:
<#spring.formInput "testModel.name" />
<#spring.showErrors "<br>" />
I'm new to Spring MVC and I have an error with a form validation and I don't know why.
This is the model:
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Size;
import org.springframework.stereotype.Component;
#Component
public class Search implements Serializable {
#Size(max = 20)
private String userInput;
#Size(max = 10)
private String ascending;
#Size(max = 10)
private String descending;
#Temporal(TemporalType.DATE)
private Date fromDate;
#Temporal(TemporalType.DATE)
private Date toDate;
#Size(max=100)
private String genres;
public String getGenres() {
return genres;
}
public void setGenres(String genres) {
this.genres = genres;
}
public String getUserInput() {
return userInput;
}
public void setUserInput(String userInput) {
this.userInput = userInput;
}
public Date getFromDate() {
return fromDate;
}
public void setFromDate(Date fromDate) {
this.fromDate = fromDate;
}
public Date getToDate() {
return toDate;
}
public void setToDate(Date toDate) {
this.toDate = toDate;
}
}
Here is the form:
<%# taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<sf:form action="/newSearch" method="post" modelAttribute="search">
<sf:input path="userInput" type="text" class="input_style" id="userInput" />
<button class="search_button"><img class="search_icon" src="resources/img/search/search_icon.png" /></button>
<sf:select id="genres" path="genres" multiple="multiple">
</sf:select>
<sf:input id="fromDate" path="fromDate" />
<sf:input id="toDate" path="toDate" type="text" />
<sf:input id="ascending" path="ascending" type="radio" checked="checked" />
<sf:input id="descending" path="descending" type="radio" />
</sf:form>
and here is the Controller:
#RequestMapping(value = "/newSearch", method = RequestMethod.POST)
public String getSearch(#Valid Search search, BindingResult result, Model m) {
if(result.hasErrors()) {
return "home";
}
System.out.println("----------------Search--------------------");
System.out.println(search.getGenres());
System.out.println(search.getUserInput());
return "search";
}
The error is:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'search' available as request attribute
Add #ModelAttribute("search") before #Valid making the method's signature look like
public String getSearch(#ModelAttribute("search") #Valid Search search, BindingResult result, Model m)
Also try
<sf:form action="/newSearch" method="post" commandName="search">
instead of
<sf:form action="/newSearch" method="post" modelAttribute="search">
I am trying to implement validation using annotations, but these validations don't work and the form gets submitted with null values.
I don't know what is missing, how to implement validations using annotations in struts2 in action that implements ModelDriven interface?
This is my struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="saveOrUpdateUser" method="saveOrUpdate1" class="com.vaannila.web.Userqqqq">
<result name="success" type="redirect">listUser</result>
<result name="input">/register.jsp</result>
</action>
<action name="listUser" method="list" class="com.vaannila.web.Userqqqq">
<result name="success">/register.jsp</result>
<result name="input">/register.jsp</result>
</action>
<action name="editUser" method="edit" class="com.vaannila.web.Userqqqq">
<result name="success">/register.jsp</result>
<result name="input">/register.jsp</result>
</action>
<action name="deleteUser" method="delete" class="com.vaannila.web.Userqqqq">
<result name="success" type="redirect">listUser</result>
<result name="input">/register.jsp</result>
</action>
</package>
</struts>
This is my jsp page
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%#taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Page</title>
<s:head />
<style type="text/css">
#import url(style.css);
</style>
</head>
<body>
<s:actionerror/>
<s:form action="saveOrUpdateUser" validate="true">
<s:push value="user">
<s:hidden name="id" />
<s:textfield name="name" label="User Name" required="true"/>
<s:radio name="gender" label="Gender" list="{'Male','Female'}" />
<s:select name="country" list="{'India','USA','UK'}" headerKey=""
headerValue="Select" label="Select a country" />
<s:textarea name="aboutYou" label="About You" />
<s:checkbox name="mailingList"
label="Would you like to join our mailing list?" />
<s:submit />
</s:push>
</s:form>
<s:if test="userList.size() > 0">
<div class="content">
<table class="userTable" cellpadding="5px">
<tr class="even">
<th>Name</th>
<th>Gender</th>
<th>Country</th>
<th>About You</th>
<th>Mailing List</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<s:iterator value="userList" status="userStatus">
<tr
class="<s:if test="#userStatus.odd == true ">odd</s:if><s:else>even</s:else>">
<td><s:property value="name" /></td>
<td><s:property value="gender" /></td>
<td><s:property value="country" /></td>
<td><s:property value="aboutYou" /></td>
<td><s:property value="mailingList" /></td>
<td><s:url id="editURL" action="editUser">
<s:param name="id" value="%{id}"></s:param>
</s:url> <s:a href="%{editURL}">Edit</s:a></td>
<td><s:url id="deleteURL" action="deleteUser">
<s:param name="id" value="%{id}"></s:param>
</s:url> <s:a href="%{deleteURL}">Delete</s:a></td>
</tr>
</s:iterator>
</table>
</div>
</s:if>
</body>
</html>
This is my action class
package com.vaannila.web;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.vaannila.dao.UserDAO;
import com.vaannila.domain.User;
public class UserAction extends ActionSupport implements ModelDriven<User> {
private static final long serialVersionUID = -6659925652584240539L;
private User user = new User();
private List<User> userList = new ArrayList<User>();
private UserDAO userDAO = new UserDAO();
#Override
public User getModel() {
return user;
}
/**
* To save or update user.
* #return String
*/
public String saveOrUpdate()
{
System.out.println(user.getName());
userDAO.saveOrUpdateUser(user);
return SUCCESS;
}
/**
* To list all users.
* #return String
*/
public String list()
{
userList = userDAO.listUser();
return SUCCESS;
}
/**
* To delete a user.
* #return String
*/
public String delete()
{
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
userDAO.deleteUser(Long.parseLong(request.getParameter("id")));
return SUCCESS;
}
/**
* To list a single user by Id.
* #return String
*/
public String edit()
{
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
user = userDAO.listUserById(Long.parseLong(request.getParameter("id")));
return SUCCESS;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
This is my BEAN
package com.vaannila.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator;
import com.opensymphony.xwork2.validator.annotations.ValidatorType;
#Entity
#Table(name="USER1")
public class User {
private Long id;
private String name;
private String gender;
private String country;
private String aboutYou;
private Boolean mailingList;
#Id
#GeneratedValue
#Column(name="USER_ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "name", message = "User Name field is empty.")
#Column(name="USER_NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "gender", message = "gender field is empty.")
#Column(name="USER_GENDER")
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#Column(name="USER_COUNTRY")
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
#Column(name="USER_ABOUT_YOU")
public String getAboutYou() {
return aboutYou;
}
public void setAboutYou(String aboutYou) {
this.aboutYou = aboutYou;
}
#Column(name="USER_MAILING_LIST")
public Boolean getMailingList() {
return mailingList;
}
public void setMailingList(Boolean mailingList) {
this.mailingList = mailingList;
}
}
You need to add #VisitorFieldValidator annotation to user getter inside your action class.
#VisitorFieldValidator(appendPrefix = false)
public User getUser() {
return user;
}
Note that you need to set appendPrefix to false if your are using field names without user. prefix in JSP.
Also, you are probably want #RequiredStringValidator not #RequiredFieldValidator inside your bean.
#RequiredStringValidator(message = "User Name field is empty.")
#Column(name="USER_NAME")
public String getName() {
return name;
}
I've configured my sturts2 application to use the validation xml for my actions. I also have fieldexpression working.
Would it be possible to call a method from my action in the expression.
eg:
<field name="myField">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[
#com.test.MyClass#isCaptchaOk(keyString, userResponce)
]]></param>
<message>My credit limit should be MORE than my girlfriend's</message>
</field-validator>
</field>
Here is my actual test code, the simple fieldexpression works, but function call one does not (see the tbox1).
I'm not sure if the #class#method path is ok or not, but is not working
coz, I've added log in the functions but nothing comes up, so i presume the validator can't reach the functions.
Also, Is this possible, ie is it allowed or am i being too ambitious.
Thanks
PS I've corrected the message, I'm not trading my girlfriend ;-)
**** validation.xml
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="tbox1">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[#uk.co.nhbc.userRegistration.action.Test2Action#getString()]]></param>
<message>function call message here</message>
</field-validator>
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[#uk.co.nhbc.userRegistration.action.Test2Action#isCaptchaOk(tbox1, user.username)]]></param>
<message>function call message here</message>
</field-validator>
</field>
<field name="tbox2">
<field-validator type="stringlength">
<param name="maxLength">5</param>
<message>length messssage here</message>
</field-validator>
</field>
<field name="user.username">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[(!(tbox2 == "aa" && user.username.equals("")))]]></param>
<message>tbox2 eq aa and username is empty messssage2 here</message>
</field-validator>
</field>
</validators>
******* java class
package uk.co.nhbc.userRegistration.action;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import uk.co.nhbc.common.action.BaseAction;
import uk.co.nhbc.userRegistration.model.Users;
public class Test2Action extends BaseAction {
private String tbox1;
private String tbox2;
private Users user;
private static final Log log = LogFactory.getLog(Test2Action.class);
public String execute() {
return SUCCESS;
}
public String getTbox2() {
return tbox2;
}
public void setTbox2(String tbox2) {
this.tbox2 = tbox2;
}
public String getTbox1() {
return tbox1;
}
public void setTbox1(String tbox1) {
this.tbox1 = tbox1;
}
public Users getUser() {
log.debug("get user called");
return user;
}
public void setUser(Users user) {
log.debug("set user called");
this.user = user;
}
public boolean isCaptchaOk(String challenge, String response) {
//dummy test function
log.debug("captcha function called");
if (response.equals("true"))
return true;
return false;
}
public String getString (){
log.debug("getString function called");
return "hello";
}
}
*********and jsp page
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags"%>
<%# taglib prefix="sj" uri="/struts-jquery-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<s:form name="formtest" action="Test2Action">
<s:actionerror/>
<s:fielderror></s:fielderror>
<s:textfield name="tbox1" label="box1"></s:textfield>
<s:textfield name="tbox2" label="box1"></s:textfield>
<s:textfield name="user.username" label="boxuser"></s:textfield>
<s:submit></s:submit>
</s:form>
</body>
</html>
In order to calling a static method in expression, which must be OGNL, you should enable struts.ognl.allowStaticMethodAccess by adding below constant to struts.xml file:
< constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
See my updated working validator file. for field tbox1 in the fieldexpression I'm referring to the method directly as it is my action, which would be on the VS.
tbox1 and user.username are items on the jsp page (and also exist in the action)
I tried to experiment with a static method, but that didn't work, (no time to investigate now).
Hope this helps
and thanks dave for the input.
***updated validation xml
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="tbox1">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[isCaptchaOk(tbox1, user.username)]]></param>
<message>function call message here</message>
</field-validator>
</field>
<field name="tbox2">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[(#uk.co.nhbc.userRegistration.action.Test2Action#isFuncOk(tbox2))]]></param>
<message>func okk function call message here</message>
</field-validator>
</field>
<field name="user.username">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[(!(tbox2 == "aa" && user.username.equals("")))]]></param>
<message>tbox2 eq aa and username is empty messssage2 here</message>
</field-validator>
</field>
</validators>
***updated java class
package uk.co.nhbc.userRegistration.action;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import uk.co.nhbc.common.action.BaseAction;
import uk.co.nhbc.userRegistration.model.Users;
public class Test2Action extends BaseAction {
private String tbox1;
private String tbox2;
private Users user;
private static final Log log = LogFactory.getLog(Test2Action.class);
public String execute() {
return SUCCESS;
}
public String getTbox2() {
return tbox2;
}
public void setTbox2(String tbox2) {
this.tbox2 = tbox2;
}
public String getTbox1() {
return tbox1;
}
public void setTbox1(String tbox1) {
this.tbox1 = tbox1;
}
public Users getUser() {
log.debug("get user called");
return user;
}
public void setUser(Users user) {
log.debug("set user called");
this.user = user;
}
public boolean isCaptchaOk(String challenge, String response) {
//dummy test function
log.debug("captcha function called");
log.debug("captcha function called"+challenge+response);
if (response.equals("true"))
return true;
return false;
}
public String getString (){
log.debug("getString function called");
return "hello";
}
public static boolean isFuncOk (String response){
log.debug("isFuncOk function called"+response);
if (response.equals("true"))
return true;
return false;
}
}