Damodar's Musings

web development and miscellany

Browsing Posts published by Damodar Chetty

The simplest and easiest backup solution is built right in Redmond!

I’ve used SyncToy for a number of years now and this program is a nice little gem – sort of XCOPY with a GUI. It can be downloaded from here.

It takes pairs of source and destination directories and then keeps them in sync. It works great for backing up photographs, for instance. And, the best part is that the files are exact copies – no need to worry about native backup formats.

Even better is that SyncToy comes with a command line invoker, SyncToyCmd.exe.

You get a backup solution when you combine this invoker with the Windows 7 Task Scheduler (which lives at: Start Menu > All Programs > Accessories > System Tools.)

You can use the scheduler to set up a regularly scheduled task to run “SyncToyCmd.exe -R <folder-pair-name>”

The scheduler can also be configured to run this command line program at startup, and then at predefined intervals (of say, an hour) to give  you real time backups as you work on your system.

Awesome? Yes, truly. Simple? Ditto.

Updated  on: Mar 13, 2011. Describes the process for verifying the installation of MySQL and phpMyAdmin.

In this article, I describe the process of setting up a complete development environment for PHP, with full debugging support within the Eclipse IDE.

The complete setup includes Ubuntu 10-10, the Apache2 web server, the MySQL RDBMS, PHP, phpMyAdmin, the Zend Eclipse/PDT All in one package, and the PDT debugger.

Setting up a PHP Debugging Environment

Go to http://www.zend.com/en/community/pdt#debugger and download Eclipse PDT All-in-one. I picked the Linux 32 bit version for installation in Ubuntu.

Unpack the downloaded file (zend-eclipse-php-helios-linux-gtk-x86.tar.gz).

Execute the eclipse/eclipse executable to launch Eclipse, and pick the appropriate workspace.

Create a new PHP project (File > New) and ensure that its location is in the same area that is monitored by your Apache install. In my case, this is /home/damodar/public_html, so my “test” project is located at /home/damodar/public_html/test.

Create a new PHP file.

Debug as PHP Script, if you want to run it locally in a PHP interpreter within the PDT.

Debug as PHP Web Page, if you want to run it in a browser.

You can place breakpoints as appropriate.

Enjoy!

(Thank you Zend Technologies, for making this so easy!)

Note: You can also use the Zend Server Community Edition as your web server. As noted, I chose to stay with Apache instead.

An errant application was causing my phone to spontaneously recycle – I gave up after about a half dozen cycles.

Verizon support indicated that I should perform a safe mode reboot and uninstall any suspect apps. The process was fairly painless, and I was up and running in a few minutes … sans my most recently installed apps.

The process?

Hold the power key down, and when you see the Motorola logo (the big M), press and hold down the Menu key for 30 seconds. This boots your Droid X into safe mode.

Also the Android 2.2 update was simply awesome for the Droid X – it’s as if I installed a brand new battery. The phone seems to be a lot more conservative about using power, leaving me as one thrilled puppy. Fingers crossed.

The easiest way I’ve found to get my contacts from Outlook to my Droid X … check out transferring contacts between Outlook and Gmail .

Decidedly low tech – but it was much easier than retyping :)

To sync your calendar – try Google Calendar Sync.

Good luck!

What a pain the Droid X is turning out to be. I can’t live with it, and I can’t live without it.

It’s like a pair of shoes that look and feel amazing, but just don’t fit quite right. You spend a lot of time hoping your feet were of the right size :(

It’s actually one of the most amazing devices I’ve ever owned – the display is simply gorgeous, and the interface is amazing.

So what’s not to like? Well how about its battery life? My battery drains even while the phone is inactive. And, by drain, I mean it goes down by as much as 40% while it sits on my bedstand.

My workaround? Turn it off before I go to bed – or leave it charging all night.

And, by default, the Wifi turns itself off when the screen is turned off. Then when you turn the phone back on, you don’t get online without waiting for anywhere from 5 to 15 to 30 minutes. Even your 3G is powerless to help.

My workaround? I found this on a Moto forum – go into advanced settings and choose not to turn off Wifi when the display is turned off. I’m guessing this will eat up battery – but it’s much better than having to wait for Wifi to kick in.

Will I return this phone, and get a Droid 2 or the Incredible instead? I’m not sure – ask me in 2 weeks.

For now, I’m folding my feet so they fit into these shoes. Maybe I’ll get used to walking this way :)

One of the easiest ways to protect oneself whilst online is to function within a virtual machine environment. In such a scenario, even if you do catch a nasty bug doing something that you probably shouldn’t, the infection is confined to that virtual machine and does not spread to the rest of your computing environment.

To that end, I’ve been playing with Sun’s VirtualBox and the free distribution of Ubuntu Lucid Lynx (10.04). Together these make an unbeatable combination.

I got VirtualBox from here:

http://download.virtualbox.org/virtualbox/3.2.8/VirtualBox-3.2.8-64453-Win.exe

And, though I’m running Windows 7 64-bit, I downloaded the 32-bit version of Ubuntu from here:

http://www.ubuntu.com/desktop/get-ubuntu/download

Once VirtualBox is installed, you can directly install Ubuntu by mounting its ISO image into VirtualBox.

The only thing you should remember is to install the Guest Additions for Linux. Without doing so, maximizing the VirtualBox window does not maximize the Guest OS’s window. To do so, you need to choose Devices > Install Guest Additions to mount the guest additions disk image. Once this shows up on your desktop, browse into it, and execute the autorun.sh file from a Terminal window. If you don’t see it take effect right away, you might want to restart your virtual machine.

You can also share a folder between the host and guest operating systems, using the following commands:

1. Create the folder on the host OS. (C:\ubuntu-vbox)

2. Register it with Virtual Box using Devices > Shared Folders, and give it a logical name to be used later (ubuntu-vbox).

3. Create the mount point
$ sudo mkdir /mnt/shared

4. Next, mount the shared folder.
$ sudo mount.vboxsf ubuntu-vbox /mnt/shared

5. That’s it – now you can access files on /mnt/shared from Ubuntu, and on c:\ubuntu-vbox from Windows!

It is also very simple to install a complete LAMP stack – Apache 2, PHP 5, MySQL, and phpmyadmin on our fresh install of Ubuntu 10.04. Check out these links for tips:

http://blogote.com/2010/ubuntu/how-to-install-apache-2-on-ubuntu-10-04-with-php5-and-mysql-support-guide.html

http://www.shicho.net/lamp/?p=138

A key aspect of using Ubuntu in VirtualBox is to ensure that you have installed any guest additions. This enables sharing of folders as well as full screen displays. To install guest additions, first start up your Ubuntu instance. Then, select Devices > Install Guest Additions in the VirtualBox menu of your running Ubuntu instance. This adds a CD image to your Ubuntu  desktop named VBOXADDITIONS_<version>. Browse to this  image using the Places menu, and execute autorun.sh.

That’s the sprinkling of pixie dust necessary to get a fully functional Ubuntu install!

All right – now, we’re finally ready to get to the meat of what JSR 315 brings to the table – asynchronous servlets.

Prior to JSR 315, the world was a very simple and pleasant place. It was the world of the synchronous web. The server maintained a server socket that waited at the gates for weary incoming requests, and as each one arrived, assigned a worker to help it accomplish its needs. In this model, there was a finite set of workers (or server threads), and once all available workers were busy, new incoming requests had to wait at the gate until a worker completed processing its current request.

The process of setting up and tearing down socket connections is an expensive operation, and the process of TCP bandwidth throttling means that the earlier transmissions over a new connection are slower than later ones. As a result, HTTP 1.1 introduced its keep-alive connection model, which allowed a client to hold the connection open (i.e. to have a worker thread assigned) until all resources on a given page were retrieved.

This model works very well, and is both very performant and scalable, since requests come in at staggered intervals, allowing a small thread pool to successfully handle a large volume of client requests.

However, all was not well in the good old days.

First, was the issue of thread starvation. Each thread consumes server side resources – both memory and CPU resources. As a result, the number of threads within the pool must be constrained to some finite number. Furthermore, if the processing that the thread must perform for a client requires some blocking operation (say waiting on some slow external resource such as a database or web service), that thread is effectively unavailable to the server. In other words, it is possible that all threads in the pool are soon blocked and incoming requests can no longer be effectively handled. This is not just a theoretical problem. With the prevalence of fine grained Ajax-requests, and the adoption of SOA, the load on web servers is on an upward trend.

Second was the issue of staleness. At any given point, a client gets a view of the web application’s state at the instant that the request was procesed. Any changes to state between two consecutive requests from a client, are effectively invisible to that client. In other words, each client only gets a static snapshot view into what is effectively a dynamic system. And the currency of that view decays the longer the time period between requests. Ajax’s fine grained interactions, do mitigate this problem, but it does not completely solve the currency issue.

Third was the issue of non standard implementations. The developers of every servlet container decided to solve this problem of the synchronous web by implementing their own custom solutions. Tomcat’s Comet, WebLogic’s FutureResponseServlet, and WebSphere’s Asynchronous Request Dispatcher are examples of developers not wanting to wait for the standards  body to catch up.

A key piece of JSR 315 therefore was to solve these issues with the synchronous web, by introducing us to the asynchronous web.

The problem of thread starvation is solved by having the main request processing worker thread delegate processing to an asynchronous thread, and return to the thread pool. In other words, if processing will require blocking operations, the worker can put the request processing context on ice, and hand it off to an asynchronous thread for processing. It can then return to the thread pool and wait for the next incoming request.

The problem of staleness is solved by allowing the client to make preemptive requests. I.e., just as soon as the client receives a snapshot, it can turn around and immediately make a preemptive request for the next snapshot. This request can be handed off to an asynchronous processor on the server, which will be notified when a state change occurs, and can immediately return a response to the waiting client. As far as the client is concerned, this looks just like any other long running request. Of course, with the advantage that there’s hardly a lag between a server side state change, and a client notification.

Finally, this solves the standardization issue by codifying asynchronous behavior into the servlet specification. This is now the one approach to rule them all!

So what do we need to implement asynchronous servlets?

  • Thread Pool and Queue
    If you haven’t read my previous blog post on thread pools in Java, this is the time to go do so. An Executor and ExecutorService provide us with a mechanism to implement our pool of asynchronous workers.
  • AsyncContext
    The context of the request must be stored for later use by the asynchronous worker thread. This is achieved using an AsyncContext instance, which holds the request and response that was provided by the container to the original servlet.
  • Runnable instance
    This instance encapsulates the actual processing of the blocking operation on the asynchronous thread.
  • Servlet/Filter chain
    All components that will participate in an asynchronous request must be marked as supporting asynchronous operation.

Let’s walk through the recipe of creating an asynchronous servlet:

  1. At context startup, a context listener is used to set up an Executor.
  2. Servlets that might involve a blocking operation are identified and marked as asyncSupported (annotation or web.xml declaration). Any servlets/filters in the processing chain for this servlet are similarly marked.
  3. Within its service() method, the asynchronous servlet then:
    1. Invokes startAsync() on the request
    2. Wraps the returned AsyncContext in a Runnable
    3. Hands the Runnable off to an Executor for asynchronous processing
    4. Returns from the service() method. For an asynchronous servlet, returning from this method does not automatically commit the response. As a result, the client has no idea that it is being given the run around – it patiently waits for the response.
  4. The main thread returns to the server’s pool, ready to handle the next incoming request.
  5. The Executor assigns an async thread to process the Runnable.
  6. The Runnable:
    1. Uses the request and response stored in its AsyncContext
    2. Accesses any request attributes/parameters that are stored in its request to perform its processing
    3. Stores the final result of the processing as a request attribute
    4. “Completes” the response – either by generating the response by itself, or by dispatching to a server side resource.
  7. The client now displays the resource.

To the client, this interaction is no different from a slow server taking an inordinate amount of time to respond.

To the server, the server worker thread spent only a fraction of the time it would have normally taken to handle such a request, helping its throughput significantly.

The actual processing was handled by a thread in a separate pool – without impacting the main server pool.

The servlet context listener does nothing more than set up a ThreadPoolExecutor with 10 threads, and a request queue with a limit of 100 pending requests.

package com.swengsol.listeners;
/**
 * User: Damodar Chetty
 * Date: Jul 23, 2010
 * Time: 10:48:14 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */

import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import java.util.EnumSet;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

@WebListener
public class MyServletContextListener implements ServletContextListener {
    private static final Logger logger = Logger.getLogger("com.swengsol");

    // Public constructor is required by servlet spec
    public MyServletContextListener() {
    }

    // -------------------------------------------------------
    // ServletContextListener implementation
    // -------------------------------------------------------
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("Context Listener > Initialized");

        //2. Creation of a global async Executor
        Executor executor =
					new ThreadPoolExecutor(10, 10, 50000L,
						TimeUnit.MILLISECONDS,
						new LinkedBlockingQueue<Runnable>(100));
        sce.getServletContext().setAttribute("executor", executor);
    }

    public void contextDestroyed(ServletContextEvent sce) {
    }
}

The servlet is marked with an annotation to indicate that it supports async processing. Some key elements to note are:

1)    The presence of the dispatch parameter on the query string will allow us to control how the async request completes (whether it is handled completely by the asynchronous processor or whether it is forwarded on to another server side resource).

2)    The timeout parameter allows us to set a timeout for an asynchronous request. The request is aborted if it does not complete within the specified timeout.

3)    The call to startAsync() builds up the AsyncContext, which represents the context of the current request.

4)    An AsyncListener can be registered to be notified of events within the asynchronous process– such as timeouts.

5)    The thread pool with our async worker threads is retrieved from the servlet context, and is given an instance of our Runnable to process – an AsyncRequestProcessor.

6)    The main worker thread now returns without committing the response.

package com.swengsol.servlets;

import com.swengsol.AsyncRequestProcessor;
import com.swengsol.listeners.MyAsyncListener;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Logger;

/**
 * User: Monsty
 * Date: Jul 23, 2010
 * Time: 9:43:25 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */
@WebServlet(urlPatterns = "/AsyncServlet", asyncSupported=true)
public class AsyncServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger("com.swengsol");

    protected void doPost(HttpServletRequest request,
			HttpServletResponse response)
		throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request,
			HttpServletResponse response)
		throws ServletException, IOException {
        logger.info("AsyncServlet: Processing request: " +
					request.getParameter("id") + ". on thread: " +
					Thread.currentThread().getId() + ":" +
					Thread.currentThread().getName() + "[" +
					new Date() + "]");

				request.setAttribute("receivedAt", new Date());

        boolean dispatch = false;
        String dispatchParam = request.getParameter("dispatch");
        if ("true".equalsIgnoreCase(dispatchParam)) dispatch = true;

        boolean timeout = false;
        String timeoutParam = request.getParameter("timeout");
        if ("true".equalsIgnoreCase(timeoutParam)) timeout = true;

        AsyncContext asyncCtx = request.startAsync();
        asyncCtx.addListener(new MyAsyncListener());
        if (timeout) {
            asyncCtx.setTimeout(1000);
        }

        Executor executor =
			(Executor)request.getServletContext().getAttribute("executor");
		//delegate long running process to an "async" thread
        executor.execute(new AsyncRequestProcessor(asyncCtx, dispatch));

        logger.info("AsyncServlet: Returning after request: " +
					request.getParameter("id") + ". on thread: " +
					Thread.currentThread().getId() + ":" +
					Thread.currentThread().getName()+ "[" +
					new Date() + "]");

				//Watch out for concurrency issues at this point
				// between the "main" thread and the "async" thread
				// main thread returns now -
				// - returning from service() does not commit the response
				// - so client still waits patiently
    }
}

The nice thing about this is that the servlet itself is pretty formulaic – and shouldn’t change much from one async servlet to the next. But all the complexity of processing has to go somewhere – and that somewhere is the AsyncRequestProcessor.

Also note the comment at the bottom of the file that indicates that there is now a short window of time here when the request and response objects are no longer thread safe. Ideally, you shouldn’t be mucking around with the request and response objects once you’ve handed them off to the async processor.

The asynchronous request processor is a Runnable instance that needs access to the AsyncContext that we previously retrieved from the request. In our example, note that the long running blocking operation is encapsulated within the longRunningProcess() method.

package com.swengsol;

import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * User: Damodar Chetty
 * Date: Jul 23, 2010
 * Time: 9:45:22 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */
public class AsyncRequestProcessor implements Runnable {
    private static final Logger logger = Logger.getLogger("com.swengsol");

    private AsyncContext asyncContext;
    private boolean dispatch;
    public  AsyncRequestProcessor(AsyncContext asyncContext) {
        this.asyncContext = asyncContext;
        dispatch = true;
    }
    public AsyncRequestProcessor(AsyncContext asyncContext,
		boolean dispatch) {
        this(asyncContext);
        this.dispatch = dispatch;
    }
    public void run() {
        //do something asynchronously –
		//  wait for a resource to become available
		//  or for a long running computation to finish
        String reqId = asyncContext.getRequest().getParameter("id");
        if (null == reqId || reqId.length() == 0) reqId = "<unk>";
        long id = Thread.currentThread().getId();
        String threadName = Thread.currentThread().getName();
        if (null == threadName || threadName.length() == 0)
			threadName = "";
        String threadId = id + ":" + threadName;

        String result = longRunningProcess(reqId, threadId);

        //Store the result of the computation in a "view helper"
        ServletRequest req = asyncContext.getRequest();
        if (null != req && req.isAsyncStarted())
					req.setAttribute("result", result);
        else
					return;

        //once done, dispatch back to the final destination
        if (dispatch) {
            asyncContext.dispatch("/results.jsp");
        } else {
            //alternatively handle it ourselves
            String html = "Result of the process for request id: " +
					reqId + "<br/> Started at:" +
					asyncContext.getRequest().getAttribute("receivedAt") +
					".<br/> Completed at:" + result +
					"<br/> Called complete.";
            Squawker squawker = new Squawker(html);
            asyncContext.getResponse().setContentType("text/html");
            try {
                PrintWriter out = asyncContext.getResponse().getWriter();
                out.println(squawker.getHTML());
            } catch(Exception e) {
                logger.log(Level.WARNING, e.getMessage(), e);
            }
            asyncContext.complete();
        }
    }

    public String longRunningProcess(String reqId, String threadId) {
        Random randomGenerator = new Random();
        int randomInt = 5000 + randomGenerator.nextInt(10000);
        logger.info("AsyncRequestProcessor: Begin long run process (" +
					randomInt + " ms) for request: " +
					reqId + ". on thread: " + threadId +
					"[" + new Date() + "]");

        try {
            Thread.sleep(randomInt);
        } catch (InterruptedException ie) {
            logger.log(Level.WARNING, ie.getMessage(), ie);
        }

        logger.info("AsyncRequestProcessor: Done processing request: " +
					reqId + ". on thread: " +
					threadId + "[" + new Date() + "]");
        return new Date().toString();
    }
}

In this example, the long running process simply sleeps for a random amount of time to simulate the randomness of accessing a remote resource. It takes anywhere from 5 to 15 seconds to complete its work – an eternity on the web. You can also imagine report generation processes that might take much longer.

Once the long running process has returned, we either dispatch the request to be handled by a server side resource (results.jsp), or we handle it ourselves by handcrafting the HTML to be returned. In the latter case, we have to explicitly call complete() on the AsyncContext instance. In the former, the container does so implicitly.

The server side resource that we forward our asynchronous request to is results.jsp. This file demonstrates how request attributes added by the async processor can be retrieved and used.


<%--
 * User: Damodar Chetty
 * Date: Jul 23, 2010
 * Time: 9:45:22 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
	<head>
  	<title>Introducing Servlet 3.0</title>
    <link rel=stylesheet type="text/css"  href="styles.css">
	</head>
	<body>
		<p class="mainpara">
			results.jsp:
			completed processing of long running activity with id:
			<span style="color:#ff3300">
				<%=request.getParameter("id")%>
			</span>
			<br/>
			received  at: <%=request.getAttribute("receivedAt")%>: <br/>
			completed at: <%=request.getAttribute("result")%>
		</p>
		<p class="copyright">Damodar Chetty,
			Software Engineering Solutions, Inc.</p>
	</body>
</html>

My sample code running on GlassFish v3 did not run until I added an XML declaration for my async servlet. To me this looks like a bug in the RI.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

	version="3.0">
    <servlet>
        <servlet-name>AsyncServlet</servlet-name>
        <servlet-class>com.swengsol.servlets.AsyncServlet</servlet-class>
        <async-supported>true</async-supported>
    </servlet>
</web-app>

The final class we will visit is our AsyncListener which is rather trivial in my sample implementation. If you check your GlassFish logs, you’ll notice entries for the async listener which indicate when the async processing was completed.

package com.swengsol.listeners;
/**
 * User: Damodar Chetty
 * Date: Jul 24, 2010
 * Time: 2:36:08 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */

import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import java.util.logging.Logger;

public class MyAsyncListener implements AsyncListener {
    private static final Logger logger =
		Logger.getLogger("com.swengsol");

    // Public constructor is required by servlet spec
    public MyAsyncListener() {    }
    public void onComplete(AsyncEvent ae) {
		logger.info("AsyncListener: onComplete for request: " +
			ae.getAsyncContext().getRequest().getParameter("id"));
	}
    public void onTimeout(AsyncEvent ae) {
		logger.info("AsyncListener: onTimeout for request: " +
			ae.getAsyncContext().getRequest().getParameter("id"));
	}
    public void onError(AsyncEvent ae) {
		logger.info("AsyncListener: onError for request: " +
			ae.getAsyncContext().getRequest().getParameter("id"));
	}
    public void onStartAsync(AsyncEvent ae) {
		logger.info("AsyncListener: onStartAsync");
	}
}

This servlet can be invoked using the URL:

http://localhost:8008/jsr315/AsyncServlet?id=1&dispatch=true&timeout=false

where, jsr315 is my context path, /AsyncServlet is the URL pattern for my servlet, and the dispatch and timeout query string parameters can be used to test out alternative behaviors.

That’s all folks!

Help is at hand for everyone who has ever cursed at having to add entries to their web.xml just because they wanted to use a third party framework.

With JSR 315, web.xml is no longer a single monolithic entity, but instead can be assembled from multiple pieces (called web fragments) into a single whole.

For instance, here’s a project I rolled earlier, that is packaged as jSwengsol.jar. This external JAR file would be deployed into your web application’s WEB-INF/lib folder, and as usual, is able to contribute web components (such as servlets, filters, or listeners). In my JAR, these components live within the com.swengsol package.

Note the presence of two special entries within this JAR file, the META-INF/web-fragment.xml file and the resources directory.

The web fragment entry allows an external JAR to package the configuration of its contained web components. This fragment will be merged into your own application’s web.xml when your application is deployed into the servlet container.

The optional resources folder can contain static resources (such as HTML, CSS, and JS files) as well as dynamic resources (JSPs). Resources provided within this folder are publicly available. Note that these resources live within your web application’s WEB-INF folder,  and yet are visible to the external world. This means that frameworks no longer have to implement workarounds (such as filters mapped to URL paths) to serve up resources that are required by that framework’s components.

Note that jSwengsol.jar is deployed into our main web application’s WEB-INF/lib.

This JAR file will now be described.

The IDEA configuration for generating the JAR file is as shown:

To build this artifact, I simply use Build > Build ‘jSwengsol’ artifact:

Squawker.java is a standard helper class that is used by our main web application. It is a very simple helper that takes a message and generates the HTML scaffolding around it. An important point of note is that it retrieves the stylesheet straight out of the web application’s WEB-INF/lib/jSwengsol.jar!resources/styles.css.

package com.swengsol;
/**
* User: Damodar Chetty
* Date: Jul 23, 2010
* Time: 8:13:26 AM
* An introduction to Servlet 3.0 and Java 6 (TC JUG)
* (c) Software Engineering Solutions, Inc.
*/
public class Squawker {
	private String title;
	private String body;
	public Squawker(String body) {
		this("Introducing Servlet 3.0", body);
	}
	public Squawker(String title, String body) {
		this.title = title;
		this.body = body;
	}
	public String getHTML() {
		String html = "<html><head>";
		if (null == title || title.length() ==0)
			title = "JSR315: Servlet 3.0";
		html += "<title>" + title + "</title>";
		html +=
		"<link rel=stylesheet type=\"text/css\"  href=\"styles.css\">";
		html += "</head> <body><p>" ;
		html += body;
		html += "</p>";
		html += "<p class=\"copyright\">Damodar Chetty,”;
		html += “ Software Engineering Solutions, Inc.</p>";
		html += "</body></html>";
		return html;
	}
}

The stylesheet, styles.css, is also a very straightforward affair:

.mainpara {
	font-size: 15pt;
	font-family:'trebuchet ms';
	padding:20;
	border-color:#736AFF;
	position:absolute;
	top:50;
	left: 200;
	border-style: dotted;
}
.copyright {
	width:375px;
	font-size:12pt;
	font-weight:bold;
	font-family:serif;
	background-color:black;
	color:white;
	position: absolute;
	top:300;
	left:500;
	padding:5;
}
body {background-color:#E0FFFF; color:#7F5217;}

In addition, you can also directly request the static resource, jSwengsol.html (listed below) as if it were directly within the root of our web application context, http://localhost:8008/jsr315/jSwengsol.html, where jsr315 is the context path for the web application that includes this JAR file.

<html>
<head>
<title>Introducing Servlet 3.0</title>
<link rel=stylesheet type="text/css"  href="styles.css">
</head>
<body>
<p>This is a static resource file served up from jSwengsol.jar</p>
<p>Damodar Chetty, Software Engineering Solutions, Inc.</p>
</body>
</html>

Likewise, you can access the JSP file as http://localhost:8008/jsr315/jSwengsol.jsp:

<%@ page import="java.util.Date" %>
<%--
  Created by IntelliJ IDEA.
  User: Monsty
  Date: Jul 22, 2010
  Time: 9:24:48 PM
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head><title>Introducing Servlet 3.0</title>
  <link rel=stylesheet type="text/css"  href="styles.css">
  </head>
  <body>
    <p class="mainpara">
      jSwengsol.jar!jSwengsol.jsp says the time is now <%=new Date()%>
   </p>
    <p class="copyright">
      Damodar Chetty, Software Engineering Solutions, Inc.
    </p>
  </body>
</html>

Now, let’s take a look at the web fragment, META-INF/web-fragment.xml:

<web-fragment>
  <name>jSwengsolFragment</name>
  <listener>
    <listener-class>com.swengsol.listeners.MyServletRequestListener</listener-class>
  </listener>
</web-fragment>

Firstly, note that a fragment can be named. This comes in handy when you are trying to specify ordering rules that define how multiple fragments can be combined into the application’s web.xml. Second, note that as its name suggests, this fragment is not a complete descriptor. Here it contains only the listener’s declaration within this fragment is automatically rolled into the main web application’s web.xml.

package com.swengsol.listeners;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.logging.Logger;

//1. No annotation - uses web-fragment.xml
public class MyServletRequestListener implements ServletRequestListener {
    private static final Logger logger = Logger.getLogger("com.swengsol");
    // Public constructor is required by servlet spec
    public MyServletRequestListener() {
    }

    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        logger.info("RequestListener > request destroyed - " + new Date());
    }

    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        HttpServletRequest req =
		(HttpServletRequest)servletRequestEvent.getServletRequest();
        String uri = req.getRequestURL().toString();
        logger.info("RequestListener > request initialized - " + uri + " - "
		 + new Date());
    }
}

There’s nothing noteworthy about this listener, except to point out that I specifically avoided using an annotation here to show how a web fragment functions.

To show how annotations could have been used instead, check out the JARServlet servlet:

package com.swengsol.servlets;

import com.swengsol.Squawker;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.logging.Logger;

/**
 * User: Damodar Chetty
 * Date: Jul 23, 2010
 * Time: 1:12:21 PM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */
@WebServlet("/JarServlet")
public class JARServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger("com.swengsol");

    protected void doPost(HttpServletRequest request,
			HttpServletResponse response)
        throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request,
			HttpServletResponse response)
        throws ServletException, IOException {
        logger.info("Within JARServlet request>>>" + new Date());

        Squawker squawker =
		new Squawker("Hello from jSwengsol.jar!JARServlet: " + new Date());
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println(squawker.getHTML());
    }
}

In this case, the servlet annotation is sufficient to register this servlet with the main web application, so no fragment entry is necessary.

That’s about it for now. As you can tell, there’s legs to this story – and I can imagine it being very useful as we head off into the future.

Whoa! I’ve just cracked the 600 ceiling on the Amazon ranks of reviewers.  Still a way to go – but I’m heading in the right direction it seems :)

http://www.amazon.com/gp/pdp/profile/A3FEGTOLCWXSV4/ref=cm_cr_thx_pdp

Powered by WordPress Web Design by SRS Solutions © 2012 Damodar's Musings Design by SRS Solutions