I think there should a way to set session variable with defined scope in pure java Servlet without using other library like jsf or springframework so that visibility of session variable can be restricted.
public void doGet(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
String userId = (String)request.getAttribute("userId");
session.setAttribute("userId", userId);
}
I found ServletContext
ServletContext context = request.getSession().getServletContext();
context.setAttribute("userId", userId);
but this one doesnot seem to provide session scope flexibility.
You've found it. Set a session attribute. The scope of a session attribute is the scope of a session, which is a single user.
The portlet scope just controls whether the attribute is confined to the current portlet or is visible to all portlets. It's still within the user session. If you need to implement that feature, just bind a Map into the session under the name of the portlet, and have each portlet look in its own Map.
If you set a context attribute it will be visible to all users.
Related
I want to create a global session in JSP to be used in all Servlets and JSP files as is done in PHP with the instruction:
<?php
session_start ();
?>
Tried with:
HttpSession s = request.getSession ();
and set. It works, but I have to make several passes from one class to another to have it in another JSP file.
How can I do?
You can use ServletContext Listener to maintain the variables for all your application Listener to
ServletContext, so you can execute some code when the application starts (is deployed correctly) to
initialize the attributes on the ServletContext) and when it finish (before its undeployed).
public final class MyAppListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
System.out.println("Application gets started.");
ServletContext servletContext = event..getServletContext();
servletContext.setAttribute("someAttribute", "Hello world!");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Application has finished.");
}
}
If you're using Java EE 5, you should configure the listener in the web.xml
<listener>
<listener-class>mypackage.listener.MyAppListener</listener-class>
</listener>
request.getSession() will create a session the first time it is called, subsequent getSession() calls will use the same session as long as the session id is available on the URL (or a cookie).
You need to make sure to call response.encodeUrl(...) when generating links from one page to another so that the session ID is included in the URL.
eg: www.mysite.com/somePage;JSESSIONID=adfasdfasdfasdf
From tutorialspoint
By default, JSPs have session tracking enabled and a new HttpSession
object is instantiated for each new client automatically. Disabling
session tracking requires explicitly turning it off by setting the
page directive session attribute to false as follows:
<%# page session="false" %>
You would then use session.setAttribute(name, value) in your servlets to store session variables and ${name} (or equivalently <% out.print(session.getAttribute(name)); %>) to retrieve and output them in your JSPs.
Try with
ServletContext servletContext = event..getServletContext();
then servletContext.getSession(). I think it should work.You need one scope who dies till the end of Application and getSession from that scope.
I'm working with servlets for a while, and trying to figure out how the view communicate with the servlet, to be more accurate I'm talking about the instances of the :
HttpSession, HttpServletRequest and HttpServletResponse classes.
1) In my jsp file i have this line of code :
<% CategorieForm cf=(CategorieForm)session.getAttribute("catForm");%>
and this is the first appearance of 'session' in this file.
when this session object is been created.
2) also in my servlet i have this method :
doPost(HttpServletRequest request, HttpServletResponse response)
{
/*
code that get the resuest parameters using the 'request.getParameter()' method, calls the model ans store the results in formBean
*/
HttpSession session=request.getSession();
session.setAttribute("catForm",cf);
response.sendRedirect("Categories.jsp");
}
I'm just trying to understand how this works, the sequencing of transactions between view and servlet, when the objects 'request' and 'response' are created, is the HttpSession object in the servlet is the same as the session in the jsp file.
thanks.
Let's start from the browser. It generates and sends a POST request.
That POST request is received, as bytes, by your Servlet container (YMMV). The Servlet container parses it, generates HttpServletRequest and HttpServletResponse objects, finds the appropriate Servlet to handle the request, and pulls a Thread from its HTTP worker thread pool to run it in.
It dispatches the Thread which invokes service(..) on your Servlet. Your custom Servlet extends HttpServlet and so inherits its service() method which, depending on the request, calls one of the doXXX() method.
In this case, doPost() will be invoked. When you reach
HttpSession session=request.getSession();
if an HttpSession doesn't exist, the Servlet container will create one for you and add a JSESSIONID Cookie to the HttpServletResponse.
When you then do
response.sendRedirect("Categories.jsp");
The Servlet container will commit the response with a status code of 302 and a Location header containing the URI to Categories.jsp resolved against your host and context path.
If your client is a browser, it will most likely send a new GET request to that URI. Your Servlet container will do the same thing I described above and invoke service() on the compiled class generated from your jsp file. This will produce the body of the HTTP response which will be sent back to the client.
when this session object is been created.
Session is created when request is made for the first time with no associated session
I'm just trying to understand how this works, the sequencing of transactions between view and servlet, when the objects 'request' and 'response' are created, is the HttpSession object in the servlet is the same as the session in the jsp file.
in that code snippet you are setting some attribute to session and then redirecting user to Categories.jsp
Upon the very first request from a user session is created. Session behaves like a hashmap and can store key/value pairs. The session also has an ID. Once the session is created, server asks client to create a cookie with session ID (there is an alternative if cookies are not available).
On each subsequent request server uses that cookie to figure out which session object to use. So yes, when you work with a session changes will persist as long as the session is not expired.
How do we handle session variables (add/fetch) in JSF 1.2?
A scenario: Consider a login screen where the user logs in successfully, the user model is stored in session. The user modes contains the user role. Next time onwards, for every user action, check the user role from the user model and display the form accordingly. In such a case how to add the user odel in session and how to etrieve it every time from the session?
Previously I have worked in Struts 1.2 where in the execute method, we have a request e=which is used to get the session and access the session variables also. But I am not sure how to achieve th same in JSF 1.2.
Is the only way achieveable is to add the managed bean in the session scope in the faces-config.xml file?
Please help me out with the session handling concepts in JSF 1.2.
The session scope is programmatically available by ExternalContext#getSessionMap() which delegates under the covers to HttpSession#get/setAttribute().
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
// ...
You can of course also just put a managed bean in the session scope. It's accessible from other managed beans by <managed-property> (or just a traversal of the session map using the managed bean name as map key).
I think you can use Java EE filters for this mechanism.
Filters are controlled by Servlet Container and runs first on an action depending on your web.xml order.
Add a servlet filter to your project.
public class YourFilter implements Filter {
public static final String USER = "USER_SESSION_KEY";
public void doFilter(ServletRequest req, ServletResponse response, FilterChain filterChain)
{
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(true);
String servletpath = request.getServletPath();
if(!servletpath.contains("login.xhtml")) //exclude your login page and other pages required to pass this filter.
{
if (session.getAttribute(USER) != null)
{
//Control your authentication and roles.
}
else
{
//There is no user in the session.
}
}
}
filterChain.doFilter(request, response);
}
Add your filter to your web.xml
<filter>
<filter-name>YourFilter</filter-name>
<filter-class>Package.YourFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>YourFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Secondly, put your User class to the session inside a JSF action.
public void userAction()
{
User user = new User();
//Build your User Class
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.getSession(false).setAttribute("USER", user);
}
P.S. : User class is a user defined POJO class. you should implement it according to your needs.
public class User
{
private String username;
//Other properties and getter setter methods required.
}
If you want to implement this mechanism inside JSF context. You can build the same logic by implementing JSF phase listeners.
In a ViewHandlerWrapper-implementation I have following code:
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
final String token = UUID.randomUUID().toString();
HttpSession httpSession = (HttpSession) context.getExternalContext().getSession(true);
httpSession.setAttribute("expectedToken", token);
getWrapped().renderView(context, viewToRender);
}
As you can see, I want to add a UUID to the Session. Following the debugger I can see that the attribute stays on the Session until the entire request-response cycle of the servlet container is complete. However, at the next invocation the "expectedToken" attribute is null.
Before going "old school" (fetching the HttpSession) I tried to manipulate a value object on the session, which rendered the same result. The change was dismissed.
Is this not supposed to work (after all, the response is not committed when renderView is invoked)?
Try getting the session without recreation
HttpSession httpSession = (HttpSession) context.getExternalContext().getSession(false);
Rather use the JSF-provided ExternalContext#getSessionMap(). This is in turn transparently backed by the HTTP session.
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.getSessionMap().put("key", "value");
A hint for the future, whenever you need to haul the raw Servlet API from under the JSF hoods, ask yourself twice: Am I doing it the right way? Isn't there a JSF-ish way? In almost all cases there is. If in vain, just ask here :)
I've a JSP/Servlet Web App that consist of more than one servlet (and some JSPs)
I need to create an new HttpSession whenever the users access servlet A, knowing that, servlet A is the home page (i.e. he access it as the first servlet/page in the application).
So far so good, I can write the following code at the start of the servlet A:
HttpSession session = request.getSession(false);
if (session == null) {
logger.debug("starting new session...");
session = request.getSession();
// other stuff here
}
But the problem is, if the user didn't close his browser (even if he closes the tab - in Firefox for instance - the session will still be open), so when he try to open my site again, the last session will be re-used (in the range of session timeout of course), and this I don't need. I need that whenever he accesses Servlet A, he gets a brand new HttpSession.
But unfortunately, he may access this servlet twice per session based on some scenario!
It seems to me that you should not be using session for this purpose. Perhaps you can add a parameter to request (i.e. transaction id) and pass it around trough all your related requests, so when user would close page the transaction id would be gone. Then you can store any data associated with given transaction id in the http session or elsewhere and could also clean it after some time.
The spring framework has an abstraction called bean scope, which seem like a good fit for your scenario, so you can create a custom scope for your transaction (or user's session) and store all the data in some bean scoped with such custom scope.
You should store some information (attribute) in the session that it's been used. And if it has been, invalidate
HttpSession session = request.getSession();
Object isOld = session.getAttribute( "isOld" );
if ( isOld != null )
{
session.invalidate( );
// Recreate session
session = request.getSession( );
}
session.setAttribute( "isOld", new Object( ) );