I tried to implement token interceptor with the <s:url .. tag but its showing error on the first click. i.e.
The form has already been processed or no token was supplied, please try again.
I want to implement this interceptor, because if users already deleted a row and refresh the page once again then the same action should not perform once again.
<s:url id="linkdelete" action="DeleteLatestUpload.action" namespace="/admin/insecure/upload">
<s:param name="latestUploadId" value="latestUploadId"></s:param>
<s:token name="token"></s:token>
</s:url>
Clear current Uploads
and my struts.xml:
<action name="DeleteLatestUpload" class="v.esoft.actions.UploadExcel" method="deleteUploads">
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="basicStack"></interceptor-ref>
<result name="success" type="tiles"> uploadforward</result>
<result name="invalid.token" type="tiles">uploadforward </result>
</action>
The s:token tag merely places a hidden element that contains the
unique token.
There's not need to use token with url, because the form should be submitted. If you want to pass some token as a parameter then you need to use s:param tag.
Define the parameter
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String execute() throws Exception {
Map<String, Object> context = ActionContext.getContext().getValueStack().getContext();
Object myToken = context.get("token");
if (myToken == null) {
myToken = TokenHelper.setToken("token");
context.put("token", myToken);
}
token = myToken.toString();
return SUCCESS;
}
in the JSP
<s:url var="linkdelete" namespace="/admin/insecure/upload" action="DeleteLatestUpload" ><s:param name="struts.token.name" value="%{'token'}"/><s:param name="token" value="%{token}"/></s:url>
The most simple way to use token with url is to use <s:token/> tag to set token value into session and retrieve it in <s:param> tag.
<s:token/>
<s:url var="..." action="...">
<s:param name="struts.token.name" value="'token'"/>
<s:param name="token" value="#session['struts.tokens.token']"/>
</s:url>
Related
I have an application where i login and it takes me to the next page and displays a table.
I have handled session by implementing the SessionAware interface.
When i refresh the page with the refresh button on the browser or F5, it works fine. However, if i press enter on the url, it takes me to the login page because the username and password is null.
Please find below my java code and jsp code and struts.xml
JAVA class:
public String Authentication()
{
// return userInfo.getUserLoginId() + "_BUSINESS_SERVICES";
if(j_username == null)
{
status="failure3";
return status;
}
System.out.println("get username and get password" +j_username + j_password);
// if no userName stored in the session,
// check the entered userName and password
if (j_username != null && j_password != null) {
System.out.println("inside function");
// add userName to the session
sessionMap.put("j_username", j_username);
status = otlAuthenticationController.loginAuthentication(j_username,j_password);
if(status == "success")
{
this.otlUserList= otlAuthenticationController.obtainList();
System.out.println("size is"+otlUserList.size());
}
}
return status;
}
public String logout()
{
if (sessionMap instanceof org.apache.struts2.dispatcher.SessionMap) {
try {
//((org.apache.struts2.dispatcher.SessionMap) sessionMap).invalidate();
if (sessionMap.containsKey("userName")) {
sessionMap.remove(j_username);
System.out.println("session killed");
status ="success";
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
return "success";
}
JSP page:
<div class="label" style="margin-top:10px;"><s:text name="login.password" /></div><input id="j_password" name="j_password" type="password" placeholder="Password" size="31" autocomplete="off"/><br><br>
<div class="left" style="padding-left:150px; horizontal-align:right;text-align:center;"><input type="submit" name="login" value=<s:text name="login"/> class="button normal normal1" onClick="validate1()"/></div>
<br> <br><s:if test="status=='failure'">
<center><p style="color:RED" text-align :"center"><b> Invalid username. Please enter a valid username</b></p></center>
</s:if>
<s:if test="status=='failure2'">
<center><p style="color:RED" text-align :"center"><b> Invalid password. Please enter a valid password</b></p></center>
</s:if>
<s:if test="status=='failure3'">
<center><p style="color:RED" text-align :"center"><b> Login to the application to continue</b></p></center>
</s:if>
</div>
struts.xml:
<action name="logout" class ="com.opentext.planning.view.OTLAuthentication" method="logout">
<result name="success">/WEB-INF/index.jsp</result>
<result name="failure">/WEB-INF/error.jsp</result>
</action>
<action name ="Otl_Homepage"
class="com.opentext.planning.view.OTLAuthentication" method="Authentication">
<result name="success">/WEB-INF/Otl_Homepage.jsp</result>
<result name="failure">/WEB-INF/index.jsp</result>
<result name="failure2">/WEB-INF/index.jsp</result>
<result name="failure3">/WEB-INF/index.jsp</result>
</action>
The required parameters are in the action context, but if you are using the action, which for some reason doesn't get parameters from the params interceptor, then you still can get parameters if your action implements ParameterAware.
public class OLTAuthentication implements ParameterAware {
private Map<String, String[]> parameters;
public void setParameters(Map<String, String[]> parameters){
this.parameters = parameters;
}
public String Authentication() {
String j_username = parameters.get("j_username")[0];
String j_password = parameters.get("j_password")[0];
...
I have an action class that saves my cookies like this:
public String execute() {
// Save to cookie
Cookie name = new Cookie("name", userInfo.getName() );
name.setMaxAge(60*60*24*365); // Make the cookie last a year!
servletResponse.addCookie(name);
}
If I submit my form, I can see the cookies on the browser that has been created and saved. When the user submits, they get redirected to a new page, a page with all the stored information that they just created.
I want the user to be able to go back to the submit page and see all the information in the forms that they just submitted. Is it possible to do this with Struts2, by using the saved Cookies and get the form to fill in with the old data?
This is my form:
<s:textfield
label="Name"
name="name"
key="name"
tooltip="Enter your Name here"/>
To send cookie you can use a cookie-provider interceptor. It allows you to populate cookies in the action via implementing CookieProvider. To apply this interceptor to the action configuration you can override the interceptors config
<action ... >
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="cookieProvider"/>
...
</action>
The CookieProvider has a method to implement,
public class MyAction extends ActionSupport implements CookieProvider {
#Override
public Set<Cookie> getCookies(){
Set<Cookie> cookies = new HashSet<>();
Cookie name = new Cookie("name", userInfo.getName() );
name.setMaxAge(60*60*24*365); // Make the cookie last a year!
name.setPath("/"); //Make it at root.
cookies.add(name);
return cookies;
}
}
In the form
<s:set var="name">${cookie["name"].value}</s:set>
<s:textfield
label="Name"
name="name"
value="%{#name}"
tooltip="Enter your Name here"/>
My Struts project structure is as follows:
page1->action1->page2->action2->page3
What i need is for a value i entered in an input tag in page1 to be accessed in action2.
Here is my code:
page1:
<div class = "container">
<s:form id = "idinput" method = "post" action = "idEntered">
Enter id: <input id = "txtid" name = "txtid" type = "text" />
<input id = "cmdsubmit" name = "cmdsubmit" type = "submit" value = "enter details" />
</s:form>
</div>
action1:
public class AddId extends ActionSupport {
private int txtid;
//getter and setter
#Override
public String execute() throws Exception {
return "success";
}
}
page2:
<div class = "container">
<s:form id = "formvalues" method = "post" action = "formEntered">
<p>Your id entered is: <s:property value = "txtid" /></p>
First name: <input id = "txtfname" name = "txtfname" type = "text" />
Last name: <input id = "txtlname" name = "txtlname" type = "text" />
Age: <input id = "txtage" name = "txtage" type = "text" />
<input id = "cmdform" name = "cmdform" type = "submit" value = "submit form" />
</s:form>
</div>
action2:
public class AddForm extends ActionSupport {
private String txtfname;
private String txtlname;
private int txtage;
private int txtid;
//getters and setters
#Override
public String execute() throws Exception {
return "success";
}
}
and displaying everything in
page3:
<div class = "container">
ID: <s:property value = "txtid" /><br>
first name: <s:property value = "txtfname" /><br>
last name: <s:property value = "txtlname" /><br>
age: <s:property value = "txtage" />
</div>
this is where I face a problem as txtid is displayed as null, from which I inferred that the value is not passed from page2 to action2
a solution i have come up with is to use
<s:hidden value = "%{txtid}" name = "txtid2 />
in my form in page2 which will allow me to use the value of txtid as txtid2 in action2, this however seems more like a hack than an actual solution, so any other suggestions are welcome.
In the situation where you want to keep the field values passed from one action to another you could configure the scope of the field. Just place the same field with getters and setters in each action, in your case it will be action1 and action2. The field name is txtid. As well as scope interceptor doesn't include in the defaultStack you should reference it in the action configuration.
For example:
<action name="action1" class="com.package.action.AddId">
<result>/jsp/page2.jsp</result>
<interceptor-ref name="basicStack"/>
<interceptor-ref name="scope">
<param name="key">mykey</param>
<param name="session">txtid</param>
<param name="autoCreateSession">true</param>
</interceptor-ref>
</action>
<action name="action2" class="com.package.action.AddForm">
<result>/jsp/page3.jsp</result>
<interceptor-ref name="scope">
<param name="key">mykey</param>
<param name="session">txtid</param>
<param name="autoCreateSession">true</param>
</interceptor-ref>
<interceptor-ref name="basicStack"/>
</action>
Now you have the scope with the key mykey and field txtid under it. Providing accessors to the field in each action will make transfer field value from one action to another.
In the example above used the basicStack which is a skeleton for the interceptor stack and it does not include some interceptors including a validation interceptor.
If you need to have other features to your actions, you should either construct a custom stack or reference other interceptors in the action configuration.
I am new to struts 2. I have a jsp page which will send a column ID to another jsp page which will send it to the action class where i will get the comments entered by user and return it to my second jsp page to display it as a popup to the user. problem is my javascript is not accepting the value of the column.
//THIS IS WHERE THE PROBLEM IS IN THE JAVA SCRIPT
<display:column title="Commentaire" sortable="true" sortProperty="Commentaire" class="alerte_td_commentaire">
<s:if test="#attr.row.Commentaire != null && #attr.row.Commentaire != ''">
<a href='#' onclick='javascript:var xx = (%{#attr.row.id}).val(); CommenatireToGet(xx);'><img src='/img/icons/ico_comment.png'></a>
</s:if>
</display:column>
//THIS IS MY SECOND JSP PAGE
function CommenatireToGet(value){
$('#divShowCommAcqui').dialog('option', 'position', 'center');
$('#divShowCommAcqui').dialog('open');
var path = buildURL("/valorisation/ajax/CommenatireToGet.do");
$.getJSON(
path,
{idAlerte:value},
function(json){
$('#commentaireAqui').val=getElementbyId(json.hello);
}
)
};
//THIS IS MY ACTION CLASS
public String getComment() throws ServiceException{
jsonData = new LinkedHashMap<String, Object>();
idAlerte= (Integer) getActionSession("idAlerte");
Alerte alerte =svc.retrieve(idAlerte);
if (alerte !=null){
jsonData.put("hello",alerte.getCommentaire());
}
return SUCCESS;
}
//THIS IS MY STRUS TAG
<action name="CommenatireToGet" class="ihm.valorisation.AlerteAction" method="getComment">
<result name="success" type="json">
<param name="root">jsonData</param>
</result>
</action>
You can't use OGNL expressions anywhere in the JSP, only in Stuts2 tag's attributes, even not all of them. So, change
<a href='#' onclick='javascript:var xx = (%{#attr.row.id}).val(); CommenatireToGet(xx);'><img src='/img/icons/ico_comment.png'></a>
to
<a href='#' onclick='CommenatireToGet(<s:property value="%{#attr.row.id}"/>);'><img src='/img/icons/ico_comment.png'></a>
I have a jsp page and struts 2 Action class . When I submit the form in the jsp , I am getting null values into the action.
The JSP code looks like :
<s:form id="user" name="user" action="initUserAdmin">
<s:textfield name="userName" cssClass="txtbox" size="30" />
<div class="btn"><a href='<s:url action="searchUserAdmin"/>'
title="Search" id="button" class="btn" ><span>Search</span></a></div>
</s:form>
The struts.xml has this part
<action name="*UserAdmin" method="{1}" class="com.mphasis.im.web.action.UserAction">
<result name="init" type="tiles">user</result>
<result name="search" type="tiles">user</result>
<result name="reset" type="tiles">user</result>
<result name="createNew" type="tiles">createNewUser</result>
</action>
And the Action class has this :
public class UserAction extends BaseAction
{
public String userName;
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String search()
{
searchProcessed = true;
System.out.println("******** inside search ******");
System.out.println("username = "+ userName);
return TilesConstants.SEARCH;
}
And the output comes as below when I type a string in the text box in jsp page.
******** inside search ******
username = null
What might be the problem ? Am I missing something ?
<a href='<s:url action="searchUserAdmin"/>'
title="Search" id="button" class="btn" >
It's just a href to the URL of action and with no parameter. Therefore, the 'userName' in the action is null.
<s:form id="user" name="user" action="initUserAdmin">
<s:textfield name="userName" cssClass="txtbox" size="30" />
<div class="btn"><a href='javascript:submitme()'
title="Search" id="button" class="btn" ><span>Search</span></a></div>
</s:form>
Javascript
function submitme(){
document.user.submit()
}
Also in the action mapping you provided the action name you are using there is UserAdmin whereas in the form action you are using initUserAdmin.They must be the same