This laboratory exercise involves modifying your Hello World servletto make it keep count of the number of times it has been invoked.
Level of Difficulty: 2 (moderately easy)
Estimated time: 15 minutes
Pre-requisites:
The goal of this exercise is to create a servlet that maintains a counterof the number of times it has been invoked since it was last reloadedby the web server. It will use a class variable (i.e. static) tokeep count of the number of invocations. Each time the servlet isinvoked, it will print out the value of the counter.
There are 2 main ways to do this lab.
Begin by copying your Hello World servlet code, and putting it intoa file called CounterServlet.java
. You may keep it inthe same project (WAR file) as before, or put it in a separate WAR file (if youwould like more practice at the process of creating WAR files).
Make the following modifications to your Hello World servlet sourcecode:
You can cut and paste the HelloWorldServlet
from the src folder. Rename the class to CounterServlet
Declare a class variable to hold the value of your counter.
private static int numRequests = 0;
Declare a synchronized method to update the value of thenumRequests
variable.
private synchronized void incNumRequests() { numRequests++; }
Modify the code inside your existing doGet()
methodto make it call the incNumRequests
method you havejust created, and print out the current value of the counter.
incNumRequests(); out.println("Number of requests since reload: " + numRequests);
The question you should be asking yourself right now is: why do I need to create an extra method just to increment the valueof numRequests
? Why can't I just have my servlet increment the value directly?
The answer lies in the way servlets handle threading.By default, every servlet you create is multi-threaded.That means that at any given instant in time, multiple instancesof your doGet()
method could be executing simultaneously.
Also recall the meaning of a class variable (i.e. declared asstatic
) in Java. A static variable is one that is shared between all instances of a given class. So if you have10 instances of your CounterServlet
executing, all 10 instances will be sharing a single copy of the numRequests
variable.
What happens if two different instances of your servlet runningat the same time both try and update the value of numRequests
at the same time? In theory, this could lead to a semantic error inthe program because two threads are trying to update the same sharedresource simultaneously. [Although strictly speaking in this casethere is not much danger because all we are doing is incrementinga single value.]
The general principle that you should follow is that if you ever writea Java servlet where multiple threads will be accessing a single,non-shareable resource, you must programmatically ensure that atmost one thread can be accessing the resource at any one time.Java provides this facility through the use of itssynchronized
keyword.
If you have studied operating systems, note that this is similarin concept to monitors and semaphores used to ensure at most oneprocess is executing a critical section at any given time.
Follow the same steps you used when creating your Hello World servlet to edit and compile the code.
You now need to do some additional work..
Declare this servlet in your web.xml deployment descriptor. The following steps shows you how to do this via Eclipse/Workshop, but do note that it can be easier just to type the extra entries into the web.xml file directly! (see for the raw XML code to add)
Step 1: Right click on the Deployment Descriptor item. This should show you either the source or the design views. The main advantage of using the IDE is the guarantee of a correctly formatted xml file so let's select the design (also called Deployment Descriptor) tab.
Step 2: Right mouse click on the Servlets entry and select New Servlet
Step 3:
You now create the servlet. You enter the servlet name (Counter) and the name of the servlet class (CounterServlet).
Note that you can also use a JSP instead of a servlet class if you wish but we will wait till a later lab to try this out.
Step 4:
You now enter the servlet URL mapping. We will use /Counter to point to our servlet.
You can optionally add more mappings by using the Add button on the Servlet Properties page.
One neat trick is to map sub-contexts (which act like virtual subdirectories on the URL) and file names to a servlet directly.
For example, you could choose a mapping called /*.counter or index.html to map to CounterServlet!
<servlet> <servlet-name>Counter</servlet-name> <servlet-class>CounterServlet</servlet-class> </servlet>
and later in the file ...
<servlet-mapping> <servlet-name>Counter</servlet-name> <url-pattern>/Counter</url-pattern> </servlet-mapping>
Note that the ORDER of these XML entities are important in web.xml. Misplacing them may result in an error or your web application to fail to deploy.
Eclipse automatically re-deploys the updated lab so you can now unit-test the application. Note that each time you reload the browser with the refresh button, the displayed counter should update.
You should now redeploy your WAR file by using the Export .. as WAR file menu and by copying the war file to your WebLogic autodeploy
directory.
cp HelloWorldApp.war ~/weblogic/autodeploy
Test your new servlet, in your web browser, by viewing a URL likethe following (the filename on the end of the URL will dependupon the name you chose for the <url-pattern>