Many times we wonder that how a web container/ web-server (e.g. tomcat or jboss) works?
How they handle the incoming http requests coming from all over the
world? What are the things which make it happen behind the scene? How
java servlet API (i.e. classes like ServletContext, ServletRequest,
ServletResponse and Session) fit into picture? These are very important
questions/concepts you must know if you are a web-application developer
or you aspire to be. In this post, I will try to find out answers for
some of above question, if not all. Remain concentrated from here.
I will first talk about web servers and application servers. Let me say it in one liner,
In early days of the Mosaic browser (often described as the first graphical web browser) and hyper-linked content, there evolved a new concept “web server” that served static web page content and images over HTTP protocol. Simple enough. In these days, most of the content was static, and the HTTP 1.0 protocol was just a way to ship files around. But soon the web servers evolved to have CGI capabilities. It means effectively launching a process on each web request to generate dynamic content. By this time, HTTP protocol also matured and web servers became more sophisticated with additional functionality like caching, security, and session management. As the technology further matured, we got company-specific java-based server-side technology from Kiva and NetDynamics, which eventually all merged into JSP (java server pages), which we still use in most applications development today.
This was about web-servers. Now let’s talk about application servers.
In a parallel category, the application servers had evolved and existed for a long time. Some companies delivered products for Unix like Tuxedo (transaction-oriented middleware), TopEnd, Encina that were philosophically derived from Mainframe application management and monitoring environments like IMS and CICS. Most of these products specified “closed” product-specific communications protocols to interconnect “fat” clients to servers. In 90′s, these traditional app server products began to embed basic HTTP communication capability, at first via gateways. And sooner the lines began to blur between these two categories.
By the time, web servers got more and more mature with respect to handling higher loads, more concurrency, and better features; Application servers started delivering more and more HTTP-based communication capability. And all this resulted into very thin line between web-servers and application servers.
At this point the line between “app server” and “web server” is a fuzzy one. But people continue to use the terms differently, as a matter of emphasis.
That’s all about web servers and application servers. Now move towards third term i.e. web container.
Web container, specially in java, should be refer to servlet container. A servlet container is the component of a web server that interacts with java servlets. A web container is responsible for managing the life-cycle of servlets, mapping a URL to a particular servlet and ensuring that the URL requester has the correct access rights and many more such services. Basically, putting together all above facts, servlet container is the runtime environment where your servlet run and it’s life cycle is maintained.
In java, servlets enable you to write server side components which help in generating dynamic content, based on request. Factually, Servlet is an interface defined in javax.servlet package. It declares three essential methods for the life cycle of a servlet – init(), service(), and destroy(). They are implemented by every servlet(either defined in SDK or user-defined) and are invoked at specific times by the server during it’s life cycle.
Servlet classes are loaded to container by it’s class loader dynamically either through lazy-loading or eager loading. Each request is in its own thread, and a servlet object can serve multiple threads at the same time. When it is no longer being used, it is garbage collected by JVM.
Lazy loading servlet
Eager loading servlet
When the servlet container starts up, it will deploy and load all web-applications. When a web application gets loaded, the servlet container will create the ServletContext once per application and keep in server’s memory. The webapp’s web.xml will be parsed and every Servlet, Filter and Listener found in web.xml will be created once and kept in server’s memory as well. When the servlet container shuts down, it will unload all web applications and the ServletContext and all Servlet, Filter and Listener instances will be trashed.
As per java docs, ServletContext defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file. In the case of a web application marked “distributed” in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won’t be truly global). Use an external resource like a database instead.
The servlet container is attached to a webserver which listens on HTTP requests on a certain port number, which is usually 80. When a client (user with a web-browser) sends a HTTP request, the servlet container will create new HttpServletRequest and HttpServletResponse objects and pass it through the methods of the already-created Filter and Servlet instances whose URL-pattern matches the request URL, all in the same thread.
The request object provides access to all information of the HTTP request, such as the request headers and the request body. The response object provides facility to control and send the HTTP response the way you want, such as setting headers and the body (usually with HTML content from a JSP file). When the HTTP response is committed and finished, then both the request and response objects will be trashed.
When a client visits the web-app for the first time and/or the HttpSession is to be obtained for the first time by request.getSession(), then the servlet container will create it, generate a long and unique ID (which you can get by session.getId()) and store it in server’s memory. The servlet container will also set a Cookie in the HTTP response with JSESSIONID as cookie name and the unique session ID as cookie value.
As per the HTTP cookie specification (a contract a decent web browser and webserver has to adhere), the client (the web browser) is required to send this cookie back in the subsequent requests as long as the cookie is valid. The servlet container will determine every incoming HTTP request header for the presence of the cookie with the name JSESSIONID and use its value to get the associated HttpSession from server’s memory.
The HttpSession lives until it has not been used for more than the time, a setting you can specify in web.xml, which defaults to 30 minutes. So when the client doesn’t visit the web application anymore for over 30 minutes, then the servlet container will trash the session. Every subsequent request, even though with the cookie specified, will not have access to the same session anymore. The servletcontainer will create a new one.
Existing Session
New Session
On the other hand, the session cookie on the client side has a default lifetime which is as long as the browser instance is running. So when the client closes the browser instance (all tabs/windows), then the session will be trashed at the client side. In a new browser instance the cookie associated with the session won’t be sent anymore. A new request.getSession() would return a brand new HttpSession and set a cookie with a brand new session ID.
You should now have learned that Servlets and filters are shared among all requests. That’s the nice thing of Java, it’s multi-threaded and different threads (i.e. HTTP requests) can make use of the same instance. It would otherwise have been too expensive to recreate it on every request.
But 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 thread-unsafe! The below example illustrates that:
Do not do this. It will result in a bug in software.
What are web server, application server and web container?
I will first talk about web servers and application servers. Let me say it in one liner,
In early days of the Mosaic browser (often described as the first graphical web browser) and hyper-linked content, there evolved a new concept “web server” that served static web page content and images over HTTP protocol. Simple enough. In these days, most of the content was static, and the HTTP 1.0 protocol was just a way to ship files around. But soon the web servers evolved to have CGI capabilities. It means effectively launching a process on each web request to generate dynamic content. By this time, HTTP protocol also matured and web servers became more sophisticated with additional functionality like caching, security, and session management. As the technology further matured, we got company-specific java-based server-side technology from Kiva and NetDynamics, which eventually all merged into JSP (java server pages), which we still use in most applications development today.
This was about web-servers. Now let’s talk about application servers.
In a parallel category, the application servers had evolved and existed for a long time. Some companies delivered products for Unix like Tuxedo (transaction-oriented middleware), TopEnd, Encina that were philosophically derived from Mainframe application management and monitoring environments like IMS and CICS. Most of these products specified “closed” product-specific communications protocols to interconnect “fat” clients to servers. In 90′s, these traditional app server products began to embed basic HTTP communication capability, at first via gateways. And sooner the lines began to blur between these two categories.
By the time, web servers got more and more mature with respect to handling higher loads, more concurrency, and better features; Application servers started delivering more and more HTTP-based communication capability. And all this resulted into very thin line between web-servers and application servers.
At this point the line between “app server” and “web server” is a fuzzy one. But people continue to use the terms differently, as a matter of emphasis.
That’s all about web servers and application servers. Now move towards third term i.e. web container.
Web container, specially in java, should be refer to servlet container. A servlet container is the component of a web server that interacts with java servlets. A web container is responsible for managing the life-cycle of servlets, mapping a URL to a particular servlet and ensuring that the URL requester has the correct access rights and many more such services. Basically, putting together all above facts, servlet container is the runtime environment where your servlet run and it’s life cycle is maintained.
What are Servlets? How they help?
In java, servlets enable you to write server side components which help in generating dynamic content, based on request. Factually, Servlet is an interface defined in javax.servlet package. It declares three essential methods for the life cycle of a servlet – init(), service(), and destroy(). They are implemented by every servlet(either defined in SDK or user-defined) and are invoked at specific times by the server during it’s life cycle.
Servlet classes are loaded to container by it’s class loader dynamically either through lazy-loading or eager loading. Each request is in its own thread, and a servlet object can serve multiple threads at the same time. When it is no longer being used, it is garbage collected by JVM.
Lazy loading servlet
Eager loading servlet
What is ServletContext? Who creates it?
When the servlet container starts up, it will deploy and load all web-applications. When a web application gets loaded, the servlet container will create the ServletContext once per application and keep in server’s memory. The webapp’s web.xml will be parsed and every Servlet, Filter and Listener found in web.xml will be created once and kept in server’s memory as well. When the servlet container shuts down, it will unload all web applications and the ServletContext and all Servlet, Filter and Listener instances will be trashed.
As per java docs, ServletContext defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file. In the case of a web application marked “distributed” in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won’t be truly global). Use an external resource like a database instead.
Where ServletRequest and ServletResponse fits into life cycle?
The servlet container is attached to a webserver which listens on HTTP requests on a certain port number, which is usually 80. When a client (user with a web-browser) sends a HTTP request, the servlet container will create new HttpServletRequest and HttpServletResponse objects and pass it through the methods of the already-created Filter and Servlet instances whose URL-pattern matches the request URL, all in the same thread.
The request object provides access to all information of the HTTP request, such as the request headers and the request body. The response object provides facility to control and send the HTTP response the way you want, such as setting headers and the body (usually with HTML content from a JSP file). When the HTTP response is committed and finished, then both the request and response objects will be trashed.
How Session is managed? Know the cookie?
When a client visits the web-app for the first time and/or the HttpSession is to be obtained for the first time by request.getSession(), then the servlet container will create it, generate a long and unique ID (which you can get by session.getId()) and store it in server’s memory. The servlet container will also set a Cookie in the HTTP response with JSESSIONID as cookie name and the unique session ID as cookie value.
As per the HTTP cookie specification (a contract a decent web browser and webserver has to adhere), the client (the web browser) is required to send this cookie back in the subsequent requests as long as the cookie is valid. The servlet container will determine every incoming HTTP request header for the presence of the cookie with the name JSESSIONID and use its value to get the associated HttpSession from server’s memory.
The HttpSession lives until it has not been used for more than the time, a setting you can specify in web.xml, which defaults to 30 minutes. So when the client doesn’t visit the web application anymore for over 30 minutes, then the servlet container will trash the session. Every subsequent request, even though with the cookie specified, will not have access to the same session anymore. The servletcontainer will create a new one.
Existing Session
New Session
On the other hand, the session cookie on the client side has a default lifetime which is as long as the browser instance is running. So when the client closes the browser instance (all tabs/windows), then the session will be trashed at the client side. In a new browser instance the cookie associated with the session won’t be sent anymore. A new request.getSession() would return a brand new HttpSession and set a cookie with a brand new session ID.
How thread safety should be ensured?
You should now have learned that Servlets and filters are shared among all requests. That’s the nice thing of Java, it’s multi-threaded and different threads (i.e. HTTP requests) can make use of the same instance. It would otherwise have been too expensive to recreate it on every request.
But 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 thread-unsafe! The below example illustrates that:
public
class
MyServlet
extends
HttpServlet
{
private
Object thisIsNOTThreadSafe;
//Don't to this
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.
}
}
Do not do this. It will result in a bug in software.
No comments:
Post a Comment