Multithreading: 1. How Do Servlets Work? Instantiation, Sessions, Shared Variables and
Multithreading: 1. How Do Servlets Work? Instantiation, Sessions, Shared Variables and
a. 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 the ServletContextonce and keeps it in the server's
memory. The web app's web.xml file is parsed, and
each <servlet>, <filter> and <listener> found (or each class annotated
with @WebServlet, @WebFilter and @WebListener respectively) is instantiated
once and kept in the server's memory as well. For each instantiated filter,
its init() method is invoked with a new FilterConfig.
b. When the servlet container shuts down, it unloads all web applications,
invokes the destroy()method of all its initialized servlets and filters, and
all ServletContext, Servlet, Filter and Listener instances are trashed.
c. When a Servlet has a <servlet><load-on-
startup> or @WebServlet(loadOnStartup) value greater than 0,
its init() method is also invoked during startup with a new ServletConfig.
Those servlets are initialized in the same order specified by that value (1 is
1st, 2 is 2nd, etc). If the same value is specified for more than one servlet,
then each of those servlets is loaded in the order they appear in the web.xml,
or @WebServlet classloading. In the event the "load-on-startup" value is
absent, the init() method will be invoked whenever the HTTP request hits
that servlet for the very first time.
d. 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 HttpServletRequest and HttpServletResponse objects and passes them
through any defined Filter in the chain and, eventually, the Servlet instance.
e. 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.
f. 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.
g. 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.
h. 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.
i. 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 / 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.
j. 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 timeout value defaults to 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.
k. On the client side, the session cookie stays alive for as long as the browser
instance is running. So, if the client closes the browser instance (all
tabs/windows), then the session is trashed 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.
l. The ServletContext lives for as long as the web app lives. It is shared
among all requests in all sessions.
m. 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 allrequests in the same session.
n. 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 notshared elsewhere.
o. All Servlet, Filter and Listener instances live as long as the web app lives. They
are shared among all requests in all sessions.
p. 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.
6. <url-pattern>/*</url-pattern>
a. The /* on a servlet overrides all other servlets, including all servlets provided by the
servletcontainer such as the default servlet and the JSP servlet. Whatever request you
fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually,
you'd like to use /* on a Filter only. It is able to let the request continue to any of
the servlets listening on a more specific URL pattern by
calling FilterChain#doFilter().
7. <url-pattern>/</url-pattern>
a. / doesn't override any other servlet. It only replaces the servletcontainer's builtin
default servlet for all requests which doesn't match any other registered servlet. This
is normally only invoked on static resources (CSS/JS/image/etc) and directory
listings. The servletcontainer's builtin default servlet is also capable of dealing with
HTTP cache requests, media (audio/video) streaming and file download resumes.
Usually, you don't want to override the default servlet as you would otherwise have to
take care of all its tasks, which is not exactly trivial (JSF utility
library OmniFaces has an open source example). This is thus also a bad URL pattern
for servlets. As to why JSP pages doesn't hit this servlet, it's because the
servletcontainer's builtin JSP servlet will be invoked, which is already by default
mapped on the more specific URL pattern *.jsp.
8. <url-pattern></url-pattern>
a. Then there's also the empty string URL pattern . This will be invoked when the
context root is requested. This is different from the <welcome-file> approach that it
isn't invoked when any subfolder is requested. This is most likely the URL pattern
you're actually looking for in case you want a "home page servlet". I only have to
admit that I'd intuitively expect the empty string URL pattern and the slash URL
pattern / be defined exactly the other way round, so I can understand that a lot of
starters got confused on this. But it is what it is
9. Servlets are normal java classes and thus are NOT Thread Safe.
But that said, Java classes are Thread safe if you do not have instance variables.
Only instance variables need to synchronize. (Instance variable are variables
declared in the class and not in within its methods.
Variables declared in the methods are thread safe as each thread creates it own
Program Stack and function variables are allocated in the stack. This means that
variable in a methods are created for each thread, hence does not have any thread
sync issues associated.
Method variables are thread-safe, class variables are not.
10. Context attributes are meant for infra-structure, such as shared connection pools.
11. Session attributes are meant for contextual information, such as user identification.
12. Request attributes are meant for specific request info, such as query results.
13. In the Runnable interface approach, only one instance of a class is being created
and it has been shared by different threads. So the value of counter is incremented
for each and every thread access.
14. Whereas, Thread class approach, you must have to create separate instance for
every thread access. Hence different memory is allocated for every class instances
and each has separate counter, the value remains same, which means no increment
will happen because none of the object reference is same.
15. When to use Runnable?
Use Runnable interface when you want to access the same resource from the group
of threads. Avoid using Thread class here, because multiple objects creation
consumes more memory and it becomes a big performance overhead.
16. A class that implements Runnable is not a thread and just a class. For a Runnable to
become a Thread, You need to create an instance of Thread and passing itself in as
the target.
17. In most cases, the Runnable interface should be used if you are only planning to
override the run()method and no other Thread methods. This is important because
classes should not be subclassed unless the programmer intends on modifying or
enhancing the fundamental behavior of the class.
18. When there is a need to extend a superclass, implementing the Runnable interface
is more appropriate than using the Thread class. Because we can extend another
class while implementing Runnable interface to make a thread
19.