import java.io.*;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
/**
Servlet Example by Sandeep Desai (http://www.thedesai.net/sandeep)
HTTP is a stateless protocol
Web container will use Cookies for tracking sessions, if client does not allow cookie
container will encode session in the URL use request.encodeURL() when genearting
HTML with links.
URL encoding is not automatic
Hidden variable maybe used for tracking state
POST is not idempotent i.e you cannot redo without sideffects
GET is idempotent (so you can bookmark)
default for form is GET
HTTP methods
GET : get resource/file at the request URL
called for link, or FORM with GET (not secure
as user can see parameters)
POST: send parameters in body and do a get (data of unlimited
length can be sent, used for sending text or binary data)
HEAD: fetch header of GET request only
TRACE: ask for a loopback request used for testing and troubleshooting
PUT: put enclosed info (the body) at the requested URL
DELETE: delete resource/file at requested URL
OPTIONS: Ask for list of the HTTP methods to which the requested URL can respond
CONNECT: connect for the purpose of tunneling
Order of loading class
listener
Servlet
filter
When user click URL that maps to servlet
1) container creates HttpServletRequest and HttpServletResponse object
2) container finds correct servlet based on URL by looking up the Deployment Descriptor
3) container calls the servlets service() method passing the request and response objects
4) service() method figures out wether to call doGet() or doPost()
5) servlet writes output using the response object,
6) container sends response output back to client
7) service method completes
8) the request and response objects become ready for garbage collection
9) the thread used for the service method dies or is reused by container
servlet destroyed
when container wants to conserve memory resources
when all threads have operating on service() method have
finished or configured timeout value is reached
destroy() method called
Note init, service, destroy called by three different threads
one thread per request (not one thread per browser/client)
Everything in javax.servlet.*
Class starting with Http in javax.servlet.http.*
Request scoped attributes mapping
HttpServletRequest.getPathInfo javax.servlet.forward.path_info
HttpServletRequest.getQueryString javax.servlet.forward.query_string
HttpServletRequest.getServletPath javax.servlet.forward.servlet_path
DD (Deployment Descriprtor) web.xml
Attributes scope : application/context, request, session
getAttribute(String), setAttribute(String, Object)
return type Object
(note no config scope)
DD Parameters scope: Application/context, servlet
servlet & config getInitParameter(String)
return type String
HTTP parameters
request.getParameter(String)
return type String
interface Servlet
init(ServletConfig)
destroy()
getServletConfig()
abstract class GenericServlet implements Servlet ServletConfig, Serializable
init()
log()
getInitParameter(String)
getInitParameterNames()
HttpServlet extends GenericServlet
doXXX(ServletRequest req, ServletResponse resp) throws ServletException, IOException
doGet() doPost() doHead() doOptions() doDelete() doPut() doTrace()
service(ServletRequest req, ServletResponse resp) throws ServletException, IOException
Listener notification done based on order in DD
HttpSessionActivationListener and HttpSessionBindingListener do not have
to be declared in DD
javax.servlet.ServletContextListener (ServletContextEvent)
contextInitialized contextDestroyed
javax.servlet.ServletContextAttributeListener (ServletContextAttributeEvent)
attributeAdded, attributeRemoved, attributeReplaced
javax.servlet.ServletRequestListener (ServletRequestEvent)
requestInitialized requestDestroyed
javax.servlet.ServletRequestAttributeListener (ServletRequestAttributeEvent)
attributeAdded, attributeRemoved, attributeReplaced
// track Active Sessions
javax.sevlet.http.HttpSessionListener (HttpSessionEvent)
sessionCreated, sessionDestroyed
javax.servlet.http.HttpSessionAttributeListener (HttpSessionBindingEvent)
attributeAdded, attributeRemoved, attributeReplaced
// attribute class needs to know when value bound or unbound from session
// does not have to be registerd in DD
javax.servlet.http.HttpSessionBindingListener (HttpSessionBindingEvent)
valueBound, valueUnbound
when session migrating to another JVM
attributes also migrated with session, but not using serialization
attribute must implement serializable
does not have to be registerd in DD
javax.servlet.http.HttpSessionActivationListener (HttpSessionEvent)
sessionDidActivate, sessionDidPassivate
*/
public class MyServlet extends HttpServlet
implements
ServletContextListener,
HttpSessionListener,
HttpSessionAttributeListener,
ServletContextAttributeListener,
ServletRequestListener,
ServletRequestAttributeListener
{
static int instance;
// public no args constructor required for conatiner to create servlet instance
// public no args constructor required to register listeners
public MyServlet() {
System.out.println("*** MyServlet created=" + ++instance);
}
public void init() {
ServletContext context = getServletContext(); // one per web app
// ServletContext methods
// getInitParameter(String) getInitParameterNames()
// getAttribute(String) getAttributeNames()
// setAttribute(String, Object)
// removeAttribute(String)
// getMajorVersion(), getServletInfo()
// getRealPath(String)
// getResourceAsStream(String)
// getRequestDispatcher(String) // path should start with /
// getNamedDispatcher(String) // for named servlet
// log(String) // Tomcat writes to logs/locahost.*
// ServletContextListener specify class implementing interface in DD
// in <listener> <listener-class> MyListener </listener-class> </listener>
// contextInitialized(ServletContextEvent)
// contextDestroyed(ServletContextEvent)
System.out.println("***** Context Parameters from DD (web.xml)");
// deploy time constants useful for things like database connection
// values in Deployment descriptor in web.xml
for (Enumeration enum = context.getInitParameterNames(); enum.hasMoreElements();) {
String name = (String) enum.nextElement();
// redeploy servlet to change values
System.out.println("**** " + name + "=" + context.getInitParameter(name));
}
System.out.println("**** End Context Parameters");
ServletConfig config = getServletConfig();
String value = config.getInitParameter("servletParam1"); // delcared in <servlet>
// ServletConfig methods
// getInitParameter(String) Enumeration getInitParameterNames()
// getServletName()
}
// recommended to override init() instead of init(ServletConfig)
public void init(ServletConfig config) throws ServletException {
super.init(config); // should be first line
}
// common practice to call doPost() from doGet()
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = getServletContext(); // one per web app
ServletConfig config = getServletConfig(); // one per Servlet
// String after the ? part
System.out.println("**** queryString=" + request.getQueryString());
System.out.println("**** queryString="
+ request.getAttribute("javax.servlet.forward.query_string"));
context.setAttribute("appAttribute", new MyAttribute("context"));
request.setAttribute("reqAttribute", new MyAttribute("request"));
PrintWriter writer = response.getWriter();
// HttpSession
// tracked using cookie
// may used URL encoding if cookie not enabled
// SSL could be used for tracking sessions
// getCreationTime(), getLastAccessedTime(),
// setMaxInactiveInterval(int seconds) // can set in DD in minutes
// // negative value session never expires
// getMaxInactiveInterval()
// invalidate() will end session, after invalidate,
// session.xxx() will throw exception
// getSession(true) and getSession() create new session first time
// getSession(false) will not create new session
HttpSession session = request.getSession(false);
if (session == null) {
// get session create if required
// will throw IllegalStateException if response is commited
// and called the first time
session = request.getSession(); // same as req.getSession(true);
assert session.isNew();
}
else writer.println(" Who created my session?");
//session.setMaxInactiveInterval(0);
//boolean b = session.isNew(); //throws IllegalStateException
// multiple requests can come in from two client browser windows
synchronized (session) {
session.setAttribute("sessionAttribute", new MySessionAttribute("session"));
//session.removeAttribute("sessionAttribute");
}
response.setContentType("text/html");
writer.println("Hello " + new Date());
Enumeration attribEnum = context.getAttributeNames();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//ServletRequest methods
// getAttribute(String), Enumeration getAttributeNames()
// getContentLength(), getInputStream()
// getParameter(String) String[] getParameterValues(String)
// Enumeration getParameterNames()
// getParameterMap() Map of name/value pairs
// this line will cause request.getParameter() to return null
//InputStream input = request.getInputStream();
// Programmatic security
// dba servlet role can be mapped to container role using the
// security-role-ref in <servlet>
// isUserInRole("dba")) can be used for authorization
// getRemoteUser() can be used to check authenticatin
// getUserPrincipal() used with EJBs
int p = request.getServerPort();
p = request.getLocalPort(); // conatiner thread can forward to different port
p = request.getRemotePort(); // client browsers port
// HttpServletRequest methods
// getHeader(String)
// getIntHeader() getDataHeader() // convenience methods
// Enumeration getHeaders(String) // header values
// Enumeration getHeaderNames()
// isRequestedSessionIdFromCookie()
String contextPath = request.getContextPath();
String client = request.getHeader("user-agent"); // platform and browser info
int keepAlive = request.getIntHeader("keep-alive");
String method = request.getMethod(); // POST or GET
// if multiple cookies with same name return first cookie
// order of cookie not gauranteed
Cookie[] cookies = request.getCookies(); // null if no cookies
Enumeration enum = request.getHeaders("Cookies");
String queryString = request.getQueryString();
System.out.println("*** queryString=" + queryString);
//HttpSession session = request.getSession();
// ServletResponse
// getBufferSize() setContentType()
// getOutputStream() getWriter() calling both will throw IllegalStateException
PrintWriter writer = response.getWriter();
response.setContentType("text/html");
// same as
response.setHeader("content-type", "text/html");
// HttpServletResponse
// addCookie() addHeader()
// encodeURL encodeRedirectURL
// sendError servers sends HTML error page based on DD,
// leaves cookie, header untouched
//
// sendError(int) sendError(int, String)
// if output commited throws IllegalStateException
// use setStatus when no error
// setStatus(int) clears buffer does not commit
// setIntHeader() setDateHeader() addIntHeader addDateHeader()
// setStatus(404) sendError(404), sendError(404, "No")
//Cookie
// String getDomain()
// getName(), getValue(), setName(String) setValue(String)
// getMaxAge() setMaxAge(int)
// in seconds, -1 delete cookie when client browser exits
// -1 used by JSESSIONID
Cookie cookie = new Cookie("username", "sandeep");
response.addCookie(cookie);
String size = request.getParameter("size");
Enumeration en = request.getParameterNames();
String[] values = request.getParameterValues("toppings");
StringBuffer toppings = new StringBuffer();
if (values != null) {
for (int i = 0; i< values.length; ++i) {
toppings.append(values[i]);
toppings.append(",");
}
}
writer.println("Preparing " + size + " pizza with " + toppings);
String redirect = request.getParameter("redirect");
if (redirect != null && redirect.equalsIgnoreCase("cnn")) {
// if done after writer.flush() will throw IllegalStateException
// can use relative URL
// tells browser to redirect user will see changed URL
response.sendRedirect("http://cnn.com");
return;
}
if (redirect != null && redirect.equalsIgnoreCase("myjsp")) {
// server side redirect user will not see changed URL is relative URL
RequestDispatcher view = request.getRequestDispatcher("my.jsp");
try {
view.forward(request, response);
//view.include(request, response);
} catch (ServletException e) {}
return;
}
if (redirect != null && redirect.equalsIgnoreCase("myjsplink")) {
// use encodeURL so that if client browser does not support cookies
// Servlet container can encode URL with the session ID
writer.println("<a href=\"" + response.encodeURL("my.jsp") + "\">link to my.jsp</a>");
}
writer.println("contextPath=" + contextPath + "<br>");
writer.println("Headers<br>");
en = request.getHeaderNames();
while (en.hasMoreElements()) {
String headerName = (String) en.nextElement();
String headerValue = request.getHeader(headerName);
writer.println(headerName + "=" + headerValue + "<br>");
}
writer.println("Attriubtes<br>");
en = request.getAttributeNames();
while (en.hasMoreElements()) {
String attributeName = (String) en.nextElement();
Object value = request.getAttribute(attributeName);
writer.println(attributeName + "<br>");
}
}
private void myWriteBytes(HttpServletResponse response) throws IOException {
// Write directly from response instead of PrintWriter
// can use for downloading binary e.g download image
ServletOutputStream os = response.getOutputStream();
byte[] bytes = new byte[5];
bytes[0] = 'A';
os.write(bytes);
os.write(1234);
}
// ServletContextListener interface methods
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
System.out.println("*** MyServlet webapp loaded");
MyAppAttribute obj = new MyAppAttribute();
context.setAttribute("app", obj);
}
public void contextDestroyed(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
System.out.println("*** MyServlet webapp unloaded");
}
// end ServletContextListener interface
// HttpSessionListener
public void sessionCreated(HttpSessionEvent hse) {
HttpSession session = hse.getSession();
ServletContext context = session.getServletContext();
System.out.println("*** MyServlet HttpSession created");
}
public void sessionDestroyed(HttpSessionEvent hse) {
HttpSession session = hse.getSession();
ServletContext context = session.getServletContext();
System.out.println("*** MyServlet HttpSession destroyed");
}
// end HttpSessionListener
// HttpSessionAttributeListener
public void attributeAdded(HttpSessionBindingEvent hsbe) {
HttpSession session = hsbe.getSession();
ServletContext context = session.getServletContext();
String attributeName = hsbe.getName();
Object attributeValue = hsbe.getValue();
System.out.println("*** HttpSessionAttributeListener.attributeAdded:"
+ attributeName);
}
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
}
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
}
// end HttpSessionAttributeListener
// ServletContextAttributeListener
public void attributeAdded(ServletContextAttributeEvent scab) {
ServletContext context = scab.getServletContext();
String attributeName = scab.getName();
Object attributeValue = scab.getValue();
System.out.println("*** ServletContextAttributeListener.attributeAdded()=" + attributeName);
}
public void attributeRemoved(ServletContextAttributeEvent scab) {}
public void attributeReplaced(ServletContextAttributeEvent scab) {}
// end ServletContextAttributeListener
// ServletRequestListener
public void requestInitialized(ServletRequestEvent sre) {
ServletContext context = sre.getServletContext();
ServletRequest req = sre.getServletRequest();
System.out.println("*** ServletRequestListener requestCreated()");
}
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("*** ServletRequestListener requestDestroyed()");
}
// end ServletRequestListener
// ServletRequestAttributeListener
public void attributeAdded(ServletRequestAttributeEvent srae) {
ServletContext context = srae.getServletContext();
ServletRequest req = srae.getServletRequest();
String attributeName = srae.getName();
Object attributeValue = srae.getValue();
System.out.println("*** ServletRequestAttributeListener:"
+ attributeName + attributeValue);
}
public void attributeRemoved(ServletRequestAttributeEvent srae) {}
public void attributeReplaced(ServletRequestAttributeEvent srae) {}
// end ServletRequestAttributeListener
}
class MyAttribute {
String scope;
MyAttribute(String scope) {
this.scope = scope;
System.out.println("*** MyAttribute created scope=" + scope);
}
}
class MyAppAttribute {}