How do servlets work? Instantiation, sessions, shared variables and multithreading
Asked Answered
H

8

1258

Suppose, I have a webserver which holds numerous servlets. For information passing among those servlets I am setting session and instance variables.

Now, if 2 or more users send request to this server then what happens to the session variables?
Will they all be common for all the users or they will be different for each user?
If they are different, then how was the server able to differentiate between different users?

One more similar question, if there are n users accessing a particular servlet, then this servlet gets instantiated only the first time the first user accessed it or does it get instantiated for all the users separately?
In other words, what happens to the instance variables?

Hiett answered 24/6, 2010 at 0:16 Comment(0)
G
1950

ServletContext

When the servlet container (like Apache Tomcat) starts up, it will deploy and load all its web applications. When a web application is loaded, the servlet container creates an instance of ServletContext once and keeps it in the server's memory. The web app's web.xml and all of included web-fragment.xml files is parsed, and each <servlet>, <filter> and <listener> found (or each class annotated with @WebServlet, @WebFilter and @WebListener respectively) will be instantiated once and be kept in the server's memory as well, registred via the ServletContext. For each instantiated filter, its init() method is invoked with an instance of FilterConfig as argument which in turn contains the involved ServletContext.

When a Servlet has a <servlet><load-on-startup> or @WebServlet(loadOnStartup) value of 0 or greater, then its init() method is also invoked during startup. Those servlets are initialized in the same order specified by that value. If the same value is specified for more than one servlet, then each of those servlets is loaded in the same order as they appear in the web.xml, web-fragment.xml, or @WebServlet classloading. In the event the "load-on-startup" value is absent or negative, the init() method will be invoked whenever the HTTP request hits that servlet for the very first time. There are two init() methods, one taking an instance of ServletConfig as argument which in turn contains the involved ServletContext, and another which does not take any arguments but the ServletContext is available by inherited getServletContext() method.

When the servlet container is finished with all of the above described initialization steps, then the ServletContextListener#contextInitialized() will be invoked with a ServletContextEvent argument which in turn contains the involved ServletContext. This will allow the developer the opportunity to programmatically register yet another Servlet, Filter or Listener.

When the servlet container shuts down, it unloads all web applications, invokes the destroy() method of all its initialized servlets and filters, and all Servlet, Filter and Listener instances registered via the ServletContext are trashed. Finally the ServletContextListener#contextDestroyed() will be invoked and the ServletContext itself will be trashed.

HttpServletRequest and HttpServletResponse

The servlet container is attached to a web server that listens for HTTP requests on a certain port number (port 8080 is usually used during development and port 80 in production). When a client (e.g. user with a web browser, or programmatically using URLConnection) sends an HTTP request, the servlet container creates new instances of HttpServletRequest and HttpServletResponse and passes them through any defined Filter in the chain and, eventually, the Servlet instance.

In the case of filters, the doFilter() method is invoked. When the servlet container's code calls chain.doFilter(request, response), the request and response continue on to the next filter, or hit the servlet if there are no remaining filters.

In the case of servlets, the service() method is invoked. By default, this method determines which one of the doXxx() methods to invoke based off of request.getMethod(). If the determined method is absent from the servlet, then an HTTP 405 error is returned in the response.

The request object provides access to all of the information about the HTTP request, such as its URL, headers, query string and body. The response object provides the ability to control and send the HTTP response the way you want by, for instance, allowing you to set the headers and the body (usually with generated HTML content from a JSP file). When the HTTP response is committed and finished, both the request and response objects are recycled and made available for reuse.

HttpSession

When a client visits the webapp for the first time and/or the HttpSession is obtained for the first time via request.getSession(), the servlet container creates a new HttpSession object, generates a long and unique ID (which you can get by session.getId()), and stores it in the server's memory. The servlet container also sets a Cookie in the Set-Cookie header of the HTTP response with JSESSIONID as its name and the unique session ID as its value.

As per the HTTP cookie specification (a contract any decent web browser and web server must adhere to), the client (the web browser) is required to send this cookie back in subsequent requests in the Cookie header for as long as the cookie is valid (i.e. the unique ID must refer to an unexpired session and the domain and path are correct). Using your browser's built-in HTTP traffic monitor, you can verify that the cookie is valid (press F12 in Chrome / Edge / Firefox 23+ / IE9+, and check the Net/Network tab). The servlet container will check the Cookie header of every incoming HTTP request for the presence of the cookie with the name JSESSIONID and use its value (the session ID) to get the associated HttpSession from server's memory.

The HttpSession stays alive until it has been idle (i.e. not used in a request) for more than the timeout value specified in <session-timeout>, a setting in web.xml. The default timeout value depends on the servlet container and is usually 30 minutes. So, when the client doesn't visit the web app for longer than the time specified, the servlet container trashes the session. Every subsequent request, even with the cookie specified, will not have access to the same session anymore; the servlet container will create a new session.

On the client side, the session cookie remains as long as the browser instance is running (normally). Unless the browser is configured to restore the last browser session, when the client closes the browser instance (all tabs/windows), the session is lost on the client's side. In a new browser instance, the cookie associated with the session wouldn't exist, so it would no longer be sent. This causes an entirely new HttpSession to be created, with an entirely new session cookie being used.

In a nutshell

  • The ServletContext lives for as long as the web app lives. It is shared among all requests in all sessions.
  • The HttpSession lives for as long as the client is interacting with the web app with the same browser instance, and the session hasn't timed out at the server side. It is shared among all requests in the same session.
  • The HttpServletRequest and HttpServletResponse live from the time the servlet receives an HTTP request from the client, until the complete response (the web page) has arrived. It is not shared elsewhere.
  • All Servlet, Filter and Listener instances live as long as the web app lives. They are shared among all requests in all sessions.
  • Any attribute that is defined in ServletContext, HttpServletRequest and HttpSession will live as long as the object in question lives. The object itself represents the "scope" in bean management frameworks such as JSF, CDI, Spring, etc. Those frameworks store their scoped beans as an attribute of its closest matching scope.

Thread Safety

That said, your major concern is possibly thread safety. You should now know that servlets and filters are shared among all requests. That's the nice thing about Java, it's multithreaded and different threads (read: HTTP requests) can make use of the same instance. It would otherwise be too expensive to recreate, init() and destroy() them for every single request.

You should also realize that you should never assign any request or session scoped data as an instance variable of a servlet or filter. It will be shared among all other requests in other sessions. That's not thread-safe! The below example illustrates this:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

See also:

Goebbels answered 24/6, 2010 at 2:41 Comment(25)
So when I somehow can find out the JSessionId which gets send to a client, I can steal his session?Ferdelance
@Toskan: that's correct. It's known as session fixation hack. Please note that this is not specific to JSP/Servlet. All other server side languages which maintains the session by a cookie are sensitive as well, like PHP with PHPSESSID cookie, ASP.NET with ASP.NET_SessionID cookie, etcetera. That's also why URL rewriting with ;jsessionid=xxx as some JSP/Servlet MVC frameworks automatically do is frowned upon. Just make sure that session ID is never exposed in URL or by other means in webpages so that the unaware enduser won't be attacked.Goebbels
@Toskan: Also, make sure that your webapp is not sensitive to XSS attacks. I.e. do not redisplay any user-controlled input in unescaped form. XSS put doors open to ways to collect session IDs of all endusers. See also What is the general concept behind XSS?Goebbels
@overshadow: as answered, it's applicationwide.Goebbels
@BalusC, Sorry for my stupidity. It means all user access the same instance of thisIsNOTThreadSafe right?Strumpet
@Strumpet yes every user will have access to same instanceSinglebreasted
@itsraja You can configure this - while a absence of a specific time to load leads to loading on the first request in most servers - also supported by most servers is setting the time a servlet should be created: stackoverflow.com/questions/809775/…Rubalcava
Amazing answer. "Any Servlet, Filter and Listener lives as long as the webapp lives. They are being shared among all requests in all sessions." But What is a filter and listener? What do they do?Adhamh
"The HttpSession lives as long as the client is interacting with ......among all requests in the same session." I couldn't understand the above explanation. a) Do they mean, A single session is created when a client(say user A) first visits the server and the same session(session created for user A) is shared among all requests (all future requests from user A only and not with session created for user B) ? b)Also do they implicitly mean, each unique user will have unique session and that session will be used for all future requests from that user until the session dies?Adhamh
@user3705478, Sessions are created per-user. Sessions are maintained as long as the client holding that session is active. When the client becomes inactive, the session expires.Cazares
@Goebbels I am a newbie but a little confused you said that " If the determined method is absent from the servlet, then an HTTP 405 error is returned in the response." Is it not suppose to be HTTP error 404?Because if the method is absent from the servlet then there is no url mapping for that method and instead should return an error 404?Chilpancingo
@Chilpancingo 404 is returned when whole servlet itself is absent. 405 is returned when servlet is present but desired doXxx() method is not implemented.Goebbels
Are request and response objects actually get reused? The answer says opposite things: "When a client (user with a web browser) sends an HTTP request, the servlet container creates new HttpServletRequest and HttpServletResponse objects" and then "When the HTTP response is committed and finished, both the request and response objects are recycled and made for reuse." Also this answer implies that they are generally reused: https://mcmap.net/q/17342/-httpservletrequest-reuseFetor
@Goebbels HttpSession object, generates a long and unique ID and stores it in the server's memory. What do you mean by server's memory? is it in JVM heap? or on a file system?Celerity
@piechuckerr Depends on server configuration.Goebbels
This is very different approach from .Net. .Net will create a new instance of Controller ( like a servlet ) for each request.Wainscot
I read somewhere servlet should be loaded with application deployment for load-on-startup >= 0 and not only for load-on-startup > 0. I might be wrong :)Riddle
@Goebbels Since Servlets arent thread safe, and the method doGet is also not synchronized, how come thisIsThreadSafe is threadsafe? I mean, Thread1 could go in, call request.getParameter("foo"), save it in thisIsThreadSafe, then Thread2 comes and does the same and saves another value, then Thread1 goes along using that thisIsThreadSafe variable unknowing it now has the value that Thread2 put in it?Tocci
@brat: Variables declared in the method are only visible to the current thread. That's basic Java and absolutely not servlet specific. Probably it's wise to take a step away from Java EE, back to basic Java and make sure you understand basic Java entirely before diving into Java EE.Goebbels
@Goebbels Ouch, "burn". Deserved though :-o. Yah, forgot some basics and had to cram in some other stuff in between which didnt help, now ashamed I asked such a question x(. Thanks for the reply, you rock!Tocci
Thanks @Goebbels When would you use a filter and when a servlet? I am trying to find a way to change the content of a rendered page when certain conditions occur.Susa
@AnaSustic: logically, if that page is not rendered by a single servlet, but by "any" servlet, then you need a filter, else you need to extend/modify that single servlet (do not add a new servlet!). See also a.o. https://mcmap.net/q/24287/-servlet-vs-filterGoebbels
@Goebbels the page rendering and delivery is done through a series of filters (Magnolia CMS). In that sense I guess there is no reason for adding a servlet?Susa
Sessions are not necessarily tracked with cookies. URL rewriting can replace the JSESSIONID cookie with a jsessionid query parameter.Demi
URL rewriting is discommended because they are a security concern. It can be disabled via web.xml. See also the 2st comment here.Goebbels
J
446

Sessions

enter image description here enter image description here

In short: the web server issues a unique identifier to each visitor on his first visit. The visitor must bring back that ID for him to be recognised next time around. This identifier also allows the server to properly segregate objects owned by one session against that of another.

Servlet Instantiation

If load-on-startup is false:

enter image description here enter image description here

If load-on-startup is true:

enter image description here enter image description here

Once he's on the service mode and on the groove, the same servlet will work on the requests from all other clients.

enter image description here

Why isn't it a good idea to have one instance per client? Think about this: Will you hire one pizza guy for every order that came? Do that and you'd be out of business in no time.

It comes with a small risk though. Remember: this single guy holds all the order information in his pocket: so if you're not cautious about thread safety on servlets, he may end up giving the wrong order to a certain client.

Jotunheim answered 6/7, 2013 at 16:38 Comment(3)
Your picture is very good for my comprehension. I have one question , What will this pizza restaurant do when too many pizza order came , just wait for one pizza guy or hire more pizza guy ? Thanks .Needle
He will return a message with to many requests at this moment. try again laterUrsala
Servlets, unlike Pizza delivery people, can do more than one delivery at the same time. They just need to take special care on where they write down the client's address, the pizza's flavor...Leitman
S
42

Session in Java servlets is the same as session in other languages such as PHP. It is unique to the user. The server can keep track of it in different ways such as cookies, url rewriting etc. This Java doc article explains it in the context of Java servlets and indicates that exactly how session is maintained is an implementation detail left to the designers of the server. The specification only stipulates that it must be maintained as unique to a user across multiple connections to the server. Check out this article from Oracle for more information about both of your questions.

Edit There is an excellent tutorial here on how to work with session inside of servlets. And here is a chapter from Sun about Java Servlets, what they are and how to use them. Between those two articles, you should be able to answer all of your questions.

Shoulder answered 24/6, 2010 at 0:20 Comment(3)
This brings up another question for me, Since there is only one servlet context for the whole application and we get access to the session variables through this servletcontext so how can the session variables be unique to every user? Thanks..Hiett
how are you accessing the session from the servletContext? You're not referring to servletContext.setAttribute(), are you?Terryn
@KuJon Each web app has one ServletContext object. That object has zero, one, or more session objects -- a collection of session objects. Each session is identified by some kind of identifier string, as seen in cartoons on other answer. That identifier is tracked on client by either cookie or URL-rewriting. Each session object has its own variables.Mikkimiko
G
33

When the servlet container (like Apache Tomcat) starts up, it will read from the web.xml file (only one per application) if anything goes wrong or shows up an error at container side console, otherwise, it will deploy and load all web applications by using web.xml (so named it as deployment descriptor).

During instantiation phase of the servlet, servlet instance is ready but it cannot serve the client request because it is missing with two pieces of information:
1: context information
2: initial configuration information

Servlet engine creates servletConfig interface object encapsulating the above missing information into it servlet engine calls init() of the servlet by supplying servletConfig object references as an argument. Once init() is completely executed servlet is ready to serve the client request.

Q) In the lifetime of servlet how many times instantiation and initialization happens ??

A)only once (for every client request a new thread is created) only one instance of the servlet serves any number of the client request ie, after serving one client request server does not die. It waits for other client requests ie what CGI (for every client request a new process is created) limitation is overcome with the servlet (internally servlet engine creates the thread).

Q)How session concept works?

A)whenever getSession() is called on HttpServletRequest object

Step 1: request object is evaluated for incoming session ID.

Step 2: if ID not available a brand new HttpSession object is created and its corresponding session ID is generated (ie of HashTable) session ID is stored into httpservlet response object and the reference of HttpSession object is returned to the servlet (doGet/doPost).

Step 3: if ID available brand new session object is not created session ID is picked up from the request object search is made in the collection of sessions by using session ID as the key.

Once the search is successful session ID is stored into HttpServletResponse and the existing session object references are returned to the doGet() or doPost() of UserDefineservlet.

Note:

1)when control leaves from servlet code to client don't forget that session object is being held by servlet container ie, the servlet engine

2)multithreading is left to servlet developers people for implementing ie., handle the multiple requests of client nothing to bother about multithread code

Inshort form:

A servlet is created when the application starts (it is deployed on the servlet container) or when it is first accessed (depending on the load-on-startup setting) when the servlet is instantiated, the init() method of the servlet is called then the servlet (its one and only instance) handles all requests (its service() method being called by multiple threads). That's why it is not advisable to have any synchronization in it, and you should avoid instance variables of the servlet when the application is undeployed (the servlet container stops), the destroy() method is called.

Grater answered 22/2, 2012 at 12:54 Comment(0)
R
21

Sessions - what Chris Thompson said.

Instantiation - a servlet is instantiated when the container receives the first request mapped to the servlet (unless the servlet is configured to load on startup with the <load-on-startup> element in web.xml). The same instance is used to serve subsequent requests.

Robertson answered 24/6, 2010 at 0:27 Comment(1)
Correct. Additional thought: Each request gets a new (or recycled) thread to run on that single Servlet instance. Each Servlet has one instance, and possibly many threads (if many simultaneous requests).Mikkimiko
S
13

The Servlet Specification JSR-315 clearly defines the web container behavior in the service (and doGet, doPost, doPut etc.) methods (2.3.3.1 Multithreading Issues, Page 9):

A servlet container may send concurrent requests through the service method of the servlet. To handle the requests, the Servlet Developer must make adequate provisions for concurrent processing with multiple threads in the service method.

Although it is not recommended, an alternative for the Developer is to implement the SingleThreadModel interface which requires the container to guarantee that there is only one request thread at a time in the service method. A servlet container may satisfy this requirement by serializing requests on a servlet, or by maintaining a pool of servlet instances. If the servlet is part of a Web application that has been marked as distributable, the container may maintain a pool of servlet instances in each JVM that the application is distributed across.

For servlets not implementing the SingleThreadModel interface, if the service method (or methods such as doGet or doPost which are dispatched to the service method of the HttpServlet abstract class) has been defined with the synchronized keyword, the servlet container cannot use the instance pool approach, but must serialize requests through it. It is strongly recommended that Developers not synchronize the service method (or methods dispatched to it) in these circumstances because of detrimental effects on performance

Seismoscope answered 5/3, 2014 at 11:41 Comment(3)
FYI, current Servlet spec (2015-01) is 3.1, defined by JSR 340.Mikkimiko
JSR 340: Java Servlet 3.1 Specification And JSR 369: JavaTM Servlet 4.0 SpecificationPastiche
Very neat answer ! @SeismoscopeLandward
B
0

No. Servlets are not Thread safe

This is allows accessing more than one threads at a time

if u want to make it Servlet as Thread safe ., U can go for

Implement SingleThreadInterface(i) which is a blank Interface there is no

methods

or we can go for synchronize methods

we can make whole service method as synchronized by using synchronized

keyword in front of method

Example::

public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException

or we can the put block of the code in the Synchronized block

Example::

Synchronized(Object)

{

----Instructions-----

}

I feel that Synchronized block is better than making the whole method

Synchronized

Barnabas answered 14/4, 2018 at 15:32 Comment(0)
F
0

As is clear from above explanations, by implementing the SingleThreadModel, a servlet can be assured thread-safety by the servlet container. The container implementation can do this in 2 ways:

1) Serializing requests (queuing) to a single instance - this is similar to a servlet NOT implementing SingleThreadModel BUT synchronizing the service/ doXXX methods; OR

2) Creating a pool of instances - which's a better option and a trade-off between the boot-up/initialization effort/time of the servlet as against the restrictive parameters (memory/ CPU time) of the environment hosting the servlet.

Fancyfree answered 6/2, 2019 at 6:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.