Session management using authentication in Struts 2 - java

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];
...

Related

Struts2 - How to repopulate form having dynamically generated fieldnames (via expression) with submitted values after validation error

We have a Struts2 application where we are building survey feature using which application users will be able to create surveys by adding different questions.
These questions are comprised of question text and an html control for getting response.
The html controls so far supported are single and multi-select list, text field, textarea, checkbox and radiobox.
So the survey form renders displaying all questions added by the user where each question has its question text displayed followed by the html field control selected for that question.
Basically, it is a dynamic form where form field names are being dynamically generated as all surveys will be different and therefore there are no properties in the Action class backing survey form fields.
We are generating form field name using prefix question_ appended with database id of the question to represent each question response input field uniquely. Here is a snippet from our JSP page to make things clear.
<s:form id="surveyForm" action="survey/submitFeedback">
<s:iterator value="surveyQuestions">
<p class="form-group <s:if test="%{fieldErrors.get('question_' + surveyQuestionId).size() > 0}">has-error</s:if>" >
<label class="control-label" >
<s:property value="questionText"/>
</label>
<s:if test="required" ><span style='color:red'>*</span></s:if>
<br>
<s:if test="surveyQuestionType.type == #com.reach150.enumeration.SurveyQuestionTypeEnum#OPENENDED_TEXTFIELD" >
<s:textfield name="question_%{surveyQuestionId}" cssClass="form-control" maxlength="charactersLimit" />
</s:if>
<s:elseif test="surveyQuestionType.type == #com.reach150.enumeration.SurveyQuestionTypeEnum#OPENENDED_TEXTAREA" >
<s:textarea name="question_%{surveyQuestionId}" style="height: 150px; width: 400px;" cssClass="form-control" maxlength="charactersLimit" />
</s:elseif>
<s:elseif test="surveyQuestionType.type == #com.reach150.enumeration.SurveyQuestionTypeEnum#SINGLESELECTDROPDOWN || surveyQuestionType.type == #com.reach150.enumeration.SurveyQuestionTypeEnum#MULTISELECTDROPDOWN" >
<s:select name="question_%{surveyQuestionId}" list="orderedSelectOptions" listKey="optionValue" listValue="optionLabel" emptyOption="true" multiple="true" cssClass="form-control" />
</s:elseif>
<s:else>
<s:radio name="question_%{surveyQuestionId}" list="#{'true':'Yes','false':'No'}" cssClass="radioMarginRight" />
</s:else>
<span class="help-block" for="question_${surveyQuestionId}">
<s:fielderror cssClass="font-bold text-danger">
<s:param>question_<s:property value="surveyQuestionId" /></s:param>
</s:fielderror>
</span>
<br/>
</p>
</s:iterator>
<button type="submit" class="btn btn-primary btn-lg pull-right "><s:if test="survey.requestReferral == true">Next</s:if><s:else>Done</s:else></button>
</s:form>
On form submit, in the action class we are using HttpServletRequest to get submitted form field values. The way we identify which question the answer belongs to is through the request parameter name which as can be seen in the above JSP snippet starts with prefix 'question_' followed by question Id. So we split the parameter name to get the question id and associate value against that question.
The problem we are facing is with repopulating survey form with submitted values when the page is presented back to the user in case of validation error as the parameter names are dynamic and cannot be backed by properties defined in Action class.
I have tried to populate radio button and textarea fields using the below code and several other ways but to no avail
<s:textarea name="question_%{surveyQuestionId}" style="height: 150px; width: 400px;" cssClass="form-control" maxlength="charactersLimit" value="#parameters.%{'question_' + surveyQuestionId}" />
<s:radio name="question_%{surveyQuestionId}" value="#parameters.%{'question_' + surveyQuestionId}" list="#{'true':'Yes','false':'No'}" cssClass="radioMarginRight" />
Below is the action mapping for survey submit action
<action name="survey/submitFeedback" class="surveyAction" method="submitFeedback">
<result name="success" type="tiles">survey.submit</result>
<result name="error" type="tiles">survey.view</result>
<param name="public">true</param>
</action>
Here is the code in Action class handling the submit logic:
private Integer npsScore = 0;
private Map<String, String[]> surveyResponseQuestionAnswerMap = new HashMap<>();
public String submitFeedback() {
try {
if (requestId == null) {
addActionError("Request Id missing! Invalid Request!");
throw new Exception("Invalid Request!");
}
surveyRequest = surveyService.getSurveyRequestByUUID(requestId);
if (surveyRequest == null) {
addActionError("Request Id Invalid! Invalid Request!");
throw new Exception("Request Id Invalid! Invalid Request!");
}
loadQuestionAnswersMap();
validateSurveyFeedback();
if (hasErrors()) {
throw new Exception("Error submitting response!");
} else {
surveyService.parseAndSaveSurveyResponse(surveyRequest, surveyResponseQuestionAnswerMap);
setSurveyCustomMessages(surveyService.getSurveyCustomMessagesSettingBySurveyId(survey.getSurveyId()));
}
return SUCCESS;
} catch (Exception e) {
addActionError("Error submitting response!");
logger.error(e);
loadSurvey();
return ERROR;
}
}
private void loadQuestionAnswersMap() {
HttpServletRequest httpRequest = ActionUtil.getRequest();
Enumeration<String> parameterNames = httpRequest.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
if (parameterName.startsWith("question_")) {
String[] values = httpRequest.getParameterValues(parameterName);
if (values != null) {
surveyResponseQuestionAnswerMap.put(parameterName, values);
}
}
}
}
private void validateSurveyFeedback() throws Exception {
HttpServletRequest httpRequest = ActionUtil.getRequest();
Survey survey = surveyRequest.getSurvey();
if (survey.isUseNetPromotorScore()) {
String npsScoreStr = httpRequest.getParameter("npsScore");
if (StringUtils.isBlank(npsScoreStr)) {
this.addFieldError("npsScore", "Answer is required");
} else {
setNpsScore(Integer.valueOf(npsScoreStr));
}
}
List<SurveyQuestion> requiredQuestions = surveyQuestionService.getRequiredSurveyQuestionsForSurvey(surveyRequest.getSurvey());
for (SurveyQuestion requiredQuestion : requiredQuestions) {
Integer requiredQuestionId = requiredQuestion.getSurveyQuestionId();
String requiredQuestionFieldParameterName = "question_" + requiredQuestionId;
logger.info("Required Question Field Parameter Name: " + requiredQuestionFieldParameterName);
String[] answers = httpRequest.getParameterValues(requiredQuestionFieldParameterName);
if (answers == null) {
this.addFieldError(requiredQuestionFieldParameterName, "Answer is required");
} else {
boolean noValue = true;
for (String answer : answers) {
if (StringUtils.isNotBlank(answer)) {
noValue = false;
break;
}
}
if (noValue) {
this.addFieldError(requiredQuestionFieldParameterName, "Answer is required");
}
}
}
}
We have finally solved the problem. The initial implementation was heading in a completely wrong direction but thanks to the clue from #RomanC, we re-factored the code and removed the direct use of HttpServletRequest to finally have a working solution. Core idea was to use a Bean for capturing response and have a List of those beans in the Action class corresponding to each survey question. On form submit, response is captured into the bean objects behind the scene by framework itself and thus available for further logic processing in submit handler action method.

Liferay portlet + struts2 + Ajax

I have tried this a lot since last couple of days, but still not able to solve this.
I am using liferay 6.1 and struts 2. Basically i have two dropdowns in my liferay portlet, one for country and other for states. When selecting the country, state list needs to be in drop down list according to the country selected. I am trying to do this through AJAX. (Below code I found from google, its working in a separate Dynamic Web Project, but when i tried this in liferay portlet its throwing error.
Below is my Code:
StartPage.jsp
<script >
$(document).ready(function() {
$('#country').change(function(event) {
var country = $("select#country").val();
alert(country);
$.getJSON("<s:url action='ajaxAction' namespace='ajax' includeParams='none' />", {countryName : country}, function(jsonResponse) {
$('#ajaxResponse').text(jsonResponse.dummyMsg);
alert($('#ajaxResponse').text(jsonResponse.dummyMsg));
var select = $('#states');
select.find('option').remove();
$.each(jsonResponse.stateMap, function(key, value) {
$('<option>').val(key).text(value).appendTo(select);
});
});
});
});
</script>
<s:form name="StartPage" id="StartPage">
<s:select id="country" name="country"
list="{'Select Country','India','US'}" label="Select Country" />
<br />
<br />
<s:select id="states" name="states" list="{'Select State'}"
label="Select State" />
<br />
<br />
<div id="ajaxResponse"></div>
</s:form>
struts.xml
<package name="default" extends="json-default">
<action name="ajaxAction" class="com.action.AjaxJsonAction">
<result type="json">/WEB-INF/view/StartPage.jsp
</result>
</action>
</package>
Action Class:
public class AjaxJsonAction extends DefaultActionSupport{
private Map<String, String> stateMap = new LinkedHashMap<String, String>();
private String dummyMsg;
//Parameter for Jquery
private String countryName;
#Override
public String execute() {
System.out.println("i am executed...");
System.out.println("CountryName: " + countryName);
if (countryName.equals("India")) {
stateMap.put("1", "Kerala");
stateMap.put("2", "Tamil Nadu");
stateMap.put("3", "Jammu Kashmir");
stateMap.put("4", "Assam");
} else if (countryName.equals("US")) {
stateMap.put("1", "Georgia");
stateMap.put("2", "Utah");
stateMap.put("3", "Texas");
stateMap.put("4", "New Jersey");
} else if (countryName.equals("Select Country")) {
stateMap.put("1", "Select State");
}
dummyMsg = "Ajax action Triggered";
System.out.println("exiting.....");
return "success";
}
public Map<String, String> getStateMap() {
return stateMap;
}
public String getDummyMsg() {
return dummyMsg;
}
public String getCountryName() {
return countryName;
}
public void setStateMap(Map<String, String> stateMap) {
this.stateMap = stateMap;
}
public void setDummyMsg(String dummyMsg) {
this.dummyMsg = dummyMsg;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
}
Errro Log:
java.lang.IllegalArgumentException: application/json;charset=UTF-8 is not a supported mime type
at com.liferay.portlet.MimeResponseImpl.setContentType(MimeResponseImpl.java:159)
at org.apache.struts2.portlet.servlet.PortletServletResponse.setContentType(PortletServletResponse.java:219)
at org.apache.struts2.json.JSONUtil.writeJSONToResponse(JSONUtil.java:225)
at org.apache.struts2.json.JSONResult.writeToResponse(JSONResult.java:211)
at org.apache.struts2.json.JSONResult.execute(JSONResult.java:172)
at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:373)
You can use AJAX AUI script for this. I am using Liferay 6.2 sp2 SDK and Liferay MVC portlet. You can try this with struts approach to see if it helps you.
Use liferay.provide function in your AUI script.
<aui:script>
Liferay.provide(
window,
'<portlet:namespace />updatePermState',
function() {
var A = AUI();
var url = '<%= ajaxCallResourceURL.toString() %>';
A.io.request(
url,
{
//data to be sent to server
data: {
<portlet:namespace />param1: (document.getElementById('<portlet:namespace/>mCountry').value),
}, .....
}
Create servResource function in your portlet class. This will be wired with your AUI call:
public void serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws IOException, PortletException {
resourceResponse.setContentType("text/javascript");
... ...
//Send Data Back
resourceResponse.setContentType("text/html");
}
In your calling JSP file add this:
<!-- Create a serveResource URL -->
<portlet:resourceURL var="ajaxCallResourceURL" />
AJAX call. I am using onChange method when on the Country field. My UpdatePermState() function is creating a div with the states dynamically.
<aui:select name="mCountry" id="mCountry" label="Country of permanent address*" inlineLabel="left" onChange='<%= renderResponse.getNamespace() + "updatePermState();" %>'>

HttpServletRequest is null although I'm implementing ServletRequestAware

I have a form in JSP having two fields, and in action class I have an instance variable for each field, but those attributes are null when action class is executing.
I have used validate() method that is not even executing.
JSP
<s:form action="addAuthority">
<table>
<caption> <b><big>Add New Authority</big></b>
</caption>
<s:if test="hasActionErrors()">
<tr>
<td><s:actionerror />
</td>
</tr>
</s:if>
<s:if test="hasActionMessages()">
<tr>
<td><s:actionmessage />
</td>
</tr>
</s:if>
<tr>
<td></td>
<td>
<s:textfield name="role" label="Authority Name"></s:textfield </td>
<td></td>
<td>
<s:select name="dependentAuthority" list="#request.authorityList" label="Dependent Authority" listKey="roleId" listValue="role"></s:select>
</td>
<td>
<s:submit value="Add"></s:submit>
</td>
</tr>
</table>
</s:form>
Action
public class AddAuthorityAction extends ActionSupport {
private String dependentAuthority;
private String role;
private Map<String, Object> session;
private HttpServletRequest request;
public String execute() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
//System.out.print(role + " " + dependentAuthority+" ");
role = request.getParameter("role");
dependentAuthority = request.getParameter("dependentAuthority");
//System.out.print(role+" "+ dependentAuthority);
//insert the data
int count = new DBInsert().addRoleDependency(role, Integer.parseInt(dependentAuthority));
if(count==0){
addActionError("There is some error while inserting. Please try again");
}else{
addActionMessage("Information successfully inserted");
}
return SUCCESS;
}
#SuppressWarnings("unchecked")
public String moveAddAuthority() {
Map request = (Map) ActionContext.getContext().get("request");
List<Role> authorityList = new DBSelect().getAuthorityId();
request.put("authorityList", authorityList);
List<Role> roleWithDependency = new DBSelect().getRoleWithDependence();
request.put("roleWithDependency", roleWithDependency);
return SUCCESS;
}
public void validate() {
if (role == null || role.trim().equals("")) {
addFieldError("role", "The name is required");
}
}
public String getDependentAuthority() {
return dependentAuthority;
}
public void setDependentAuthority(String dependentAuthority) {
this.dependentAuthority = dependentAuthority;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}}
when I am using HttpServletRequest request = ServletActionContext.getRequest(); I can get the value;
but through implementing ServletRequestAware request become null;
without using both instance variable is null;
I could not get ActionMessage in JSP page.
struts.xml
<action name="addAuthority" class="nodue.action.AddAuthorityAction"
method="execute" >
<interceptor-ref name="authonticateInterceptor"></interceptor-ref>
<result name="success" type="redirect">moveAddAuthority</result>
</action>
<action name="moveAddAuthority" class="nodue.action.AddAuthorityAction"
method="moveAddAuthority">
<interceptor-ref name="authonticateInterceptor"></interceptor-ref>
<result name="success">/authority.jsp</result>
</action>
I have made some modification on datatype of dependentAuthority previously it was Integer, and also added in JSP page the <s:if> tag.
You are probably using a single Interceptor, while you should use an entire stack with your interceptor in it.
You are returning the redirect result that should be used to reach external URLs or non-action URLs. To redirect to an action you should use redirectAction result.
No matter if redirect or redirectAction, when you redirect you lose the request parameters, and this is why you don't see action errors and messages. There are different solutions to this.
You use the validate() method, that returns INPUT result when things go south. But you haven't defined any INPUT result for your actions; be sure to understand how the INPUT result works, along with ValidationInterceptor and ParameterInterceptor.

passing property value using javascript

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>

Recieving 'null' values from a jsp page into Struts 2 Action

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

Categories