MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets
Upcoming SlideShare
Loading in...5
×
 

MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets

on

  • 503 views

MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets

MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets

Statistics

Views

Total Views
503
Views on SlideShare
503
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets MELJUN CORTES Jedi course notes web programming-lesson3-advanced servlets Document Transcript

  • Advanced ServletsIn the previous discussion, we have looked at how Servlets can be used by Javadevelopers to receive client requests and to produce a response dynamically. We havealso seen how to deploy such servlets by packaging them in industry-standard WAR filesand loading them into the servlet container.In this discussion, we will cover several advanced servlet topics: • Response redirection • Scope objects • Sessions and session tracking • FiltersResponse RedirectionThere are cases when we want our servlets only responsibility is to do some initialprocessing and leave the generation of actual content to some other entity.Suppose we take in some value from the user and present him with several possibleviews based on that value. Lets also say that we have a site that, after processing theusers log-in, would present him with different pages depending on the role the user hasin the system. Placing the content generation code for all of those pages into one servletmay make our servlet too unmanageable. In these cases, it would be better for theservlet to redirect output generation.There are two methods that a developer can use to perform this redirection. One isthrough a RequestDispatcher object and the other is through the sendRedirect() methodfound in the HttpServletResponse object.RequestDispatcherWe obtain an instance of the RequestDispatcher object by invoking the followingmethod: public RequestDispatcher getRequestDispatcher(String path)This method can be found in the HttpServletRequest object.The String parameter that this method takes in is the location of the HTML, JSP, orservlet we want to dispatch the request to. Once we have an instance of aRequestDispatcher object, we now have the option of invoking one of two methods: • public void include(ServletRequest req, ServletResponse res) • public void forward(ServletRequest req, ServletResponse res)Both methods take in the content produced by the specified location and make it a partof the servlets response to the user. The main difference between them is that, the
  • forward makes the target the entity with sole responsibility of generating response, whileinclude only incorporates the contents of the target. Using include, we could add othercontent to the response or even include another target.To illustrate the difference of the two, two servlets are presented below. Their code isvirtually identical. Its just that, the first makes use of the include method while thesecond uses the forward method.public DispatchServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("Error occurred during login request processing"); RequestDispatcher rd = request.getRequestDispatcher("/login.html"); rd.include(request, response); }}public DispatchServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("Error occurred during login request processing"); RequestDispatcher rd = request.getRequestDispatcher("/login.html"); rd.forward(request, response); }}Both of the servlets defined above make use of a web page named login.html to formthe basis of its output. The definition of this page is given below:<H1>Login Page</H1><form action="DispatchServlet">User name : <input type="text" name="loginName"><br/>Password : <input type="password" name="password"><br/><input type="submit"/></form>On running the first servlet, the one making use of the include method, the followingoutput was generated:
  • Figure 1: Output of DispatchServlet using the include MethodRunning the second servlet yields the following result: Figure 2: Output of DispatchServlet using the forward MethodGiven the virtually identical codes, we have two different outputs. Using the includemethod, the String message we output to the user prior to calling the method isdisplayed. This is not the case for the output of the forward method wherein themessage we added into the response prior to calling the method is not part of theoutput.With the forward method, all content in the response buffer is cleared prior to themethod call, after which the response is immediately committed; no further content canbe added. With the include method, all content placed in the response buffer is keptbefore and after the method call.Using the include method, it is possible for our servlet to present the output of severaldifferent sources in whole. It also allows us to append messages to otherwise staticcontent. Take the following as an example:
  • public LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestDispatcher rd = null; // retrieve user parameters from form String loginName = request.getParameter("loginName"); String password = request.getParameter("password"); User user = null; // create the JavaBean implementing authentication functionality UserService service = new UserService(); user = service.authenticateUser(loginName, password); if (user == null) { // generate error message response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("User does not exist with given login and/or password"); // return user to login page rd = request.getRequestDispatcher("/login.html"); rd.include(request, response); out.close(); } else { // store the User object into session scope HttpSession session = request.getSession(); session.setAttribute(ApplicationConstants.USER_OBJECT, user);// build the response from multiple HTML components rd = request.getRequestDispatcher("/header.html"); rd.include(request, response); rd = request.getRequestDispatcher("/mainContent.html"); rd.include(request, response); rd = request.getRequestDispatcher("/footer.html"); rd.include(request, response); }}Since the include method only adds content from another source and does not committhe response after its call, we can use it repeatedly. By using this principle, theLoginServlet presented above is able to create a response containing three differentpages.sendRedirectThe other way of redirecting output to an entity outside the servlet is the sendRedirectmethod. It has the following method signature and can be found in the
  • HttpServletResponse object: public void sendRedirect(String relativePath)The parameter it takes is a String representing the path to the target we want to redirectthe user to. Calling this method effectively instructs the browser to send in another HTTPrequest, this time to the specified target.This makes the target the sole entity responsible for generating the content, which is, ina way, similar to the results of using the forward method in the RequestDispatcherobject discussed earlier. However, the re-sent request presents several practicaldifferences compared to the forward method: • The URL in the browser bar reflects the target specified. This makes use of the sendRedirect method which is undesirable if we dont want user to be aware of the redirection. • Since it is effectively a new request, data stored in the previous request object is discarded. User-supplied parameters, if there were any, must be resubmitted if we want our target to be aware of them. Custom data stored in the request object must also be maintained in some other way. Otherwise, they will be lost.It is recommended then that the include method be used to allow multiple outputsources. The forward method should be used in redirecting to components whichgenerate dynamic content (e.q. Servlets, JSPs) while the sendRedirect method should beused in redirecting to components that generate static content.EXERCISES1) What are the two ways of performing redirection in the servlet API?2) What is the difference between using the include method and the forward method inthe RequestDispatcher object?3) What is the difference between using the forward method in the RequestDispatcherobject and the sendRedirect method using the HttpServletResponse object?Scope ObjectsThe servlet specification allows us four scopes where data is placed, in order to beshared among our components. They are listed below in increasing scope: • Page - Page scope is defined to be the scope encompassing a single JSP page. Variables declared within the page are visible only within that page and are no longer visible once that pages service ends. The object associated with this scope is a PageContext object. • Request - Request scope is defined to be the scope encompassing a clients single request. Data that is stored within this scope is visible to all web components handling the clients request. After the clients request has finished, that is, the client has received an HTTP response and has closed the connection to the server, all data stored within this scope is no longer visible.The object associated with this scope is the HttpServletRequest object. Instances of this
  • object are readily available to servlets as they are given as parameters to the servicemethods called by the container upon client request. • Session – This is the scope encompassing a single “session” with the client. This session starts when the client first starts with the web application and ends once the user logs out of the system or a server-defined timeout has been achieved. Data within this scope is visible to all web components the client makes use of during this interval. Data from one user session, however, is not visible from within another users session.The object associated with this scope is the HttpSession object. An instance of this canbe retrieved by using the getSession() method in the HttpServletRequest object. • Application – This scope encompasses the whole of the application. Data that is stored within this scope is visible to all components regardless of which user request or client session they are handling and lasts until the application is terminated.The object associated with this scope is the ServletContext object. As previouslydiscussed, this can be retrieved by calling on the getServletContext() method from avalid ServletConfig objectStoring and Retreiving Data from ScopeAll of the scope objects mentioned above contain common methods to be able to retrieveand store data within them. To store data use the method public void setAttribute(String key, Object value);The String parameter that this method takes will store the Object under that value. Toretrieve the data later, pass the same key as the parameter. public Object getAttribute(String key);If there is no object that can be retrieved from the given key, a null is returned by themethod. Also, since the return type is Object, it would be up to the developer to cast theObject to the appropriate class and perform type-checking.To remove an attribute from the scope object, simply call on the removeAttribute()method and pass the key to the attribute as its parameter.Sample ScenarioLet us take in the following scenario: we want our application to display the details abouta person given their personalID. This personalID will be provided by the user. Topromote maintainability, we want to separate the component that will retrieve thepersonal details and the component that will display the information to the user. Thesetwo components are to communicate using the data storage and retrieval facilitiesavailable in request scope.
  • public PersonalDataRetrievalServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {// retrieve user supplied parameterString personalID = request.getParameter("personalID");// create business object that handles implementation of retrieving data given id.DataService service = new DataService();// retrieve the person object that contains the details we needPerson person = service.retrievePersonalDetails(personalID);// store the data into request scope using a constant keyrequest.setAttribute(ApplicationConstants.PERSON, person);// forward the request into the component that will display the detailsRequestDispatcher dispatcher = request.getRequestDispatcher("/DisplayServlet");dispatcher.forward(request, response);}}public DisplayServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {// retrieve the Person object that contains the detailsPerson person = (Person) request.getAttribute(ApplicationConstants.PERSON);// construct the response based on the infoStringBuffer buffer = new StringBuffer();buffer.append("<HTML><TITLE>Personal Info</TITLE>");buffer.append("<BODY><H1>Details : </H1><br/>");buffer.append("Name : ");buffer.append(person.getName());buffer.append("<br> Address : ");buffer.append(person.getAddress());buffer.append("</BODY>");// display the responseresponse.setContentType("text/html");PrintWriter out = response.getWriter();out.println(buffer.toString());out.close();}}The code for the DataService object and the Person object are no longer listed here astheir implementations are not important for our example. What the above exampleshows is how to store a data object from one servlet and retrieve the same data fromanother servlet which has access to the same scope.
  • Here are a couple of notes regarding the example. First, the second servlet was able toretrieve the data from request scope because it is still part of the same request. If wehad used the sendRedirect way of redirecting control to the servlet, the getAttributemethod would have returned null since sendRedirect would have made the browser issueanother request. This effectively ends the lifetime of the request object storing the data.Second, it is recommended that the keys used for storing and retrieving data be madeavailable to the application as constants, as in the example above. This makes sure thatthe exact same key is used for storage and retrieval, reducing the possible amount oferrors that can be encountered during development.EXERCISES1) What are the different scopes available in a web application in which an object canbe stored?2) Which object is associated with the application scope? With the session scope?3) What is the lifetime/visibility of objects placed within session scope? Within requestscope?4) Given the following code: public class SenderServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String message = "Can you hear me?"; request.setAttribute("messageKey", message); response.sendRedirect("ReceiverServlet"); } } If you have a ReceiverServlet mapped to the location indicated within thesendRedirect method, would it be able to successfully retrieve the message? Why orwhy not?5) Create an implementation of a ReceiverServlet that will attempt to retrieve themessage stored within request scope by the SenderServlet given in the previousnumber.Session Tracking and ManagementWe must recall that HTTP is designed as a connected, stateless protocol. When a browsersends a request to a server, it opens a connection, sends in a HTTP request, consumesthe HTTP response, and then closes the connection. Since each browser request iseffectively sent over different connections each time, and the server does not inherentlymaintain an awareness of the clients accessing it, the problem of maintaining state for aparticular users web transaction is presented for web applications.A solution for this problem is for the server to maintain the concept of a "user session".While in a session, the server will be able to recognize a client over multiple requests.
  • With that awareness, the server can now be able to maintain state for a client.For such a session to exist, the client browser must be able to send data to the serveraside from its standard HTTP request. This data allows the server to identify which useris performing the request, and maintain his state accordingly. There are 3 typicalsolutions to this problem: cookies, URL-rewriting, and hidden form fields.Traditional Methods for Maintaining Session State . CookiesCookies are small data structures used by a web server to deliver data to a clientbrowser. This data is stored by the browser, and in some circumstances the browserreturns the data back to the web server.Using cookies, servlets can store "session ids" that it can use to identify the user as aparticipant in a particular session. After the ID is generated, it is stored in a Cookieobject, and sent back to the client browser for storage. This cookie object can then beretrieved from the request object each time to determine if the user is in a session.Below is a sample of how to use cookies for session tracking in servlets:...// generate new session ID for userString sessionID = generateSessionID();// create new map object that will be used to store data to be maintained in sessionHashMap map = new HashMap();// retrieve a map that serves as a container for all session info.HashMap containerMap = retrieveSessionMaps();// add the newly created map object into the map containing all session infocontainerMap.put(sessionID, map);// create the cookie that will be stored in the browserCookie sessionCookie = new Cookie("JSESSIONID", sessionID);// add the cookie to the response and ask the browser to store itresponse.addCookie(sessionCookie);..To retrieve the right map containing session data, servlets would retrieve the cookiecontaining the session ID, and obtain the appropriate HashMap using the session Id as akey.While cookies are good solutions for session tracking, its usage requires developers tohandle a lot of details such as: • generating a unique session id for each user,
  • • retrieving the appropriate cookie from the browser that contains the session ID, and • setting an appropriate expiration time for the cookie.Aside from the above details, a problem with cookie usage is that some users disablecookie support for their browser due to security concerns. Alternative approaches aredefinitely needed. . URL RewritingIn this approach, the client browser appends a unique session ID to the end of eachrequest it makes to the server. This session ID can then be read, and the appropriateuser information retrieved.This is another good solution that works even if the user has disabled the use of cookies.However, there are two problems associated with this approach. First, the server mustmake sure that each session ID it gives out is unique. Second, the entire applicationmust be written such that the session ID is appended to all links/URLs pointing to theapplication. Any request that does not include the session ID would not be consideredpart of the session and will not have access to session specific information. . Hidden form fieldsIn this approach, a hidden form field is introduced to HTML forms with the value beingset to a particular session ID. However, this method is very limited due to the fact that itcan only be used when there is a form in the page the client is using.Session Tracking in ServletsThe servlet specification has provided a high-level API to provide access to sessiontracking: the HttpSession API. Using this API, the developer no longer needs to worryabout many of the details mentioned above: session ID recognition, cookie manipulationdetails, and URL-information extraction details. These are abstracted from the developer.Also, the developer is provided a convenient location in which to store data for a usersession. Correct use of the HttpSession API also allows your application to automaticallyswitch to the URL-rewriting method if it detects that cookie support in the client browseris disabled. . Obtaining an instance of the HttpSession objectThe HttpSession object representing session data associated for a given client requestcan be obtained by calling the getSession() method in the HttpServletRequest object.The container is then responsible for reading data from the client (either from cookies orfrom URL-rewriting), and creating an instance of the HttpSession object.By passing in a boolean value to the the getSession() method (i.e., getSession(true)),we can specify to the server whether a new HttpSession object should automatically becreated in case the user is not currently participating in any session.A sample code showing how to retrieve an instance of the HttpSession object is shownbelow:
  • public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { .... HttpSession session = request.getSession(); . Storing and retrieving data in a sessionWith the HttpSession API, developers no longer have to explicitly manage objects tostore data that need to be maintained within a user session. All that is needed is to callon either of the following methods: • public void setAttribute(String key, Object value) • public Object getAttribute(String key)These are the same methods we have encountered during our discussion of the differentobject scopes. Actually, the HttpSession object that we are working on now representsthe session scope previously discussed.Another example of saving and retrieving objects from session scope is given below: public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { User user = authenticateUser(); ... HttpSession session = request.getSession(); session.setAttribute("userObject", user); ... } }Above is an excerpt of an implementation of a servlet handling user login. One of theactivities commonly performed by such handlers aside from user authentication is thestorage of the User object representing the currently logged-in user into session scope.This object can then be retrieved by other servlets that need information about thecurrent user such as the one below:
  • public class InfoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); User user = (User)session.getAttribute("userObject"); // perform necessary operations on user object here } } . Removing data stored in sessionTo remove data placed in session scope, call on the removeAttribute() method and passin as a parameter the String key associated with the data.An example of a servlet performing such a removal is presented below. In this imaginaryscenario, the application has stored temporary data inside the session under the key"tempData". After it has made all possible use of the data, it passes control to thisservlet to remove it from session. public class InfoProcessingServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { HttpSession session = request.getSession(); session.removeAttribute("tempData"); // pass control on to the next web page response.sendRedirect("next.html"); } } . Terminating the sessionAutomatic termination through timeoutSessions are automatically terminated after a predefined maximum interval. This intervalcan be found and configured in the applications deployment descriptor.The deployment descriptor for the FirstServlet example is reprinted here for recall:
  • ...</servlet-mapping><session-config><session-timeout>30</session-timeout></session-config><welcome-file-list>...The value of 30 in the session-timeout element tells the server to wait for an inactiveperiod lasting for 30 minutes before terminating the session. At this point, all objectsplaced inside session will be removed from scope, and the HttpSession object becomesinvalid.Programmatic terminationAside from waiting for session time-out to occur, a session can be terminatedprogramatically by calling on the invalidate() method in the HttpSession object. Use ofthis method is recommended for situations where the user no longer needs to be part ofa session, such as when s/he has indicated their need to log out from the application. Byending a session programatically instead of waiting for the time out, resources are freedup quicker. It also ensures that any sensitive data stored in the session is removedimmediately, making it less likely to be retrieved by other people.A sample implementation of a servlet handling user logout is presented below: public class LogoutServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { HttpSession session = request.getSession(); // perform other log out activities here //invalidate user session session.invalidate(); // send user back to the login page of our application response.sendRedirect("login.jsp"); } } . Performing URL-RewritingBy default, the HttpSession API makes use of cookies to track sessions. However, weshould develop our web applications by adding support for URL rewriting so it can workequally well on browsers not supporting cookies.We can add this support for URL rewriting by making use of the encodeURL() methodfound in the HttpServletResponse object. This method takes in a String representing a
  • path or URL as its parameter. It then determines whether cookie support is enabled onthe target browser. If it is enabled, it returns the given String as is. However, if cookiesare disabled, it enables URL rewriting by appending the session ID to the given URL.The following is an example on how to use the encodeURL method....String encodedURL = response.encodeURL("/welcome.jsp");out.println("<A HREF=" + encodedURL + ">Click here to continue</A>");...To provide URL rewriting functionality in our application then, we must replace all URLspassed as links to the user with something reencoded through the encodeURL method.Paths passed in to the sendRedirect method that we discussed earlier must also bereencoded – this time using the results of the encodeRedirectURL() method.EXERCISES1) The HttpSession API provided along with the servlet API relies mostly on cookies forits session handling. What is the disadvantage of this form of session handling?2) How can a developer retrieve an instance of the HttpSession object?3) Consider the following object : public class InfoBean { private String name; private String number; // getter and setter methods here } If an instance of this object has been stored into the session under the key"infoBean", create a servlet that would retrieve this instance and display the name andnumber stored within it.FiltersFilters are advanced web components introduced since the Serlvet 2.3 Specification.Basically, they are components that stand between a client request and a particularresource. Any attempts to retrieve the target resource has to go through the filter. Theresource can be any static or dynamic source of content (HTML, JSP, GIF, etc.).Filters work by intercepting client requests and exist as part of a chain; that is, there is adefined sequence of filters that a request passes through before finally arriving at thetarget resource. When the request passes through the filter, the filter does its processingand can then decide whether to pass the request on to the next filter in the sequence (ifthe current filter is the last filter in the sequence, the request is passed on to the targetresource), or to bypass the chain entirely, denying the user access to the resource.
  • Figure 3: Illustration of Requests Passing through FiltersThe figure above is a graphical representation of how requests pass through a series offilters before finally arriving at the target endpoint.Filters are useful components since they provide the developer an easy way of includingadditional processing before resources within the web application are accessed. This kindof functionality is possible using only servlets and response redirection. This is moredifficult to implement though, and requires that each level servlet be aware of thelocation of the next servlet in the sequence. Filters have no such limitation; it is theservlet container and not the developer, that manages the sequence of components thatare called before the request ever reaches the endpoint.Creating a FilterTo create a filter, developers must create a class that implements the javax.servlet.Filterinterface. This interface defines the following methods: • void init(FilterConfig config) throws ServletException – This method is called by the servlet container the first time that it loads the Filter into memory. Initialization code must be placed here, including code that gathers initialization parameters located in web.xml through the use of the given FilterConfig object. • void destroy – This method is called by the container when the filter is unloaded from memory. This is usually done when the application shuts down. Code that releases any resources held by the Filter should be done here. • void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException – This method contains all of the functionality of the Filter class. It is called by the servlet container when the server determines that the filter is required to intercept a particular user response.The parameters passed into this method are instances of ServletRequest,
  • ServletResponse, and FilterChain objects. If this Filter is participating in a webenvironment though (as is commonly the case), the developer may choose to cast therequest and response objects to instances of HttpServletRequest andHttpServletResponse, respectively, so that they can retrieve HTTP-specific information.Like a servlet, the container will create only one instance of a Filter object and use multi-threading to allow it to handle multiple concurrent client requests. This means that thismethod MUST be defined to be thread-safe.An example of a class implementing a filter is given below. This filter makes use of thelogging facility available in the ServletContext object to make a log of all user requeststhat have passed through it. public LoggingFilter implements Filter { private FilterConfig config; public void init(FilterConfig config) { this.config = config; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { // retrieve the ServletContext object which we will use to perform the logging operation ServletContext context = config.getServletContext(); // create as a log entry the URL accessed by the user during request processing. String logEntry = request.getServerName() + ":" + request.getServerPort(); logEntry += "/" + request.getContextPath() + "/" + request.getPathInfo(); logEntry += "--> accessed by the user on " + new java.util.Date(); // use the logging facilities built-in into the ServletContext object context.log(logEntry) // call on the next filter in the chain chain.doFilter(request, response); } public void destroy() {} }Filter ChainsFilter chains allow Filters to be applied in a certain sequence for a particular resource,and are represented by a FilterChain object. The ability of a Filter to be chained makes itdistinctive. Otherwise, a Filter is functionally the same as a Servlet.Filter chaining allows a clean separation between different processing layers. If, forexample, new functionality needs to be implemented before a request is processed, itcan simply be created as a Filter. Once the Filter is configured, the Filter is merely addedto the components servicing the request before the endpoint has been reached. It doesnot supercede any previous processing unless explicitly coded to do so by the developer.
  • The sequence of the filter chain is determined by a filters location in the deploymentdescriptor and follows in ascending order the ordering of <filter-mapping> elements thatrepresent the mapping of each filter (more on filter configuration later).As said before, the FilterChain object represents the sequence of the Filters that will becalled before it eventually reaches the endpoint. The only access a developer has to thissequence is the doFilter method in the FilterChain object: this calls the next Filter in thesequence, or the target resource if the current Filter is the last in the sequence. Thismethod only requires the current ServletRequest and ServletResponse objects asparameters. Again, since there is no need for the Filter programmer to have anawareness of which Filter will receive the next request, it allows the programmer to focusonly on the current object.If a developer failed to call on the doFilter method, the rest of the filters in the chain (aswell as the target resource), would never be called. If this were not the functionalitydesired, care must be taken to include that method called into the filter code. However,there are times when we would intentionally not call the rest of the filters/resources inthe chain. One such case would be if our filter acted as a security filter that would blockaccess to a resource if appropriate conditions were not met.An example of such a filter is provided below. The code describes a security filter thatchecks for the existence of user information placed within session scope. If it did not findsuch information, it assumes that the current user either has not logged in to theapplication or the users session has expired. In either case, it returns the user to thelogin page.
  • public class SecurityFilter implements Filter {private FilterConfig config;public void init(FilterConfig config) {this.config = config;}public void doFilter(ServletRequest request, ServletResponse response, FilterChainchain)throws ServletException, IOException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;HttpSession session = httpRequest.getSession();User user = (User) session.getAttribute("userObject");if (user != null) { // if the user passes the conditions, allow access to the resource chain.doFilter(request, response);} else { PrintWriter out = response.getWriter(); out.println("Welcome. Please log in before continuing with the application."); RequestDispatcher rd = request.getRequestDispatcher("login.jsp"); rd.include(request, response);}public void destroy() {}}Filter ConfigurationFilter configuration is very much alike of that required for servlets. There is a requiredsection to define each filter to be used in the application, as well as sections to define theurl-pattern, which a filter will listen to intercept.An example of filter configuration is given below:...</context-param><filter><filter-name>LoggingFilter</filter-name><filter-class>jedi.filters.LoggingFilter</filter-class></filter><filter-mapping><filter-name>LoggingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>Given that web.xml files are very particular of the ordering of its elements, it is best to
  • make sure that the filter element entries after any context-param entries are definedbefore any servlets are defined. Also, all filter-mapping entries should be located afterany filter definition.By default, Filters are not applied towards web components (other servlets, JSP) that arethe target of include or forward calls from a RequestDispatcher object. They are appliedonly to requests that are directly made by the client. This behaviour can be changedhowever by adding one or more dispatch elements to a filters mapping....</context-param><filter><filter-name>LoggingFilter</filter-name><filter-class>jedi.filters.LoggingFilter</filter-class></filter><filter-mapping><filter-name>LoggingFilter</filter-name><url-pattern>/*</url-pattern><dispatch>REQUEST</dispatch><dispatch>INCLUDE</dispatch></filter-mapping>Dispatch elements have one of the following values : REQUEST, INCLUDE, FORWARD,and ERROR. This tells the filter whether it will be applied to client requests only, includesonly, requests only, or errors only, or any combination of the four.EXERCISES1) What are the three methods defined in the Filter interface that must be implementedby each filter class?2) When configuring a filter for use within a web application, does its configurationentries come before or after servlet definitions?3) After our filter has performed the required functionality, how does it call the nextfilter or resource in the chain?4) Consider the following scenario: We have a web application that has administrative capabilities in addition toproviding features to its normal users. If all of the administrative resources can befound in the admin directory of our application, how do we configure a filter namedAdminFilter such that all requests to admin resources pass through it first?5) Create an implementation of the AdminFilter described above. It should be able todetermine whether a user is authorized or not by retrieving a boolean value storedwithin the session. The key used to store this value is "isAdmin". If this value is true,the user is authorized. If not, user must be sent back to the login page with a messageinforming him/her that they lack the proper credentials.