What is the best approach to handle session timeouts in struts2 - java

I have a struts2 app and I need to handle the session-timeout in the logged section.
What I have in mind is to use an Interceptor class :
public class SessionInterceptor extends AbstractInterceptor {
#Override
public String intercept(ActionInvocation invocation) throws Exception {
Map<String,Object> session = invocation.getInvocationContext().getSession();
if(session.isEmpty())
return "session";
return invocation.invoke();
}
}
In my struts.xml :
<struts>
<interceptor name="session" class="org.app.struts.interceptor.SessionInterceptor" />
<interceptor name="admin" class="org.app.struts.interceptor.AdminInterceptor" />
<interceptor-stack name="adminStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="session"/>
<interceptor-ref name="admin"/>
</interceptor-stack>
<action name="doaction" class="org.app.class" method="doAction">
<interceptor-ref name="adminStack" />
<result name="success">page.jsp</result>
<result name="error">error.jsp</result>
<result name="session">sessionexpired.jsp</result>
</action>
</struts>
Is there a better approach ?
Thanks!

You are on the right track.

try this: http://nickcoblentz.blogspot.com/2008/11/page-level-access-controls-in-struts-2.html
and in web.xml:
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
this is for 30 minutes

Related

File upload interceptor does not call setter methods

I need to do very basic file upload operation, but in my case setter methods are not called by file upload interceptor.
I have checked the solution of similar questions like this on stackoverflow but they didnot resolve my issue.
Please let me know what mistake i am doing in code.
Action class
public class ResultFileUploadAction extends ActionSupport {
private File upload;
private String uploadFileName;
private String uploadContentType;
private Logger logger = Logger.getRootLogger();
#Override
public String execute() throws Exception {
logger.info("ResultFileUploadAction->execute");
String destPath = "C:/work/";
try {
System.out.println("Src File name: " + upload);
System.out.println("Dst File name: " + uploadFileName);
File destFile = new File(destPath, uploadFileName);
FileUtils.copyFile(upload, destFile);
} catch (IOException e) {
e.printStackTrace();
return ERROR;
}
return super.execute();
}
public void setUpload(File upload) {
this.upload = upload;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
}
Jsp file
<body>
<s:form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="upload" id="uploadfile" />
<input type="submit" id="submit" />
</s:form>
</body>
Struts.xml
<interceptors>
<interceptor name="fileupload"
class="org.apache.struts2.interceptor.FileUploadInterceptor"></interceptor>
<interceptor name="servletConfig"
class="org.apache.struts2.interceptor.ServletConfigInterceptor" />
<interceptor name="authenticationinterceptor"
class="interceptors.common.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="securestack">
<interceptor-ref name="authenticationinterceptor"></interceptor-ref>
<interceptor-ref name="servletConfig"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="upload" class="actions.result.ResultFileUploadAction"
method="execute">
<interceptor-ref name="securestack"></interceptor-ref>
<interceptor-ref name="fileupload"></interceptor-ref>
<result name="success" type="dispatcher">/AddResultBullk.jsp</result>
</action>
Since, setters are not called therefore i am getting NPE in execute().
As stated in the fileUpload interceptor docs:
It adds the following parameters, where [File Name] is the name given to the file uploaded by the HTML form. [fileName, contentType]
When mucking with interceptor stacks there are always two plans of attack:
Try a non-custom stack
Don't mess with the stack unless you know precisely why you're doing it, and what you're doing.
Also, actions that are configured to use almost no interceptors, as yours is, are almost always suspect, because they eliminate the bulk of framework functionality. Params in particular is key to essentially every form-based action.
When you want to implements a new interceptors, it is a good idea to add them to the default stack in front or back of the chain, i faced the same problem before when I am trying to add an interceptor for authentication and ended with the following practice, I will update your
code to mention my idea:
...
<interceptors>
<interceptor name="authenticationinterceptor" class="your.class.name" />
<interceptor-stack name="securestack">
<interceptor-ref name="authenticationinterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<!--
Implicitly use securestack for all actions.
-->
<default-interceptor-ref name="securestack" />
....
<!--
and if you want some actions to pass from secureStack and use defaultStack
(ex login page), you can state that explicitly, See:
-->
<action name="GetLoginPageAction" class="your.class.name">
<interceptor-ref name="defaultStack" />
...
</action>
<!--
for upload action you can use interceptor without define
it in the interceptors tag only in the action,
Note that you should explicitly use securestack below
-->
<action name="upload" class="actions.result.ResultFileUploadAction">
<!-- You can remove the below refs because fileUpload is already
included in defaultStack that is included in the securestack
and securestack is default interceptor for all actions.
<interceptor-ref name="securestack"/>
<interceptor-ref name="fileUpload"/>
-->
...
</action>
I hope these notes help you.

java struts2 hibernate and spring application and soap web services

I have a web application using struts2, spring and hibernate frameworks. Now I want to expose some of its methods via soap web service. I have a class and I simply annotated it with #WebService annotation and an Service endpoint interface. Now when I deploy my application on glassfish it deploys fine but when I try to access wsdl via glasssfish admin console. It gives me the following error.
There is no Action mapped for namespace [/] and action name [UsersControllerImplService] associated with context path [/ossoc].
I understand its something related to configuration but I am unable to figure out what configuration.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ossoc</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts2.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory" value="spring" />
<package name="user" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="authentication" class="com.riteshsangwan.ossoc.core.interceptors.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="authStack">
<interceptor-ref name="authentication"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="authStack"></default-interceptor-ref>
<global-results>
<result name="login" type="redirect">/index.action</result>
</global-results>
<action name="register" class="com.riteshsangwan.ossoc.core.actions.RegisterAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/index.jsp</result>
<result name="error">/register.jsp</result>
<result name="input">/register.jsp</result>
</action>
<action name="login" class="com.riteshsangwan.ossoc.core.actions.LoginAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/user/home.jsp</result>
<result name="error">/index.jsp</result>
<result name="input">/index.jsp</result>
</action>
<action name="activate" class="com.riteshsangwan.ossoc.core.actions.ActivateAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/user/home.jsp</result>
<result name="error">/index.jsp</result>
<result name="input">/index.jsp</result>
</action>
<action name="index">
<interceptor-ref name="defaultStack"></interceptor-ref>
<result>/index.jsp</result>
</action>
<action name="home">
<result>/user/home.jsp</result>
</action>
<action name="showfiles" class="com.riteshsangwan.ossoc.core.actions.ShowFiles">
<result name="success">/user/files.jsp</result>
</action>
<action name="edit">
<result>/user/edit.jsp</result>
</action>
<action name="logout" class="com.riteshsangwan.ossoc.core.actions.LogoutAction">
<result name="success">/index.jsp</result>
</action>
<action name="changepassword" class="com.riteshsangwan.ossoc.core.actions.ChangePassword">
<result name="success">/user/edit.jsp</result>
</action>
<action name="upload" class="com.riteshsangwan.ossoc.core.actions.UploadFile">
<result>/user/home.jsp</result>
</action>
<action name="showgrid" class="com.riteshsangwan.ossoc.core.actions.ShowFiles">
<result name="success">/user/files.jsp</result>
</action>
<action name="deletefile" class="com.riteshsangwan.ossoc.core.actions.DeleteFile">
<result name="success">/user/files.jsp</result>
</action>
<action name="downloadfile" class="com.riteshsangwan.ossoc.core.actions.DownloadFile">
<result name="success" type="stream">
<param name="contentType"></param>
<param name="inputName"></param>
<param name="contentDisposition"></param>
<param name="bufferSize"></param>
<param name="allowCaching"></param>
<param name="contentLength"></param>
</result>
</action>
</package>
</struts>
applicationCOntext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Database Configuration -->
<import resource="DataSource.xml"/>
<import resource="HibernateSessionFactory.xml"/>
<!-- Beans Declaration -->
<import resource="UsersBean.xml"/>
</beans>
Why everyone here is so eager to vote down.
This was the problem.
In web.xml the struts2 filter has /* url pattern mapped so struts2 will filter every request that comes to it including the request to the webservice servlet. Since filters execute before servlets so I was getting the action not mapped error.
From the struts2 documentation.
The action mapping extension has been changed to .action plus "" it means if I simply enter name of servlet in the address bar the struts2 will take it as action and check struts2.xml for relevant action mapping since there are no action mapping so it will throw error.
Solution
I just add the .extension after url in URL pattern mapping so struts2 will treat as a servlet request other option will to use
<constant name="struts.action.excludePattern" value="URLTOEXCLUDE"/>
and configure the webservice to use the excluded URL
Hope this helps others.

Get Request in Struts 2

I am new to struts2. In application there is Action called userLogin. when i enter to url http://servername:9090/appName/userLogin, It should forward the request directly to to /jsp/account/login.jsp. it should not call action method. how can i ensure that when request is through get then forword to loginPage else if Request is Post then it should call the action
Struts.xml is as follows
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<package name="default" extends="struts-default">
<action name="index">
<result>jsp/index.jsp</result>
</action>
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<result>jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
<action name="ministatement" class="com.ril.tc.action.MiniStatementAction">
<result>jsp/account/ministatement.jsp</result>
<result name="success">jsp/account/ministatementdetails.jsp</result>
<result name="error">jsp/account/ministatement.jsp</result>
</action>
</package>
</struts>
1. You can simply check the request method in action method before the business method executes.
It will add 2-3 lines of java code in action method and a line modification in xml configuration.
2. Or you can strictly restrict the execution of the Action method by using an interceptor.
Interceptor requires a seperate java class and a few lines of xml configuration.
Method 1
a) Java code
public String execute (){ // or your method name
if(ServletActionContext.getRequest().getMethod().equals("GET")){
return "getrequest";
}
........
//your business logic
}
b) xml configuration
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<result name="getrequest">jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
Method 2.
a) Java Code
public GetRequestFilterInterceptor extends AbstractInterceptor{
#Override
public void intercept (ActionInvocation action){
if(ServletActionContext.getRequest().getMethod(). equals("GET")){
return "getrequest";
}else{
action.invoke();
}
}
}
b) Xml configuration
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="getUrlFilter" class="packagename.GetRequestFilterInterceptor"/>
<interceptor-stack name="requestFilter">
<interceptor-ref name="getUrlFilter"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
......
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<interceptor-ref name="requestFilter"/>
<result name="getrequest">jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
</package>
</struts>
I recommend you to use interceptors, if you want to filter a lot a methods. If you have want to filter only one method, the first one is better.

Adding interceptors in struts.xml for all Action classes

I've used the Struts 2 framework and I have created a web application which has a Login Page. I have three different Action classes named Action1, Action2, Action3, and different views for JSP pages which are rendered by running some business logic in the Action classes.
Now, I want to check whether a user has logged in before the Action class carries out processing. So,
I created an interceptor below that works fine:
public String intercept(ActionInvocation invocation) throws Exception
{
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
HttpSession session = request.getSession();
if(session.isNew())
{
response.sendRedirect("Login.action");
}
System.out.println("Interceptor Fired");
String result = invocation.invoke();
return result;
}
What I want to be in struts.xml is instead of adding an interceptor for all the actions like the one below
<interceptor-ref name="newStack"/>
My struts.xml file has:
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="printMsgInterceptor" class="LoginInterceptor"></interceptor>
<interceptor-stack name="newStack">
<interceptor-ref name="printMsgInterceptor"/>
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<action name="actone" class="Action1">
<result name="success">/success.jsp</result>
<interceptor-ref name="newStack"/>
</action>
<action name="acttwo" class="Action2">
<result name="success">/success.jsp</result>
<interceptor-ref name="newStack"/>
</action>
<action name="actthree" class="Action3">
<result name="success">/success.jsp</result>
<interceptor-ref name="newStack"/>
</action>
</package>
For every action I want to have some definition written in struts.xml which runs the interceptor rather than manually adding
<interceptor-ref name="newStack"/>
<interceptor name="test" class="Full path for LoginInterceptor" />
<interceptor-stack name="testStack">
<interceptor-ref name="test"/>
<interceptor-ref name="defaultStack"/> //here you are including default stack
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="testStack"></default-interceptor-ref>
Now testStack will execute for every request
Use
<default-interceptor-ref name="newStack"/>
If you not putting interceptor-ref manually for each action you could use the default-interceptor-ref to intercept all actions that has not explicitly defined interceptors configuration. See How do we configure an Interceptor to be used with every Action.
We can create our own named stacks and even declare a new default interceptor stack for a package
<package name="default" extends="struts-default" >
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="timer"/>
<interceptor-ref name="logger"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
However, if you say that the interceptor above works fine I will encourage you to be cautious about a business logic that the login action will not be executed if it fails on the first execution. Instead of checking for the new session you should check for results of the authenticated user and save these results in the session that you could check in the interceptor. See this question for example.
The example of writing the interceptor that use the authenticated user information with the session you could find here.

How to configure #SkipValidation by XML configuration in Struts 2

In Struts 2,
I am trying to skip validation on method base on XML configuration.
As per my application I can not use annotation. So I cannot use #SkipValidation annotation. Is there any alternative for this?
I have one action class which has five methods create, update, delete, search, and view. I want to validate only two methods create and update.
You should configure in the struts.xml package with interceptors
<interceptors>
<interceptor-stack name="validateWorkflowStack">
<interceptor-ref name="basicStack"/>
<!-- ... whatever interceptors -->
<interceptor-ref name="validation">
<param name="excludeMethods">delete, search, view</param>
</interceptor-ref>
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
then use action configuration
<action name="create" class="your.package.CreateAction" method="create">
<result name="input">/path/to/form.jsp</result>
<interceptor-ref name="validateWorkflowStack"/>
</action>
apply interceptor to each action that has a validation interceptor referenced explicitly on action or implicitly via <default-interceptor-ref on the package.
You must configure validation interceptor for your action to exclude methods names that you do not want to be validated.
<action name="..." class="...">
<interceptor-ref name="defaultStack">
<param name="validation.excludeMethods">input,back,cancel,browse,delete,search,view</param>
</interceptor-ref>
<result>...</result>
</action>

Categories

Resources