How to create global session in JSP? - java

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.

Related

How to secure session variable in HttpSession using java servlets

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.

how to forward session from one servlet to another?

Hey guys i'm working on admin module for my project. When a person logs-in, a request is sent to login servlet. When it further ask for some other report by clicking other options a request for the report is sent to other servlet which gives the result on the page which is shown at the time of user which is of normal type. The session is lost between two servlets.
I am trying to navigate the generated report on some other page but for that i need to know user type in second servlet. This can be done by fetching value of user_type from login module bean class.
How to handle this situation? thanks
My login servlet is :
LoginService user = new LoginService();
user.setUserName(request.getParameter("username"));
user.setPassword(request.getParameter("password"));
user = UserDAO.login(user);
if (user.isValid())
{
HttpSession session = request.getSession(true);
session.setAttribute("currentSessionUser",user);
if(user.getUser_type().equalsIgnoreCase("admin")){
response.sendRedirect("administrator/homepage.jsp");
}else{
response.sendRedirect("homepage.jsp"); //logged-in page
}
}
else
response.sendRedirect("invalidlogin.jsp"); //error page
}
i tried using this in second servlet:-
LoginService session = (LoginService)request.getAttribute("currentSessionUser");
String drake = session.getUser_type();
System.out.println("usertype = " +drake);
Here LoginService is the bean class of login module. i'm get a nullpointer exception here.
I think you're trying to do stuff that your web container should handle for you... A session should automatically be maintained over the course of multiple servlet calls from the same client session. Methods from HttpServlet are given a HttpServletRequest. You can obtain the corresponding HttpSession using one of the getSession methods of that class.
You can bind stuff to the HttpSession using setAttribute and getAttribute.
EDIT: I'm taking this from the Servlet spec 2.5:
A servlet can bind an object attribute into an HttpSession implementation by name.
Any object bound into a session is available to any other servlet that belongs to the
same ServletContext and handles a request identified as being a part of the same
session.
I think you're better off getting the HttpSession object from the HttpServletRequest (at least assuming it's a HttpServlet) and setting/getting attributes through that. If you choose a proper name (it follows the same convention as Java package naming) for your attribute, you can be sure the returned object, as long as it's not null, can be cast to whatever type you put in there. Setting and getting attributes on the request itself isn't gonna help, I don't think stuff will get carried over from one servlet call to the next unless you call one servlet from the other with a RequestDispatcher, but that's not what you're after here.
So in your second code sample, do (LoginService)request.getSession().getAttribute("currentSessionUser");, that ought to work. Make sure to check for nulls and maybe choose an attribute name that uses your project's package name convention (like com.mycompany...).
I wouldn't mind a second opinion here since I'm not much of an EE/web developer.

Java HttpSession

Is HttpSession in java servlet is created only after
HttpSession s = request.getSession();
?
In my code I didn't write that, but when I use if (request.getSession(false) == null) ..., it doesn't work. Why?
A HttpSession is created when calling request.getSession().
But if you access a JSP by default it will automatically create a session.This behaviour can be disabled by using: <%# page session="false">
Are you using JSP?
Read JavaDocs, it says clearly:
This says, request.getSession()
Returns the current session associated with this request, or if the request does not have a session, creates one.
And the other variant request.getSession(isCreate)
Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session.
If create is false and the request has no valid HttpSession, this method returns null.
To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an IllegalStateException is thrown.
Update
On a bit research, I have found that Session is not created unless request.getSession() is called somewhere. Since, The servlet container uses this interface to create a session between an HTTP client and an HTTP server. There are good chances that your Servlet container creates the Session for you by default.
refer:
Java Doc HttpSession
Discussion on JavaRaunch: is HttpSession created automatically?
But, to be safer side, use request.getSession() to get session, and use request.getSession(false) only when you need to verify if a session has already been created.
In addition to Nishant's answer note that session can be created implicitly by JSP pages unless you configured them not to create a session with <%# page session = "false" %>.
To make it complete:
session is not created, unless you call request.getSession(), in your servlet, use request.getSession(false) to get existing session without creating new session
if you use JSP page, session is automatically created for you - variable session - unless you specify <%# page session="false" %>
even if your session is created automatically, you can use session.isNew() to find out, if it has been newly created
Try to remove session cookies from browser and make another test. If it does not work then some other component is creating a new session before that call.

Any way to anticipate session timeout?

Is there a way to "catch" the session timeout event, so as to retrieve data from HttpSession before its invalidated ?
We're implementing the Filter Interface, and in the doFilter method, the user we stored in the session object at login is null when session times out.
Thanks in advance.
You should be able to register an HttpSessionListener for your webapp that will allow you to get notified when a Session is destroyed.
It has two callback methods:
public void sessionCreated(HttpSessionEvent se)
public void sessionDestroyed(HttpSessionEvent se)
The HttpSessionEvent class has a getSession method that should let you get the affected session.
The listener class is registered in the web.xml
<listener>
<description>My Session Listener</description>
<listener-class>
my.package.MySessionListener
</listener-class>
</listener>
Have the user object implement HttpSessionBindingListener, then it can see for itself when it is added to or removed from the session.
You can always ad a piece of JSP that will check to see if your session is still active or valid - basically check to see if a session var exists (!=null) and if it doesn't - redirect the user to another page -
<%
// check for session object
HttpSession validuser = request.getSession();
// check to see if session var exists
if (validuser.getValue("auth_user") == null) {
response.sendRedirect("admin3.jsp?access+denied");
}
// if the session var is null then redirect the user
Hope this helps
Mark
Source : http://www.coderanch.com/t/279538/JSP/java/jsp-session-timeout

Multiple dynamic data sources for a servlet context

I'm developing a java servlet web application that manages information from multiple databases (all structurally the same) each corresponding to a different "business". The user selects "the current business" which is stored in the session and the application can display or modify that "current business".
I would like to use tomcat Resources in a dynamic way to have access to these businesses using jndi. In this way I can use the jstl sql tags or context lookups in servlets. I can not define each Resource in the web.xml file because they are stored in a SQL table. The end result is to be able to write simple jsp that has lines like these:
<%# taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>
<sql:query var = "users" dataSource="sources/${sessionScope.currentBusiness}">
select id, firstName, lastName FROM user
</sql:query>
or servlets that can have lines like these
String request.getSession().getAttribute("currentBusiness");
Context initial = new InitialContext();
Context context = (Context) initial.lookup("java:comp/env");
DataSource source = (DataSource) context.lookup("sources/" + currentBusiness);
where I can get the correct datasource for the "current business".
I have experimented with writing my own ObjectFactories derived from javax.naming.spi.ObjectFactory without success. Any pointers on how to easily do this?
I finally settled for the following solution consisting on a SessionListener and a Servlet that work as follows. The SessionListener has the following form:
public class SessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
// get list of possible data sources available to this session
List<DataSource> sources = new ArrayList<DataSource>();
... code to get the available sources
// get the current data source
DataSource source = null;
... code to get the current source
source = sources.get(0); // for example
// setup the session attributes
session.setAttribute("availableSources", sources);
session.setAttribute("currentSource", source);
}
}
Whenever a user logs in and a session is created, the list of available DataSources, and the current one, are placed into the session. This is done at the Session level because DataSources depend on the user login in. It is now possible to have access at them from within the application. To change the current DataSource I created a Servlet with this simplified version:
public abstract class BoxletServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
String s = request.getParameter("source");
// based on 's' choose from the available DataSource
List<DataSource> sources = (List<DataSource>) session.getParameter("availableSources");
Source source = chooseFrom(sources, s);
session.setParameter("currentSource", source);
// forward to a page saying that the DataSource changed
}
}
With this implementation it is now possible to create the following jsps:
<%# taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>
<sql:query var = "users" dataSource="${sessionScope.currentSource}">
select id, firstName, lastName FROM user
</sql:query>
Hope it helps someone else.
Create the data sources in a ServletContextListener and place them in the ServletContext.
This approach will certainly "work", but the notion of a separate, identical database for each business seems wrong to me. Surely being able to delineate business somewhere in the schema seems possible. Separating them this way requires a new database per business, where a schema would only require a new business identifier.
I'd also argue that any possibility of cross-business data mining is lost, unless you ETL data from separate databases into a dimensional cube for ad hoc reporting and querying.
And JSTL <sql> tags should only be used in the simplest web apps. You leave yourself open to the possibility of SQL injection attacks when you forego validation on a middle tier.
UPDATE:
You have to declare resources in your web.xml AFAIK, so whenever you have a new database you have to stop the application, configure the new JNDI source, and restart Tomcat. I hope you're clustered, because all the previous clients will be affected by the app being down every time you add a new business/database.

Categories