Monday, January 26, 2015

EE JSP: The Reversed Jacket of Servlet

Generating HTML from Servlet is only practical if you have small amount of pages, or needed fine control of the content you are generating, (binary PDF etc). For most application, the output is going to be HTML, and we need a better way to do this; and that's where the JSP (Java Server Pages) comes in.

With JSP, you write and focus on the HTML content in a file; then only when you needed dynamic or condition logic in between the content, you would insert the Java code, which called the Scriptlet. When the application server process the JSP page, it will automatically generate a Servlet class that write these JSP file's content out (as you would programatically writing it using PrintWriter as shown in my previous posts). Wherever you have the Scriptlet in JSP, it will be inlined in the generated Servlet class. The generated jsp servlet classes are all managed, compiled and deployed by the application server within your application automatically. In short, the JSP is nothing more than the reverse jacket of the Servlet.

Here is a simple example of JSP that print Hello World and a server timestamp.

<!DOCTYPE html>
<html>
    <body>
        <p>Hello World!</p>
        <p>Page served on <%= new java.util.Date()%></p>
    </body>
</html>


Simply save this as text file named hello.jsp inside your src/main/webapp maven based folder, and it will be runnable within your NetBeans IDE. For JSP, you do not need to configure URL mapping as in Serlvet, and it's directly accessable from your context path. For example, above should display in your browser by http://localhost:8080/hello.jsp URL.

Notice the example also show how you can embed Java code. You can place a method or object inside <%= %> scriptlet, and it will use the resulted object's toString() method output to concatenate to the HTML outside the scriptlet tag. You can also define new methods using <%! %> scriptlet tag, or execute any code that does not generate output using <% %> scriptlets. Note that you can add comments in JSP between <%-- --%> scriptlet as well.

JSP also allows you to insert "Page Directives" to control how the JSP container render the result. For example, you can change the result content type by insert this on top of the page

<%@ page contentType="text/txt" %>

Another often used page directive is import Java package so you don't need to prefix it on each Java statement line.

<%@ page imporet="java.util.*" %>
 
...



 
<p>Page served on <%= new Date()%></p>

There are many more directives you can use. Checkout the JSP spec doc for more details.

Besides inserting your own Java code, JSP also predefined some variables you may access directly without declaring them. Here is an example that displays most of these built-in implicit variables.

<!DOCTYPE html>
<html>
    <body>
        <h1>JSP Examples</h1>
        <p>Implicit Variables</p>
        <table>
            <tr>
                <td>Name</td><td>Instance</td><td>Example</td>
            </tr>
            <tr>
                <td>applicationScope</td><td>${applicationScope}</td><td>${applicationScope['myAppName']}</td>
            </tr>
            <tr>
                <td>sessionSope</td><td>${sessionSope}</td><td>${sessionSope['loginSession']}</td>
            </tr>
            <tr>
                <td>pageScope</td><td>${pageScope}</td><td>${pageScope['javax.servlet.jsp.jspConfig']}</td>
            </tr>
            <tr>
                <td>requestScope</td><td>${requestScope}</td><td>${requestScope['foo']}</td>
            </tr>
            <tr>
                <td>param</td><td>${param}</td><td>${param['query']}</td>
            </tr>
            <tr>
                <td>header</td><td>${header}</td><td>${header['user-agent']}</td>
            </tr>
            <tr>
                <td>cookie</td><td>${cookie}</td><td>${cookie['JSESSIONID']}</td>
            </tr>
            <tr>
                <td>pageContext</td><td>${pageContext}</td><td>${pageContext.request.contextPath}</td>
            </tr>
        </table>
        <p>Page served on <%= new java.util.Date()%></p>
    </body>
</html>
 
In above example, I accessed the implicit variables using the JSP Expression Language (EL) syntax rather than the <%= %> scriptlet. The EL is more compact and easier to read, however it only can read variable that existed in any of the request, session or application scopes. The EL uses DOT notation to access fields or even nested fields from the object variable; assuming the fields have corresponding getter methods that is. EL can also access map with "myMap[key]" format, or a list with "myList[index]" syntax. Most of these implicit variables can be access as a Map object, and they exposed mainly from the ServletHttpRequest object on the request, as you would from your own Servlet class.

JSP can be seen as a template language in the web application. It helps generate the "VIEW" part of the application. It let you or the authoring in your team to focus on the HTML and look and feel of the content. It can help building larger web application much easier. Be careful about using excessive and complex logic Java code inside your JSP files though, as it will make it harder to debug and read; especially if you have a Java statement that throws an exception. The line number from the stacktrace would be harder to track and match to your Scriptlet code. Also imagine if you start to have JavaScript code inside JSP files, then it can get really messy. Better to keep these in separate files. If you must embed Java code in JSP, try to wrap it in a single line of Java invocation call. Better yet, try to process request using Servlet code, and generate all the data you need to display in JSP by insert them into the request scope space, and then forward to a JSP file for rendering. With this pattern, you can actually limit usage of scriptlet in JSP, and only use EL and JSP tags.

You can find above code in my jsp-example in GitHub.

Saturday, January 17, 2015

EE Servlet 3: Developing User Login with Session and Filter

I have introduced the Application class in my previous post where you can setup backend services. One example service I added is the UserService. This service will load a Java users properties file that contains username and password sets; and it's used later to authenticate users to login into the web application. Now I will show how the login part is done using standard Servlet API along with this backend service.

At a high level, what we want is to restrict some web resources (this means certain URLs provided by Servlets such as "/sysprops", or "/user") to only client users who are known in our users properties file. Users may identify themself with the matching password. This is typically done with a user login form, authenticate it, then insert a login token into Http Session scope space. This login token then can be used to verify whether to allow users to access the restricted resources or not. We only interested in a single authorization (no roles are defined, and any logged in user may access any protected URLs.)

You have already seen an example that mapped to "/sysprops" URL in one of my previous post provided by the SysPropsServlet, which it simply generate a HTML table of System information. These are sensitive information, so we want to protect this URL. We would need to create a class that implements javax.servlet.Filter interface, and then add the "/sysprops" URL with this filter so it can pre-process the request before the actual Servlet does. This filter gives us a place to inspect the HTTP request object and abort the request if needed to, thus restricting the access.

package zemian.servlet3example.web;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import zemian.service.logging.Logger;

@WebFilter(urlPatterns={"/sys-props", "/user"})
public class LoginRequiredFilter implements Filter {
    private static final Logger LOGGER = new Logger(LoginRequiredFilter.class);
    public static final String LOGIN_REDIRECT = "LOGIN_REDIRECT";
  
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            HttpServletRequest req = (HttpServletRequest) request;
            LOGGER.trace("Checking LoginSession token for uri=%s", req.getRequestURI());
            LoginSession loginSession = LoginServlet.getOptionalLoginSession(req);
            if (loginSession == null) {
                LOGGER.debug("No LoginSession token found; forwarding request to login page.");
                // We need to save the old URI so we can auto redirect after login.
                req.setAttribute(LOGIN_REDIRECT, req.getRequestURI());
                req.getRequestDispatcher("/login").forward(request, response);
                return;
            } else {
                LOGGER.debug("Request allowed using LoginSession token=%s", loginSession.getId());
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

}


Notice that you can configure this filter to match more than one URL that you want to protect. You can even use wildcard pattern such as "/*" and it will protect every URLs in your application! The filter simply looks into the Http Session space for a LoginSession object that we will create later. If it's found then it let the request through, otherwise it will redirect to a Login form page, which is served by LoginServlet class (notice the RETURN statement for early exit of the filter method without calling the filter chain!).

The LoginServlet class is a form processing Servlet that will prompt user for username and password. If it succeed, then we will insert the LoginSession token object into the HttpSession space space, which is what the filter above is looking for. Here is the processing Servlet code.

package zemian.servlet3example.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import zemian.service.logging.Logger;
import zemian.servlet3example.service.Application;
import zemian.servlet3example.service.UserService;

@WebServlet("/login")
public class LoginServlet  extends HtmlWriterServlet {
    private static final Logger LOGGER = new Logger(LoginServlet.class);
   
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HtmlWriter html = createHtmlWriter(req, resp);
        String message;
       
        // Check to see if we are doing logout or not.
        LoginSession loginSession = getOptionalLoginSession(req);
        if (loginSession != null && req.getParameter("logout") != null) {
            logout(req);
            message = "Your have successfully logged out.";
        } else {   
            message = (String)req.getAttribute("message");
            if (message == null)
                message = "";
        }  
       
        // Show a login form
        String redirectUri = (String)req.getAttribute(LoginRequiredFilter.LOGIN_REDIRECT);
        String redirectHtmlTag = "";
        if (redirectUri != null) {
            redirectHtmlTag = "<input type='hidden' name='redirectUri' value='" + redirectUri + "'/>";
        }
        html.header()
            .h(1, "Please Login")
            .p(message)
            .println("<form method='post' action='login'>")
            .println(redirectHtmlTag)
            .println("<p/>Username: <input type='text' name='username'/>")
            .println("<p/>Password: <input type='password' name='password'/>")
            .println("<p/><input type='submit' value='Submit'/>")
            .println("</form>")
            .footer();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.debug("Processing login form.");
        if (login(req)) {
            // Login succeed, we should auto redirect user if exists.
            String redirectUri = req.getParameter("redirectUri");
            if (redirectUri != null) {
                LOGGER.debug("Redirect after login to: %s", redirectUri);
                resp.sendRedirect(redirectUri);
                return;
            }
        }
       
        // Show the form again in case login failed or user didn't provide a redirect
        doGet(req, resp);
    }   
      
    protected LoginSession createLoginSession(HttpServletRequest req, String username) {
        LoginSession result = new LoginSession(username);
        req.getSession(true).setAttribute(LoginSession.LOGIN_SESSION_KEY, result);
        return result;
    }
   
    protected void removeLoginSession(HttpServletRequest req) {
        HttpSession session = req.getSession(false);
        if (session != null) {
            session.removeAttribute(LoginSession.LOGIN_SESSION_KEY);
        }
    }

    private boolean login(HttpServletRequest req) throws IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
       
        UserService userService = Application.getInstance().getUserService();
        if (userService.validate(username, password)) {
            LOGGER.info("User %s logged in successfully.", username);
            // Create Session Data here after successful authenticated.
            LoginSession loginsession = getOptionalLoginSession(req);
            if (loginsession == null) {
                createLoginSession(req, username);
                req.setAttribute("message", "You have successfully logged in.");
            } else {
                req.setAttribute("message", "You already have logged in.");            
            }
        } else {
            LOGGER.info("User %s failed to login.", username);
            req.setAttribute("message", "Invalid login.");
        }
        return true;
    }
   
    /** Return LoginSession if found in HttpSession scope, else return NULL value. */
    public static LoginSession getOptionalLoginSession(HttpServletRequest req) {
        LoginSession result = null;
        HttpSession session = req.getSession(false);
        if (session != null)
            result = (LoginSession)session.getAttribute(LoginSession.LOGIN_SESSION_KEY);
        return result;
    }
}


Inside LoginServlet class is where we use the UserService service to validate username and password. We display the login form with a GET request, and then process the login with a POST action. Once username and password are checked, we create the LoginSession object. This is just a simple POJO to represent a session token; and you can hold any user information you want. I won't list here, but you can browse it on GitHub. Note that you should make it serializable though, because any data stored in HttpSession may be subject to be serialize/deserialize by your application server.

Notice also that I have implemented the Logout functionality into the LoginServlet class as well. You simply pass "logout" query parameter, and it will be detected and remove the login token from the session. Ensure you invalid the HttpSession itself when you do this, just to be in clean side. I also exposed a static helper getOptionalLoginSession
that is used between few of the classes to check whether user has logged in or not.

These few classes are simple but yet demonstrated the use of Servlet Filter and Servlet on how to manage Session data. This programming pattern allows users to have their own browsing session and privacy through the application.

If you are to run my servlet3-example in a GlassFish server, you may login using any users listed in here.

Saturday, January 10, 2015

EE Servlet 3: How to Setup Backend Services in a Web Application

In a web application, providing user interfacing (UI) is often only half of the job. Many applications have requirements that's supported by backend services. Some example of backend services are scheduler process (batch processing), listen to a queue and respond when messages come in, or simple thing such as storing information for the entire application to use. These global data often needs to be shared between all Servlet (for each request processor) classes. Here I will show you how and where you should add such backend services in a Servlet based application.

Before we begin though, I would like to explain how a Servlet application store data variables (after all backend services are just simply Java objects). There are 3 major areas where you can add and share data (we sometimes call these areas in different "space", "scope" or "context"). You may also think of each of these area as a hash Map with unique keys and data values.

1. Application scope - This is a global, application wide storage map space that's allocated for your instance of web application. Each web application will have its unique space. Even if you deploy the same WAR file into a a domain server, they each will get their own space. You can get a hold of this space by implementing javax.servlet.ServletContextListener interface. This interface also has two callback methods that will get invoked when your application is starting (init) or shutting down (destroy). In these method you can do your own one-time application or services setup and clean up logic. You can store any Java objects by using ServletContext#setAttribute(key, value) method. This storage is not persistent externally but only in server memory. So the more you add to it, the more memory you will need (usually you only want to hold the the references to your service objects, so typically don't have memory issue). This is the location where you should create backend services and initialize it, then add the instances to the space so you may retrieve it later.

You may also use the Singleton Pattern to create a Application wide context area to hold your own business services as space, but you will still need ServletContextListener if you need to initialize it in a web application environment.


2. Request scope - This is a single HTTP request process storage map space, exits only for a specific request, or tempory. This map space is also not persistent. You will have access to this space inside your Servlet code by handling one of the HTTP action method. You will add data by using HttpServletRequest#setAttribute(key, value) method. Usually these stored data is used to pass to a VIEW processing layer (such as JSP) to construct HTML output. You have already seen some of my preview post that uses this inside a Servlet component.

Note also that inside a Servlet method that process a request, you will also have access to the Application space method above by using HttpServletRequest#getServletContext()#getAttribute(key) method.

3. Session scope - This is a special space where you can track a specific user interacations to the applicatoin as a series of conversation requests, or so call a user session. Remember that a HTTP request is stateless, so you will need this space if you want to store some data to share between multiple requests, but they should be isolated for each client browser user. This is usually used when  implementing user login and resource restriction in an application. You can add to this space using the HttpServletRequest#getSession(true)#setAttribute(key, value) method in a Serlvet class. The application server will automatically return you the same session object or space everytime for that specific client user

Handling user session can be tricky though, so you'll have to spend time and carefully designing your application to implement the proper solution for your need. I will write a seperate post on how to use Session scope in future, but for now I can show you an exmaple of how I initialize my web Application with custom services inside. You can find this code in my servlet3-example.

package zemian.servlet3example.web;

import javax.servlet.ServletContext;
import zemian.servlet3example.service.Application;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import zemian.service.logging.Logger;

@WebListener
public class WebAppStartup implements ServletContextListener {
    private static final Logger LOGGER = new Logger(WebAppStartup.class);

    @Override
    public void contextInitialized(ServletContextEvent event) {
        LOGGER.debug("WebApp is starting up.");
        Application app = Application.getInstance();
        app.init();
               
        // Store the app instances.        event.getServletContext().setAttribute(Application.SERVLET_CONTEXT_KEY, app);
        LOGGER.info("WebApp initialized.");       
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        Application app = Application.getInstance();
        app.destroy();
        LOGGER.info("WebApp destroyed.");
    }
}


With this in place, I can easily add any custom business backend services inside the Application class, and and then have any of the Servlet code access it. Notice that I am using Servlet 3's @WebListener annotation so there is no config is needed. You simply package along your WAR application and it will be detected by your EE application server!

NOTE: Try to use Application as holder class only and not place any logic in it. With EE 6, you can easily replace this with CDI bean injection as alternate solution.

Wednesday, January 7, 2015

EE Servlet 3: Simple Form Processing

Form handling in web application is like bread and butter for most Web developers. It will not be much use if we can not capture users input and process it. So I have included a simple FormServlet in my servlet3-example  that demonstrated few frequently used form inputs you might encounter. Here is how it looks like:

package zemian.servlet3example.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import zemian.service.logging.Logger;

@WebServlet("/form")
public class FormServlet extends HtmlWriterServlet {
    private static final Logger LOGGER = new Logger(FormServlet.class);
   
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HtmlWriter html = createHtmlWriter(req, resp);   
        String message = getMessage(req);
       
        html.header()
            .h(1, "User Data Form")
            .p(message)
            .println("<form method='post' action='form'>")
            .println("<p/>Username: <input type='text' name='username'/>")
            .println("<p/>Password: <input type='password' name='password'/>")
            .println("<p/>Choose a country: <select name='country' size='1'>")
            .println("<option default='true'>US</option>")
            .println("<option>China</option>")
            .println("<option>Korea</option>")
            .println("</select>")
            .println("<p/>Skills set: <input type='checkbox' name='skills' value='Java'/> Java")
            .println("<input type='checkbox' name='skills' value='Java EE'/>Java EE")
            .println("<input type='checkbox' name='skills' value='MySQL Database'/> MySQL Database")
            .println("<p/>Notes: <textarea name='notes' cols='50' rows='3'></textarea>")
            .println("<p/><input type='submit' value='Submit'/>")
            .println("</form>")
            .println(html.link("Back to Home", "/index"))
            .footer();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.info("Processing form.");
        Form form = new Form();
        form.setUsername(req.getParameter("username"));
        form.setPassword(req.getParameter("password"));
        form.setNotes(req.getParameter("notes"));
        form.setCountry(req.getParameter("country"));
        String[] skills = req.getParameterValues("skills");
        skills = (skills == null) ? new String[0] : skills;
        form.setSkills(Arrays.asList(skills));
        req.setAttribute("message", "Processed: " + form);
        doGet(req, resp);
    }
  
    private String getMessage(HttpServletRequest req) {
        String message = (String)req.getAttribute("message");
        if (message ==  null) {
            message = "";
        }
        return message;
    }

}

As usual, most forms are display with a http GET request and then process it with a POST action. Take a closer look, and pay close attention to how Servlet handle single vs multi values inputs. These exist because HTML form might allow users to choose multiple values from a single input tag/widget.

One common pattern developers do in form handling is to capture the input data into a "command object", "transfer object", or (in my example) "form" object; so that data can be pass into another layer of your application for further processing. This is a good design becuase it decouples the Web layer dependencies from your backend tier service layers.

Another frequent dealt with area in form processing is data validation. If you capture your data as form object, then you will likely have two layers of validations. One layer is when you extract it right off the http request (usually from a String input), then you would validate such as is it a required field or optional, is the String value convertable to the expected and desiable type (integer or date etc). Second layer of validation might be further down in your service layer where you already have the form object constructed with correct types, but their values might not be valid per your application requirement. Most common invalid data is due to not conforming to the database constraints and thus not able to persist it. I didn't provide example above on validation, but you can eaisly improve the Servlet and further explore this on your own.

I like to mention one more note. There are many Java web frameworks out there that focus a LOT of attention on form handling, and they ought to help you develop application easier with less duplicated code. It is done usually with a very concrete programming model and style that, in many cases, shield you away from seing the HttpServletRequest object completly. All these are good (assuming the framework is a good quality one), but keep in mind that majority of cases when there is a problem occur, it's mostly at the framework specific layer, or even more likely your own code that use the framwork. And then you will be spending most of your debugging time learning the framework specific domain, rather than the Servlet spec layer.

For my example purpose I am trying to focus on EE API alone, so I will stay away from any extra frameworks other than the standard API. If you are a beginner, I strongly encourage you to study the Servlet API and see how form is handled, this gives you a more solid understanding of how the data come about in a web application. If you look further into the Java EE stack, it actually already has a framework that's called JSF as part of EE 6 standards. It's design is to help construct web pages as components model; and it lets you capture form data and automatically bind to a bean object in a much more smoother and integrated fashion. JSF is worthy of its own topic for future posts.


Friday, January 2, 2015

EE Serlvet 3: Generating HTML output in Servlet

If you just need to handle a handful of requests URI in your EE web module, then it might be easier to generate your own HTML response in your Servlet code instead of using a full blown template library. As part of my examples, I tried out a very simple Java DSL that generate html output when writing your own Serlvet. The code looks like this:

package zemian.servlet3example.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/index")
public class IndexServlet extends HtmlWriterServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HtmlWriter html = createHtmlWriter(req, resp);
        String message = getMessage(req, html);
       
        html.header()
            .h(1, "Welcome to Servlet 3 Example")
            .p("Let's explore Java Servlet 3.x Features.")
            .p(message)
            .ul(
                html.link("Index", "/index"),
                html.link("Hello", "/hello"),

                html.link("Sys Props", "/sys-props")
            )
            .footer();
    }

}

I wrote a base HtmlWriterServlet class that provide a method where you can get an instance of a HtmlWriter builder. The benefit of wrapping the HTML like builder is that it's more easier to read and helps generate correct well form tags. For example the "ul" and "table" accepts Java List or Map object, and it generates the correct html tags.

Here is another example how I generate a table view of Java System Properties page with few lines of code:

package zemian.servlet3example.web;

import java.io.IOException;
import java.util.TreeMap;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/sys-props")
public class SysPropsServlet extends HtmlWriterServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HtmlWriter html = createHtmlWriter(req, resp);
        TreeMap sysProps = new TreeMap(System.getProperties());
        html.header()
            .h(1, "Java System Properties")
            .table(sysProps)
            .footer();
    }
}



The simple HtmlWriter class provide few html builder methods and it can help generate HTML links with relative context paths. You can easily further improve it to help generate more HTML code such as form tags etc.

Also, note that ServletResponse object let you have full control on writing custom responses, so you are not restricted to only returing HTML. You can write binary output such as PDF or even MP3 files. You simply need to control the Response Writer and the correct corresponding content mime type and size that will return.


You can get these code at servlet3-example