Monday, March 26, 2012

The Web Container in a nutshell


General Overview

This topic is a discussion of the general JEE web container components. While useful, this isn't a discussion of any of the frameworks built upon the JEE web container such as struts, JSF, Spring MVC or others. Each of these frameworks have their own sites with a plethora of examples and other information. Each of the following sections contain a component or piece of the web container setup. This paper also does not get into other Enterprise components such as JMS or EJB, although there are ways for the web container to use these components and those places will be mentioned.

Web Contexts

There are 4 different contexts in the web container, in parentheses would be their object variable equivelant:
  • Application (static)
  • Session (class)
  • Request (method)
  • Page (Only applicable on the JSP) (sub-method)
Application scoped variables are available to every web piece. They're available within a given servlet/jsp request, they're available to the session and any setup for a servlet, listener, filter or any other web component, just like static properties are available to any method in a class and all instances all can see the same static parameter. Just like static variables, any change to an application scoped variable will be seen by the rest of the application.
Session scoped variables are tied to a specific user that span multiple requests. This would be like creating a configuration object in a general project to store information about a specific process for the length of the process. Any sub process that originates from this process will get the same data in this configuration object. Once the process is done the object is discarded, just like a session when a user leaves the system (or a timeout occurs before the nest request from a specific user).
Request scoped variables are tied to a specific request on the server. The parameters only live for the length of the request and are reset with the next request. In object speak these would be just like parameters created within a request. Variables within request don't require a visibility modifier (such as public) because once the method is done the variables are cleaned up and rest for the next request.
Page scope is a special case of the request scope used only for JSPs. Many custom tags will create properties and, in most cases, store them in the page scope for use on that specific page. If you were to be redirected to another page (an extremely unlikely thing but still possible) these variables are wiped clean which makes this scope a perfect place to store this temporary information.

Servlets

Servlets are the primary way to execute logic in a web application. While you do have direct access to the output stream that is returned to the client it is generally considered proper form for the servlet to execute the logic (such as accessing a database, interacting with a web service or an EJB), set parameters in one of the web contexts and then forward to a JSP to implement the actual rendering logic. One usual deviation from this would be if you have to return some kind of non-viewable content (such as an excel, PDF or other file) for the user to save outside the HTML viewing process.
You can chain servlets together using the HttpServletRequest.forward() and the HttpServletResponse.sendRedirect() to chain logic (or, generally using the former) to use a JSP to render the result back to the user. One thing to note on the sendRedirect() method, it sends a response back to the browser and tells the browser to go to the page so any request variables that were set will be reset when accessing the redirected resource. Usually, instead of directly chaining servlets, filters would be used. These components are covered in a later section.

JSP

JSPs are actually special servlets that are intended to just render content for the user. The web server will actually compile the JSP on the back-end into a servlet for quicker access. They're intended to be very light weight and just take properties set in a servlet and render them to the user.

Scriptlets

Scriptlets are defined as anything between <% and %>. Everything between the braces must be valid java. A special cased where the output is rendered directly to the screen is the <%= %>. Whatever is between the braces is evaluated and the result is rendered to the screen, you shouldn't put a semi-colon at the end of this expression. In general a mature project should not use these as they're generally reserved for lightweight projects that don't use servlets at all. If you find yourself using scriptlets you most likely should be doing more work in the servlet or creating a custom tag to keep from cluttering the page.

Expression Language

JSPs have their own expression language for quick and easy access to scoped variables. The format of the expression is ${..} where the first word inside the braces is a variable name in a scope. After the variable name you can access properties based on dot notation. So, if you had an expression like the following ${foo.bar} the jsp would look in the all the contexts (more on the order in a minute) for a property called 'foo', and once it finds the object it will try to access the property getBar() (or isBar() if the property is a Boolean). You can chain this down to any level you wish, as long as the chain is valid. You can also access indexed or mapped properties using brackets so an expression like the following: ${foo[0].bar} would try to find a list in a context called foo, retrieve the first element and access the bar property of that object. As a convenience for a map property you can use the dot notation to access a entry of the map so ${foo.bar} would be the same as ${foo['bar']} if 'foo' is a map.

Tag Libraries

Tag libraries are self contained pieces of rendering logic that an be accessed just like any other tag. There are standard tag libraries (generally called JSTL) and nearly every framework has a set of tag libraries for use with the framework. You define them at the top of the JSP file using the format <%@ taglib uri=”uri” prefix=”x”>. With the preceding tag declaration to use the taglib you'd start your tags with <x:....> where the colon is followed by the tag definition. Think of a definition as a method call to render some kind of element. Now, there are standard tag libraries for things like database connections but most mature projects won't use them as they're targeted at stand alone JSPs. The most common tag libraries used are core as <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> and format as <%@ taglib prefix="f" uri="http://java.sun.com/jstl/fmt" %>. There are additional tag libraries like sql and xml but most of these are covered by a framework.

Custom Tag libraries

If the standard tag libraries and your framework's tag libraries aren't sufficient for your needs you can roll your own tag library. To do this you create an XML file called <name>.tld and place it in your WEB-INF/tld directory. The XML file has to implement the http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd schema. You can view a tutorial on Oracle's site for exactly how to write a TLD but essentially there are two types of tags:
  1. Static function calls you want to expose in your application to the JSPs. These are defined using the <function> tag with the function-class and function-signature elements
  2. The <tag> class to define the traditional tag setup where you define the tag class with tag-class and body-content to define how to handle sub tags or sub html elements.

Filters

Filters are a command pattern for usage with Servlets. Filters can operate before the servlet call on the request and after the servlet call on the response. For the request side they can be useful for things like verifying a user has logged in (assuming you aren't using container managed security defined below) and forwarding to a login page before secured sections of the app. You can also perform actions like retrieving necessary information or instantiating objects needed by the servlet (such as data access objects or common lookups) since filters can be shared across multiple servlets. On the outbound side they're useful for things like encrypting output when necessary any other cleanup tasks necessary after a servlet is done executing its tasks.

Listeners

There are two different kind of listeners in a standard web application:
  1. SessionListeners
  2. ApplicationContextListeners
Both listeners are essentially the same thing but targeted at different levels of the web container. They both have two methods to implement, one for when an object is created and one for when that object is destroyed.
For the Session listener it's targeted (not surprisingly) at when each session is created or destroyed. While not extreemly useful, it can be used to track when a particular user has logged in (which can also be done through a filter for each request) or useage statistics. When sessions are destroyed you could go through the session and serialize items for retrieval upon re-creation or closing resources that were stored in the session but these are generally fringe cases.
The application context listener is called twice during the life of a web app, once when the application starts up and once when it shuts down. In it, you can run anything that you need to manually set up or tear down.
One thing to note about both these listeners, tread lightly on the closing of resources when things stop. While you're guaranteed to see things start up the app could crash and the shutdown methods may not be called (a general problem anyway but something to remember)

WAR packaging and web.xml

The WAR file is a standard JAR file with a .war extension that can be decompressed and used by an application server.
The web.xml file is the configuation file for a web application. In this file you define all listeners, servlets, servlet mappings and all other less common web application components. As you'll see below, it's located under the WEB-INF directory and is required to deploy a web application.


Directory layout
/ (all jsps go at this level for standard access through the browser)
/WEB-INF (in here you put any other configuration file (other than classes and jars)
/web.xml
/classes (all classes for the web app go here)
/lib (any dependent libraries for your web ap)
/scripts (standard but configurable location for javascript files)
/images (standard but configurable location for images)

Security

While there is no standard way for an application server to set up security there are standard ways to interact and set up restricted access in the web app. There are two prominent ways to deal with security. Neither way is definitively better than the other and they can easily be used together.
The first way is declarative through the web.xml config file using the <security-constraint> tag. Inside this tag you define what url patterns you want to secure (they can be hard paths referenced by a jsp or virtual paths defined in a servlet mapping) and the roles necessary to access these resources. When a request is made the server will check if the request has an authenticated user and if not then redirect them to a login page for authentication. Once authenticated, it will check the roles assigned to that user to see if one matches what is necessary to access the page. Both the page and the user can have multiple roles and only one matching role is necessary. If no roles match then a forbidden page (403) is returned to the user.
The other authentication mechanism is progromatic security (which relies on the user being authenticated on the system). There are two methods on the HttpServletRequest object that deal with authentication:
  • getUserPrinciple()
  • isUserInRole(String)
getUserPrinciple() returns a UserPrinciple object if the user is logged in with information about the logged in user, otherwise it's null. The isUserInRole takes in a role as a string and returns true if the user has that role. These are available in both the servlet and on jsp pages to conditionally render JSP elements or conditional business logic on the server.

Resources

Resource-ref

Resource-ref is used to define connection factories for enterprise components. Some of the standard enterprise factories are:
  • DataSource
  • QueueConnectionFactory
  • TopicConnectionFactory
  • Session (for JavaMail)
The declaration includes a JNDI location where to find the resource.

Env-entry

The env-entry tag is used to define a property (similar to a jvm property) for use by the web application. The following types are possible:
  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short
  • java.lang.String
These properties are useful for values that change based on the environment. One example would be if you have to store report files you can make the directory where they're stored an environment property so you can put the same WAR file in each environment and update the environment value on the server.

No comments:

Post a Comment