I have a very simple JSP page where it has one search box and based off the input, in the search box, it will return a response with a submit button to get the following response.
I noticed that whenever I use request.getattribute("foo") in my servlet to retrieve some request it returns null due to the request ending so I looked at the answers on here and started using session.getattribute("foo") instead. However, now I am stuck having session variables responses being set and it is causing my view to have old session data that isn't suppose to be there so now I have to use session.removeAttribute("foo"), whenever, I don't want that particular response data to be shown.
Is there a better way to go about managing this instead of having to use session.getattribute("foo"), session.removeAttribute("foo") and session.setattribute("foo")?
You should work with request.getSession()
Returns the current session associated with this request, or if the request does not have a session, creates one.
Set an attribute:
request.getSession().setAttribute("foo")
And get attribute using:
request.getSession().getAttribute("foo")
It will be used in the context of the request and not effect other requests, so you don't need to remove attribute.
Read more in Servlets tutorial
Servlets provide an outstanding technical solution: the HttpSession API. This is a high-level interface that allows the server to "remember" a set of information relevant to a particular user's on-going transaction, so that it can retrieve this information to handle any future requests from the same user.
You can go for request.getparameter("foo") or request.setparameter("foo", obj)
This can be used for every request, and it will not add to your session variables and basically will not make your "session object heavy".
Java doc:
Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.
Related
EDIT: changed file name to 'follow-up.jsp' for clarity.
This is a shorter, and hopefully better version of a longer question I posted earlier today (link: Java web development: transfer control from one servlet to another while passing the request object).
I have a form that is POST-ed upon submit. In the corresponding servlet to which the POST action is done, I want to show either the form page again or a follow-up page, depending on whether validation succeeds. BOTH the form page AND the follow-up page need the form data submitted by the user; the form page needs it to re-populate the form fields, and the follow-up page needs it to show some of this data (for example, to have the user double-check that it is correct). Therefore, I want the request object containing the submitted data to be available to BOTH pages.
Forwarding back to the form is not a problem:
RequestDispatcher rd =
getServletContext().getRequestDispatcher("/form.jsp");
rd.forward(request, response);
But how do I reach the follow-up page (say, follow-up.jsp) in such a way that the request object containing the submitted form data is still accessible in that follow-up page?
The following doesn’t seem to work:
response.sendRedirect("/MyProject/follow-up.jsp");
This is because if “name” is a form parameter that was assigned to an attribute of the request object in the form handling servlet, with this attribute conveniently also being called "name", then the following line in follow-up.jsp:
Your name is: ${name}.
does NOT print the user-submitted name (instead it prints nothing, i.e. only “Your name is:”). In other words, the attributes of the original request object are no longer available in follow-up.jsp. This makes sense in that response.sendRedirect triggers a new HTTP-request (with its own request and response objects). But is not what I want.
Another (secondary) concern is that sendRedirect is unable to issue POST-requests (it only uses GET; see [link] response.sendRedirect() from Servlet to JSP does not seem to work).
EDIT: Also, I realise I could actually use:
rd.forward(request, response);
for BOTH requests. However, that would result in both pages having the same URL showing in the address bar (i.e. the name of the routing servlet, like "...../Register"). And that is definitely bad, because the form page and the follow-up are completely different pages; the follow-up page has little to do with the form (except for displaying some of the submitted form data).
Thanks.
In this case I believe you need to store the data not in request, but in a conversation scope....or in the session scope...regarding redirection not supporting post...then ideally all redirections by definition should be get requests only.....if you want to redirect using a a POST request please re-evaluate your approach...
I am writing one application, on that i am setting user object into a session and i cannot able to get that session into another controller. And i want to maintain that session throughout the application(Until the user logout). So how can i get the session object into another controller and throughout the application. And what are the steps that i need to follow to maintain the session throughout the application.
Setting into session:
public ResponseEntity<Object> getCustMenus(HttpSession session){
UserInformation userInformationSession = luser.getRolesData();
session.setAttribute("userInfo", userInformationSession);
}
Getting the session:
UserInformation userInformation=(UserInformation) session.getAttribute("userInfo");
System.out.println("-----"+userInformation.getUserName()+"----------username");
I came across your question, because I'm also facing the same problem.
I think we can rely on Tomcat's request handling mechanism - each request is running in a single thread.
So I can have
Static map where key is the request Thread object and value is the Httpsession or even HTTpRequest object. Map
Filter with url set to /* which means each request passes through this filter. The filter will add the current thread and request object to the static map.
map.put(Thread.currentThread(), httpRequest);
As the map is a static field of some class it will be accessible to all threads and if you need to share an object between different controllers though lifecycle of a request you can put it in this map, e.g. put in httpsession as an attribute and get it anywhere you want.
In filter remove the thread from map when request is done.
map.remove(Thread.currentThread());
In case we use WeakHashMap I suppose we can skip step 3.
I haven't tried this approach yet, but I think it should work. I will share results when I try it.
I found complete answers in another discussion. Get the HttpServletRequest (request) object from Java code
The most useful part of the discussion for me was posted by skaffman. Please find it below.
Spring provides the RequestContextFilter for just this purpose. It uses ThreadLocal, and allows the code to fetch the current request via RequestContextHolder. Note that this filter does not require you to use any other part of Spring:
I'm making a Java webapp which uses the Spring 4 framework.
When a user makes any request, if the user is not logged in, I use an interceptor to store this request object inside the user's session. Afterwards I redirect the user to a login screen.
When the user succesfully logs in, I want the login controller to not return a model and view (for example, the homepage) but instead fetch the stored previous request from the session and "execute" it as if the user just launched that request.
I'm having some problems with filling in some variables:
public ModelAndView login(RedirectAttributes redirectAttributes)
{
... //Do login stuff.
HttpServletRequest previousRequest = (HttpServletRequest) httpServletRequest.getSession().getAttribute("previousRequest");
httpServletRequest.getRequestDispatcher(previousRequest.getServletPath()).forward(previousRequest, ????????);
//end of method, I must return a ModelAndView but I don't have any view, I just want the request to be forwarded??
return null; //???????????
}
When getting the request dispatcher, you need to give it an url. I used httpServletRequest.getServletPath() but I'm not sure if this is correct.
When forwarding, you need to give a request and response object. But I don't have the response object at this time. I could perhaps also store the response object just like I did with the request. Or is there any other way? What would happen if I supply the CURRENT reponse object instead of the PREVIOUS response object?
My method expects me to return a modelandview, but I don't have any. How can I tell Spring to stop doing its normal "modelandview" scheme and instead start working on the forwarding of the request?
The setup described above is impossible in Jboss. You cannot forward and pass an arbitrary request object, because the servlet container will display an error. The forward method is meant to forward the CURRENT request object that is begin processed by the container.
A possible strategy, although still not ideal, is to wrap the stored request together with a freshly incoming request, and override the important methods like getParameters()´ andgetAttribute()´ to use the stored request instead of the actual request. This is the way Spring security solves this.
It seems to be impossible to tell a servletcontainer to stop handling the current request and redirect or forward to an arbitrary request object you just so happen to have available in your servlet.
Is it possible to instruct a Jetty server not to update the session's last access time when a particular servlet is accessed?
Our use case is an HTML page that sends asynchronous requests in the background every 5 miniutes to refresh its contents. The session's timeout is set to 30 minutes.
The unfortunate problem with this configuration is that when a user leaves that page open in a browser's tab, the session never expires because the access time of the session is updated by every asynchronous request.
For correctness' sake I have to admit that I didn't try anything yet because I wasn't able to find any help for my issue on the Internet. If what I'm asking for is not possible, I'm thinking of storing the access time in a session's variable that is controlled directly by the application. This value would have to be checked early before a request is processed (in the doGet and doPost methods of the servlets) and the session would need to be invalidated manually. Is there a better solution?
Servlet can't distinguish if the request is generated by some script or human, since both requests come from a same browser, consequently sending the same JSESSIONID. So you have to mark those requests in order to distinguish its source. You can mark them by some header or request parameter.
I like your idea of storing access time in session's variable (it will piggy back on servlet session expiry)
Your algorithm will be in this case:
if isUser(request){
session.lastRobotAccess == null
}else{
if (session.lastRobotAccess == null) {
session.lastRobotAccess = current_time
} else {
if(current_time - session.lastRobotAccess > session.timeout){
session.invalidate
}
}
}
When request arrives at servlet container it is first processed by the filters (if you have defined) and then by the servlet. Filters are useful for:
A common scenario for a filter is one in which you want to apply
preprocessing or postprocessing to requests or responses for a group
of servlets, not just a single servlet. If you need to modify the
request or response for just one servlet, there is no need to create a
filter—just do what is required directly in the servlet itself.
Since you can reach session from filter, they are more suitable place for your logic. You won't pollute servlet's logic with additional checking, and you can apply it to other servlets. Filters are also part of servlet specification so this will work in any container.
You already knew this things, but I've just put them on "paper" :-D
I am learning Spring security and Spring MVC, but I realized I needed to learn jsp Servlets first and general web programming in a java environment.
I have confusions surrounding the HttpServletRequest and HttpServletResponse objects and how they can be used to add headers to the request and response objects and how they relate to sessions.
As far as I understand, a cookie is a type of header just like Content-type and Accept.
The java servlet api just makes it easy to work with the header by using methods specific to the context in which the header is being used. For example:
response.setContentType(String mimeType)
response.setContentLength(int lengthInBytes)
My confusion starts here.. Cookie is not a String or int, its a object:
response.addCookie(Cookie cookie)
response.getCookies()
Since a cookie is a type of header, can't I just use something like this:
String cookieVal = response.getHeader("cookie")
I'm having difficulty understanding session management and how it relates to the HttpServletRequest and HttpServletResponse API.. What is the HttpSession object for?
HttpSession.getAttribute() // What is this getting??
HttpSession.setAttribute("Bla Bla", "valuetoset") // What is this setting?
You can read the RFC describing Cookies and the related headers, Set-Cookie and Cookie to understand what they are.
You can go through Chapter 7 of the Servlet Specification if you want to understand in detail how Cookies and Sessions are related.
You first need to understand that HTTP is a stateless protocol. This means that each request that a client makes has no relation to any previous or future requests. However, as users, we very much want some state when interacting with a web application. A bank application, for example, only wants you to be able to see and manage your transactions. A music streaming website might want to recommend some good beats based on what you've already heard.
To achieve this, the Cookie and Session concepts were introduced. Cookies are key-value pairs, but with a specific format (see the links). Sessions are server-side entities that store information (in memory or persisted) that spans multiple requests/responses between the server and the client.
The Servlet HTTP session uses a cookie with the name JSESSIONID and a value that identifies the session.
The Servlet container keeps a map (YMMV) of HttpSession objects and these identifiers. When a client first makes a request, the server creates an HttpSession object with a unique identifier and stores it in its map. It then adds a Set-Cookie header in the response. It sets the cookie's name to JSESSIONID and its value to the identifier it just created.
This is the most basic Cookie that a server uses. You can set any number of them with any information you wish. The Servlet API makes that a little simpler for you with the HttpServletResponse#addCookie(Cookie) method but you could do it yourself with the HttpServletResponse#addHeader(String, String) method.
The client receives these cookies and can store them somewhere, typically in a text file. When sending a new request to the server, it can use that cookie in the request's Cookie header to notify the server that it might have done a previous request.
When the Servlet container receives the request, it extracts the Cookie header value and tries to retrieve an HttpSession object from its map by using the key in the JSESSIONID cookie. This HttpSession object is then attached to the HttpServletRequest object that the Servlet container creates and passes to your Servlet. You can use the setAttribute(String, Object) and getAttribute(String) methods to manage state.
You are correct that cookies are managed using headers. There are TWO cookie management related headers: Cookie and Set-Cookie.
Cookie header is sent by the user agent (browser) and will be available in your HttpServletRequest object and the Set-Cookie header is appended to your HttpServletResponse object when you use methods such as addCookie(Cookie).
In Java an HttpSession is established when the first request reaches your application. The Servlet Spec implementation in your container (Jetty, Tomcat, WebSphere, etc) will create and manage the HttpSession. The browser will receive a JSESSIONID cookie which will identify this particular session in the future.
Agreeing with the answers given above, I would like to conclude that Cookie and Session are two different entities in the world of web.
Cookie
Cookie represents some brief information that's generated by server and stored on client(browser). According to HTTP mechanism, browser have to send all the cookies(that have not expired), that server had sent before to browser.
Session
HTTP is a stateless protocol. Unlike FTP and other protocol, where connection state is preserved between multiple request-response transaction, in HTTP connection is established for one request and it's closed when response for that request is satisfied. This flaw in HTTP is present, because it was designed in early days to serve static web pages only. But as web has expanded, it's now used to serve dynamic full-fledged webapps. Thus, it has become necessary to identify users. Thus, for every request served by web-server, a labeling mechanism is required which can identify user of each request. This identification of user of request(whether the request has came from same user, same machine), sessions are used.
Session can be successfully implemented only if web-server can receive any information about the user in the request. One way of making this information available to user is Cookie. Others are URL rewriting, hidden fields, etc.
session.setAttribute() will store information in current session on server side not on client side(browser).
Hope it may help you.
Ok Looks like you want to see the difference between Cookies and Headers. They have different purpose. Cookies are temporary storage of information on client side. Server set the cookies(data) on the response and once set browser send these cookies(data) with each subsequent requests till the cookie expires. But headers are used as hints to browser and server. For ex
setHeader("Content-Type", "application/json");
will inform client to prepare to see a json response in the payload. Since it is a "one time" information there is not need the browser to send that information back to the server with each new requests like cookies.