J2EE Servlets Ch. 10 (Architecture) Ch. 12 (21 Days) History of Interactive Web Applets CGI Long download times Code on client machines (maintenance) Custom code to interact with web server Security hole Resource hog for large sites Java Servlets Standard, easy interface to web server Security/authentication Implements sessions History (cont.) Early use of Servlets Simple, easy to use for web applications MVC all implemented in one big servlet • • • Very complex Difficult to maintain Not scalable Current state of Servlet use Smaller is better. Used only for: • • • • Gathering and validating data input from the user Coordinating output Minimal business logic Web page forwarding Servlet Features Tailored to interact with Web Server Server and platform independent Efficient and scalable Container provides additional functionality (i.e., authentication, cookies, etc.) Interacting with HTML Forms – Request information from web server Get Simple http://www.byui.edu/j2ee?Name=Fred+&tel=3565132 Post – Send data to the server Submit button, etc. Data is sent in body of message Safer than Get HTML Forms (Cont.) Put – Place a file on the server Delete – Remove a web page from server Servlet Class Diagram Class Diagram Servlet Life Cycle Class Diagram START init() doGet(), doPost, … State: Resident destroy() END Processing Request Servlet Sequence Diagram Fig. 12-15 Model 1 - Servlets only Model/View/Control submit Servlet doGet/doPost webpage WebServer Generate HTML Data Data base Servlets in the Enterprise submit View/Control doGet/doPost Model Servlet Input Control WebServer webpage Output Performance and Flexibility Issues Data EJB Entity Bean Example Servlet publc class HtmlPage extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String name = request.getParameter(“name”); String telephone = request.getParameter(“tel”); response.setContentType(“text/html”); Get value of form parameters …. Business logic …. PrintWriter out = response.getWriter(): out.println(“<HTML>”); out.println(“<HEAD><TITLE>First Servlet</TITLE></HEAD>”); out.println(“<BODY>”); out.println(“<H1>Hello “ + name + “, Telephone “ + telephone + “</H1>”); out.println(“</BODY>”); out.println(“</HTML>”); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { doGet(request, response); } } Sent output to web browser Model 2 Architecture submit View doGet/doPost Model Business Data Access Objecs Servlet input <<forward>> WebServer Control Methods <<SessionEJB>> Data <<EntityEJB>> webpage JSP page output Web Development Life Cycle Model 2 Architecture Servlet Get request Parameters Determine and call business function JSP Determine next view Build view Web Development Life Cycle protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); 1. Get request parameters try { InitialContext context = new InitialContext(); BusinessRulesRemote businessRules = (BusinessRulesRemote) context.lookup(BusinessRules.REMOTE_JNDI_NAME); Long personId = businessRules.login(username,password); } catch (Exception e) { e.printStackTrace(); } 2.Call business function HttpSession session = request.getSession(); session.setAttribute("personid", personId); RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp"); dispatcher.forward(request, response); } 3. Determine next view Web Development Life Cycle JSP page <div id="login"> <span class='highlight'>Welcome to Home Town Bank!</span> <br> <a id='logout' href="">Logout</a> </div> 4.Build next view How to use HTTPServlet HttpServlet doGet(request HttpServletRequest , response:HttpServletResponse) doPost(request HttpServletRequest, response:HttpServletResponse) doPut(request HttpServletRequest , response:HttpServletResponse) doDelete(request HttpServletRequest , response:HttpServletResponse) HttpServletRequest Contains Request Info (Input) HttpServletResponse Handles Response (Output) RequestResponse Interface Forwarding a Response RequestResponse Interface Including other Web Components Deployment of Servlets All Servlet files zipped together into a web archive (“war”) file Requires specific directory structure Deployment Descriptor (WSDL) Deployment Descriptor <?xml version=“1.0” encoding=“UTF-8:?> <!DOCTYPE web-app PUBLIC ‘-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN’ ‘http://java.sun.com/dtd/web-app_2_3.dtd’> <web-app> <display-name>A Simple Application</display-name> <servlet> <servlet-name>Verify Data</servlet-name> <servlet-class>VerifyData</servlet-class> <init-param> <param-name>maxValue</param-name> <param-value>25</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Verify Data</servlet-name> <url-pattern>/verifydata</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <error-page> <error-code>404</error-code> <location>/error404.html</location> </error-page> </web-app> Customizing Deployment Define initialization parameters Context parameters • Apply to entire web application Servlet parameters • Apply to a specific servlet Deployment Descriptor <?xml version=“1.0” encoding=“UTF-8:?> <!DOCTYPE web-app PUBLIC ‘-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN’ ‘http://java.sun.com/dtd/web-app_2_3.dtd’> <web-app> <display-name>A Simple Application</display-name> <context-param> Context <param-name>location</param-name> <param-value>BYU-Idaho</param-value> Intialization <description>Site Location</description> Parameter </context-param> <servlet> <servlet-name>Verify Data</servlet-name> <servlet-class>VerifyData</servlet-class> <init-param> Servlet <param-name>maxValue</param-name> Intialization <param-value>25</param-value> Parameter </init-param> </servlet> <servlet-mapping> <servlet-name>Verify Data</servlet-name> <url-pattern>/verifydata</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <error-page> <error-code>404</error-code> <location>/error404.html</location> </error-page> </web-app> Retrieving Init. Parameters public void init() throws ServletException { super.init(); ServletContext context = this.getServletContext(); String location = context.getInitParameter(“location"); if (maxValue == null) { int maxValue = Integer.parseInt(this.getInitParameter(“maxValue"); } … … } Handling Errors HTTP Error Codes Http Status code – set error code Error page – set default error page Send Redirect – redirect to another page Exceptions – catch and handle all servlet exceptions Servlet Set HTTP Status Code Sets the error status code on default error page HttpServletResponse public void sendError(int statusCode) public void sendError(int statusCode, String msg)) …. public void sendRedirect(String url); Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class HtmlPage extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String name = request.getParameter(“name”); if (name.length() < 1) response.sendError(9001, “Invalid name”); } } Default HTTP Error Page Deployment Descriptor <?xml version=“1.0” encoding=“UTF-8:?> <<!DOCTYPE web-app PUBLIC ‘-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN’ ‘http://java.sun.com/dtd/web-app_2_3.dtd’> <web-app> <display-name>A Simple Application</display-name> <servlet> <servlet-name>Verify data</servlet-name> <servlet-class>VerifyData</servlet-class> <init-param> <param-name>maxValue</param-name> <param-value>25</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>verifyData</servlet-name> <url-pattern>/verifyData</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <error-page> <error-code>9001</error-code> <location>/error9001.html</location> </error-page> Define output error page for error code Send Redirect Redirect to another page to handle error HttpServletResponse public void sendError(int statusCode) public void sendError(int statusCode, String msg)) …. public void sendRedirect(String url); Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class HtmlPage extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String name = request.getParameter(“name”); if (name.length() < 1) response.sendRedirect(“/Servlets/invalidNamePage”); } } Servlet Session Management Hidden fields in form Visible to client in source (not secure) Limited amount of data URL rewritting http://www.byui.edu/j2ee?sessionid=9982345 Cookies Store on client browser May be disabled by some users Server side session object Session info stored on Server • Unlimited amount of space • More secure Automatic management Creating Cookies Implement transactions with Cookies Store state data in Cookie HttpServletResponse … public void addCookie(Cookie c) public Cookie[ ] getCookies() …. Cookie public void setValue(String value) public String getName() public String getValue() …. Creating a Cookie Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class HtmlPage extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { try { Cookie cookie = new Cookie(“userAddress”, null); String url = this.getRequextURI(); cookie.addValue(url); response.addCookie(cookie); double quantity = Double.parseDouble(request.getParameter(“quantity”)); double totalQuantity += (Double) session.getAttribute(“totalQuantity”); } catch (RemoteException remex) { response.sendError(response.SC_INTERNAL_SERVER_ERROR); } } } Retrieving a Cookie publc class HtmlPage extends HttpServlet { String userUrl = new UniqueID(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { try { Cookie cookie = null; Cookie[] cookies = response.getCookies(); if (cookies != null) { for (int i=0; i < cookies.length; i++) { cookie = cookies[i]; if (cookie.getName().equals(“userAddress”)) { String urlAddress = cookie.getValue(); break; } } } } catch (RemoteException remex) { response.sendError(response.SC_INTERNAL_SERVER_ERROR); } } Sessions Implement transactions with a HttpSession Retains state of data between page request HttpSession HttpServletRequest … public HttpSession getSession() …. public long getId() public long getLastAccessedTime() public long getCreationTime() public long getMaxInactiveInterval() public Object getAttribute() public boolean isNew() …. Getting a Session Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class HtmlPage extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { try { HttpSession session = request.getSession(); if (session.isNew()) { Long personId = (Long) session.getAttribute(“personId”); } double quantity = Double.parseDouble(request.getParameter(“quantity”)); session.setAttribute(“quantity”); } catch (RemoteException remex) { response.sendError(response.SC_INTERNAL_SERVER_ERROR); } } } Filter Servlets Acts as preprocessor to request/response for target servlet …HttpPage Authenticate Filter Servlet PageHits Filter Servlet HttpPage Servlet …VerifyData VerifyData Servlet Filter Servlet Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class PageHits extends HttpServlet implements Filter { private FilterConfig filterConfig = null; Must implement Filter Interface public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void destroy( { this.filterConfig = null; } Must override init. method Must override destroy method Filter Servlet (cont.) public void doFilter(HttpServletRequest request, HttpServletResponse response, Must override FilterChain chain) throws IOException, ServletException doFilter method { if (filterConfig == null) return; synchronized (this) { Integer counter =(Integer) filterConfig.getServletContext().getAttribute("Counter"); if (counter == null) counter = new Integer(0); counter = new Integer(counter.intValue()+1); filterConfig.getServletContext().log("Number of hits is " + counter); filterConfig.getServletContext().setAttribute("Counter", counter); } chain.doFilter(req, resp) } Modify Deployment Descriptor <?xml version=“1.0” encoding=“UTF-8:?> <<!DOCTYPE web-app PUBLIC ‘-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN’ ‘http://java.sun.com/dtd/web-app_2_3.dtd’> <web-app> <display-name>A Simple Application</display-name> <servlet> <servlet-name>VerifyData</servlet-name> <servlet-class>VerifyData</servlet-class> <init-param> <param-name>maxValue</param-name> <param-value>25</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Verify Data</servlet-name> <url-pattern>/verifyData/</url-pattern> </servlet-mapping> <filter> <filter-name>Page Hits</filter-name> <display-name>Page Hits</display-name> <description>Count page hits<description> <filter-class>PageHits</filter-class> </filter> <filter-mapping> <filter-name>PageHits</filter-name> <servlet-name>VerifyData</servlet-name> </filter-mapping> </web-app> Listener Servlet Servlet is automatically executed when some external event occurs HTTPSessionActivationListener Session is activated/passivated HTTPSessionAttributeListener Session attribute is added/removed HTTPSessionListener Session attribute is created/destroyed HTTPSessionContextAttributeListener Servlet contextattribute is added/removed HTTPSessionContextListener Servlet context changes Create Listener Servlet Import java.io.*; import javax.servlet.*; import javax.servlet.http.*; publc class Listener extends HttpServlet implements ServletContextListener { private ServletContext context = null; Must implement Listner Interface public void contextIntialized(ServletContextEvent event) { context = event.getServerContext(); Integer counter = new Integer(0); context.setAttribute(“Counter”, counter); context.log(“Created Counter”); Must override contextInitialized method } public void contextDestroyed(ServletContextEvent event) { event.getServletContext().removeAttribute(“Counter”); } } Must override contextInitialized method Modify Deployment Descriptor <?xml version=“1.0” encoding=“UTF-8:?> <<!DOCTYPE web-app PUBLIC ‘-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN’ ‘http://java.sun.com/dtd/web-app_2_3.dtd’> <web-app> <display-name>A Simple Application</display-name> <servlet> <servlet-name>Verify data</servlet-name> <servlet-class>VerifyData</servlet-class> <init-param> <param-name>maxValue</param-name> <param-value>25</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Verify Data</servlet-name> <url-pattern>/verifyData/</url-pattern> </servlet-mapping> <filter> <filter-name>Page Hits</filter-name> <display-name>Page Hits</display-name> <description>Count page hitsdescription> <filter-class>PageHits</filter-class> </filter> <filter-mapping> <filter-name>PageHits</filter-name> <servlet-name>Verify data</servlet-name> </filter-mapping> <listener> < listener-class>Listener</ listener -class> </listener> </web-app> Modify Filter Servlet public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (filterConfig == null) return; synchronized (this) { Integer counter =( Integer) filterConfig.getServletContext().getAttribute(“Counter”); if (counter = null) No longer needed counter = new Integer(1); counter = new Integer(counter.intValue()+1); filterConfig.getServletContext().log(“Number of hits is “ + counter); filterConfig.getServletContext().setAttribute(“Counter”, counter); counter); } chain.doFilter(request, response); } } Modified Filter Servlet public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (filterConfig == null) return; synchronized (this) { Integer counter =( Integer) filterConfig.getServletContext().getAttribute(“Counter”); counter = new Integer(counter.intValue()+1); filterConfig.getServletContext().log(“Number of hits is “ + counter); filterConfig.getServletContext().setAttribute(“Counter”, counter); counter); } chain.doFilter(request, response); } }