Javaserver Faces Introduction By Example Juneau Josh
Javaserver Faces Introduction By Example Juneau Josh
Javaserver Faces Introduction By Example Juneau Josh
Isharyanti-2025-Cross Language Communication in Indonesian LanguageNeny Isharyanti
Ad
Javaserver Faces Introduction By Example Juneau Josh
1. Javaserver Faces Introduction By Example Juneau
Josh download
https://ebookbell.com/product/javaserver-faces-introduction-by-
example-juneau-josh-11704300
Explore and download more ebooks at ebookbell.com
2. Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Javaserver Faces Introduction By Example 1st Edition Josh Juneau Auth
https://ebookbell.com/product/javaserver-faces-introduction-by-
example-1st-edition-josh-juneau-auth-4971844
Javaserver Faces Introduction By Example Josh Juneau
https://ebookbell.com/product/javaserver-faces-introduction-by-
example-josh-juneau-5052840
Javaserver Faces In Action 1st Edition Kito D Mann
https://ebookbell.com/product/javaserver-faces-in-action-1st-edition-
kito-d-mann-5470692
Javaserver Faces The Complete Reference Complete Reference Series 1st
Edition Chris Schalk
https://ebookbell.com/product/javaserver-faces-the-complete-reference-
complete-reference-series-1st-edition-chris-schalk-1877086
3. Javaserver Faces 1st Hans Bergsten
https://ebookbell.com/product/javaserver-faces-1st-hans-
bergsten-917936
Core Javaserver Faces 2nd Ed David M Geary Cay S Horstmann
https://ebookbell.com/product/core-javaserver-faces-2nd-ed-david-m-
geary-cay-s-horstmann-4099476
Mastering Javaserver Faces 22 Illustrated Leonard Anghel
https://ebookbell.com/product/mastering-javaserver-
faces-22-illustrated-leonard-anghel-55587594
Mastering Javaserver Faces Bill Dudney Jonathan Lehr Bill Willis
https://ebookbell.com/product/mastering-javaserver-faces-bill-dudney-
jonathan-lehr-bill-willis-975282
Core Javaserver Faces Cay S Horstmann
https://ebookbell.com/product/core-javaserver-faces-cay-s-
horstmann-976172
6. For your convenience Apress has placed some of the front
matter material after the index. Please use the Bookmarks
and Contents at a Glance links to access them.
7. v
Contents at a Glance
About the Author ..............................................................................................................xvii
Acknowledgments.............................................................................................................xix
Chapter 1: Introduction to Servlets
N ...................................................................................1
Chapter 2: JavaServer Pages
N ..........................................................................................55
Chapter 3: The Basics of JavaServer Faces
N ....................................................................99
Chapter 4: Facelets
N ........................................................................................................163
Chapter 5: JavaServer Faces Standard Components
N ....................................................205
Chapter 6: Advanced JavaServer Faces and Ajax
N .........................................................261
Index.................................................................................................................................325
8. 1
CHAPTER 1
Introduction to Servlets
Java servlets were the first technology for producing dynamic Java web applications. Sun Microsystems released the
first Java Servlet specification in 1997. Since then it has undergone tremendous change, making it more powerful
and easing development more with each release. The 3.0 version was released as part of Java EE 6 in December
2009. Although not always used directly by Java web developers, servlets are at the base of all Java EE applications.
Many developers use servlet frameworks such as Java Server Pages (JSP) and Java Server Faces (JSF), both of those
technologies compile pages into Java servlets behind the scenes via the servlet container. That said, a fundamental
knowledge of Java servlet technology is very useful for any Java web developer.
Servlets are Java classes that conform to the Java Servlet API, which allows a Java class to respond to requests.
Although servlets can respond to any type of request, they are most commonly written to respond to HTTP requests.
A servlet must be deployed to a Java servlet container in order to become usable. The Servlet API provides a number
of objects that are used to enable the functionality of a servlet within a web container. Such objects include the
request and response objects, pageContext, and a great deal of others, and when these objects are used properly, they
enable a Java servlet to perform just about any task a web-based application needs to perform.
As mentioned, servlets can produce not only static content but also dynamic content. Since a servlet is written in
Java, any valid Java code can be used within the body of the servlet class. This empowers Java servlets and allows them
to interact with other Java classes, the web container, the underlying file server, and much more.
This chapter will get you started developing and deploying servlets, and provide you with foundational
knowledge to move forward with other servlet-based web frameworks In this chapter, you will learn how to install
Oracle’s GlassFish application server, a robust servlet container, which will enable you to deploy sophisticated Java
enterprise applications. You will be taught the basics of developing servlets, how to use them with client web sessions,
and how to link a servlet to another application. All the while, you will learn to use standards from the latest release of
the Java Servlet API (3.2), which modernizes servlet development and makes it much easier and more productive than
in years past.
Note
N You can run the examples within this chapter by deploying the JSFByExample.war file (contained in the sources)
to a local Java EE application server container such as GlassFish v4.x. You can also set up the NetBeans 8.x project entitled
JSFByExample that is contained in the sources, build it, and deploy to GlassFish v4.x. Otherwise, you can run the examples
in Chapter 1 stand-alone using the instructions provided in the section “Packaging, Compiling, and Deploying a Servlet”.
If you deploy the JSFByExample.war file to a Java EE application server container, you can visit the following URL to load
the examples for this chapter: http://localhost:8080/JSFByExample/faces/chapter01/index.xhtml.
9. CHAPTER 1 N INTRODUCTION TO SERVLETS
2
Setting Up a Java Enterprise Environment
You’ll need an environment in which to experiment with servlets, and then later with JavaServer Faces. Oracle’s
GlassFish application server is a good choice, as it is the Java EE 7 Reference Impementation. It’s easy to set up, and
the following example will get you started and ready to run all the subsequent examples in the book.
Example
To get started, ownload and install Oracle’s GlassFish application server from the GlassFish web site. The version used
for this book is the open source edition, release 4.1, and it can be downloaded from http://glassfish.java.net/ in
the “Download” section. Select the .zip or .tar.gz download format, and decompress the downloaded files within a
directory on your workstation. I will refer to that directory as /JAVA_DEV/GlassFish. The GlassFish distribution comes
prepackaged with a domain so that developers can get up and running quickly. Once the .zip file has been unpacked,
you can start the domain by opening a command prompt or terminal and starting GlassFish using the following
statement:
/PATH_TO_GLASSFISH /GlassFish/bin/asadmin start-domain domain1
The domain will start, and it will be ready for use. You will see output from the server that looks similar to the
following:
Waiting for domain1 to start ............
Successfully started the domain : domain1
domain Location: /PATH_TO_GLASSFISH/glassfish/domains/domain1
Log File: /PATH_TO_GLASSFISH/glassfish/domains/domain1/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.
Explanation
The development of Java EE applications begins with a Java EE–compliant application server. A Java EE–compliant
server contains all the essential components to provide a robust environment for deploying and hosting enterprise
Java applications. The GlassFish application server is the industry standard for Java EE 7. As of GlassFish 4.0, there is
only an open sourced distribution of the server available, meaning that it is not possible to purchase Oracle support
for GlassFish. However, in a production environment, you may want to consider purchasing GlassFish 4.x support
from a third-party organization so that technical support will be available if needed. An alternative is to utilize a
commercially supported server that is Java EE 7 compliant, such as Oracle WebLogic 12.1.x.
Installing GlassFish is easy. It consists of downloading an archive and uncompressing it on your development
machine. Once you’ve completed this, the application server will make use of your locally installed Java development
kit (JDK) when it is started. JDK 8 is supported for use with GlassFish as of release 4.1. For GlassFish 4.0, please
use JDK 7. Once the server starts, you can open a browser and go to http://localhost:4848 to gain access to the
GlassFish administrative console. Most Java EE developers who deploy on GlassFish use the administrative console
often. The administrative console provides developers with the tools needed to deploy web applications, register
databases with Java Naming and Directory Interface (JNDI), set up security realms for a domain, and do much more.
You should take some time to become familiar with the administrative console because the more you know about it,
the easier it will be to maintain your Java EE environment.
Installing the GlassFish application server is the first step toward developing Java applications for the enterprise.
While other applications servers such as JBoss WildFly, Apache TomEE, and WebLogic are very well adopted,
GlassFish offers developers a solid environment that is suitable for production use and easy to learn. It also has the
bonus of being an open source application server and the reference implementation for Java EE 7.
10. CHAPTER 1 N INTRODUCTION TO SERVLETS
3
Developing Your First Servlet
Web applications are based upon a series of web views or pages. There is often a requirement to develop a view that
has the ability to include content that may change at any given time. For instance, you may be developing a view
that contains stock data, and you may wish to have that data updated often. Servlets provide the ability to produce
dynamic content, allowing server-side computations and processes to update the data in the servlet at will.
Example
Develop a Java servlet class, and compile it to run within a Java servlet container. In this example, a simple servlet
is created that will display some dynamic content to the web page. The The following code is the servlet code that
contains the functionality for the servlet:package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Simple Dynamic Servlet
* @author juneau
*/
public class SimpleServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
/*
* TODO output your page here. You may use following sample code.
*/
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet SimpleServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h2>Servlet SimpleServlet at " + request.getContextPath() + "</h2>");
out.println("<br/>Welcome to JavaServer Faces: Introduction By Example!");
11. CHAPTER 1 N INTRODUCTION TO SERVLETS
4
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the
left to edit the code.">
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
12. CHAPTER 1 N INTRODUCTION TO SERVLETS
5
The following code is the web deployment descriptor. This file is required for application deployment to a servlet
container. It contains the servlet configuration and mapping that maps the servlet to a URL. Later in this chapter,
will learn how to omit the servlet configuration and mapping from the web.xml file to make servlet development,
deployment, and maintenance easier.
<?xml version="1.0"?>
<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>SimpleServlet</servlet-name>
<servlet-class>org.javaeeexamples.chapter1.example01_02.SimpleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimpleServlet</servlet-name>
<url-pattern>/SimpleServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file> /SimpleServlet </welcome-file>
</welcome-file-list>
</web-app>
Note
N Many web applications use a page named index.html or index.xhtml as their welcome file. There is nothing
wrong with doing that, and as a matter of fact, it is the correct thing to do. The use of /SimpleServlet as the welcome
file in this example is to make it easier to follow for demonstration purposes.
To compile the Java servlet, use the javac command-line utility. The following line was excerpted from the
command line, and it compiles the SimpleServlet.java file into a class file. First, traverse into the directory
containing the SimpleServlet.java file; then, execute the following:
javac -cp /JAVA_DEV/GlassFish/glassfish/modules/javax.servlet-api.jar SimpleServlet.java
Once the servlet code has been compiled into a Java class file, it is ready to package for deployment.
Note
N You may want to consider installing a Java integrated development environment (IDE) to increase your develop-
ment productivity. There are several very good IDEs available to developers, so be sure to choose one that contains the
features you find most important and useful for development. As the author of this book on Java EE 7, I recommend
installing NetBeans 8.x or newer for development. NetBeans is an open source IDE that is maintained by Oracle, and it
includes support for all the cutting-edge features that the Java industry has to offer, including EJB development with Java
EE 7, JavaFX 8 support, and more.
13. CHAPTER 1 N INTRODUCTION TO SERVLETS
6
Explanation
Java servlets provide developers with the flexibility to design applications using a request-response programming
model. Servlets play a key role in the development of service-oriented and web application development on the
Java platform. Different types of servlets can be created, and each of them is geared toward providing different
functionality. The first type is the GenericServlet, which provides services and functionality. The second type,
HttpServlet, is a subclass of GenericServlet, and servlets of this type provide functionality and a response that uses
HTTP. The solution to this example demonstrates the latter type of servlet because it displays a result for the user to
see within a web browser.
Servlets conform to a life cycle for processing requests and posting results. First, the Java servlet container calls
the servlet’s constructor. The constructor of every servlet must take no arguments. Next, the container calls the servlet
init method, which is responsible for initializing the servlet. Once the servlet has been initialized, it is ready for use.
At that point, the servlet can begin processing. Each servlet contains a service method, which handles the requests
being made and dispatches them to the appropriate methods for request handling. Implementing the service
method is optional. Finally, the container calls the servlet’s destroy method, which takes care of finalizing the servlet
and taking it out of service.
Every servlet class must implement the javax.servlet.Servlet interface or extend another class that does.
In the solution to this example, the servlet named SimpleServlet extends the HttpServlet class, which provides
methods for handling HTTP processes. In this scenario, a browser client request is sent from the container to the
servlet; then the servlet service method dispatches the HttpServletRequest object to the appropriate method
provided by HttpServlet. Namely, the HttpServlet class provides the doGet, doPut, doPost, and doDelete
methods for working with an HTTP request. The HttpServlet class is abstract, so it must be subclassed, and then an
implementation can be provided for its methods. In the solution to this example, the doGet method is implemented,
and the responsibility of processing is passed to the processRequest method, which writes a response to the browser
using the PrintWriter. Table 1-1 describes each of the methods available to an HttpServlet.
Table 1-1. HttpServlet Methods
Method Name Description
doGet Used to process HTTP GET requests. Input sent to the servlet must be included in the URL
address. For example: ?myName=Josh&myBook=JSF.
doPost Used to process HTTP POST requests. Input can be sent to the servlet within HTML form
fields.
doPut Used to process HTTP PUT requests.
doDelete Used to process HTTP DELETE requests.
doHead Used to process HTTP HEAD requests.
doOptions Called by the container to allow OPTIONS request handling.
doTrace Called by the container to handle TRACE requests.
getLastModified Returns the time that the HttpServletRequest object was last modified.
init Initializes the servlet.
destroy Finalizes the servlet.
getServletInfo Provides information regarding the servlet.
14. CHAPTER 1 N INTRODUCTION TO SERVLETS
7
A servlet generally performs some processing within the implementation of its methods and then returns
a response to the client. The HttpServletRequest object can be used to process arguments that are sent via the
request. For instance, if an HTML form contains some input fields that are sent to the server, those fields would be
contained within the HttpServletRequest object. The HttpServletResponse object is used to send responses to
the client browser. Both the doGet and doPost methods within a servlet accept the same arguments, namely, the
HttpServletRequest and HttpServletResponse objects.
Note
N The doGet method is used to intercept HTTP GET requests, and doPost is used to intercept HTTP POST
requests. Generally, the doGet method is used to prepare a request before displaying for a client, and the doPost
method is used to process a request and gather information from an HTML form.
In the solution to this example, both the doGet and doPost methods pass the HttpServletRequest and
HttpServletResponse objects to the processRequest method for further processing. The HttpServletResponse
object is used to set the content type of the response and to obtain a handle on the PrintWriter object in the
processRequest method. The following lines of code show how this is done, assuming that the identifier referencing
the HttpServletResponse object is response:
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
A GenericServlet can be used for providing services to web applications. This type of servlet is oftentimes
used for logging events because it implements the log method. A GenericServlet implements both the Servlet and
ServletConfig interfaces, and to write a generic servlet, only the service method must be overridden.
How to Package, Compile, and Deploy a Servlet
Once a servlet has been developed (and compiled), it needs to be deployed to a servlet container before it can be
used. After deployment to the server, the servlet needs to be mapped to a URL for invocation.
Example
Compile the sources, set up a deployable application, and copy the contents into the GlassFish deployment directory.
From the command line, use the javac command to compile the sources.
javac -cp /PATH_TO_GLASSFISH/GlassFish/glassfish/modules/javax.servlet-api.jar SimpleServlet.java
After the class has been compiled, deploy it along with the web.xml deployment descriptor, conforming to the
appropriate directory structure. In web.xml, declare the servlet, and map it to a URL using the following format:
<servlet>
<servlet-name>SimpleServlet</servlet-name>
<servlet-class>org.javaserverfaces.chapter01.SimpleServlet</servlet-class>
</servlet>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SimpleServlet</servlet-name>
<url-pattern>/SimpleServlet</url-pattern>
</servlet-mapping>
15. CHAPTER 1 N INTRODUCTION TO SERVLETS
8
QUICK START FOR DEPLOYING WITHOUT AN IDE
To quickly get started with packaging, compiling, and deploying the example application for the servlet examples
in this chapter on GlassFish or other servlet containers such as Apache Tomcat without an IDE, follow these steps:
1. Create a single application named SimpleServlet by making a directory named
SimpleServlet.
2. Create a directory at the root of the application, and name it WEB-INF. Create an XML file in
the new WEB-INF directory, and name it web.xml. In the web.xml, add the following markup:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/
xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>SimpleServlet</servlet-name>
<servlet-class>org.javaserverfaces.chapter01.SimpleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimpleServlet</servlet-name>
<url-pattern>/SimpleServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
3. Create “classes”, and “lib” drectories inside the directory that was created in step 2. Drag
the Chapter 1 sources into the WEB-INF/classes directory.
4. Set your CLASSSPATH to include any necessary JAR files. For this chapter, the JavaMail
API JAR (mail.jar) is required. Place it into the WEB-INF/lib directory and set your
CLASSPATH accordingly.
5. At the command prompt, change directories so that you are within the “classes” directory
that was created in Step 3. Compile each class within the org.javaserverfaces.
chapter01 directory with the following command:
javac orgjavaserverfaceschapter01*.java
6. Copy your SimpleServlet application into the /JAVA_DEV/GlassFish/glassfish/domains/
domain1/autodeploy directory for GlassFish, or the /Tomcat/webapps directory for Tomcat.
Test the application by launching a browser and going to http://localhost:8080/SimpleServlet/servlet_
name, where servlet_name corresponds to the servlet name in each example. If using Tomcat, you may need to
restart the server in order for the application to deploy.
16. CHAPTER 1 N INTRODUCTION TO SERVLETS
9
Explanation
To compile the sources, you can use your favorite Java IDE such as NetBeans or Eclipse, or you can use the command
line. For the purposes of this example, I will use the command line. Note that in many of the remaining examples
for this book, the NetBeans IDE is used. If you’re using the command line, you must ensure you are using the javac
command that is associated with the same Java release that you will be using to run your servlet container. In this
example we will assume that GlassFish 4.1 is being used with JDK 7, and therefore assume that the location of the Java
SE 7 installation is at the following path:
/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home
This path may differ in your environment if you are using a different operating system and/or installation
location. To ensure you are using the Java runtime that is located at this path, set the JAVA_HOME environment variable
equal to this path. On OS X and *nix operating systems, you can set the environment variable by opening the terminal
and typing the following:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home
If you are using Windows, use the SET command within the command line to set up the JAVA_HOME environment
variable.
set JAVA_HOME=C:your-java-se-path
Next, compile your Java servlet sources, and be sure to include the javax.servlet-api.jar file that is packaged
with your servlet container (use servlet-api.jar for Tomcat) in your CLASSPATH. You can set the CLASSPATH by using
the –cp flag of the javac command. The following command should be executed at the command line from within the
same directory that contains the sources. In this case, the source file is named SimpleServlet.java.
javac -cp /path_to_jar/javax.servlet-api.jar SimpleServlet.java
Next, package your application by creating a directory and naming it after your application. In this case, create a
directory and name it SimpleServlet. Within that directory, create another directory named WEB-INF. Traverse into the
WEB-INF directory, and create another directory named classes. Lastly, create directories within the classes directory
in order to replicate your Java servlet package structure. For this example, the SimpleServlet.java class resides within
the Java package org.javaserverfaces.chapter01, so create a directory for each of those packages within the classes
directory. Create another directory within WEB-INF and name it lib; any JAR files containing external libraries should
be placed within the lib directory. In the end, your directory structure should resemble the following:
SimpleServlet
|_WEB-INF
|_classes
|_org
|_javaserverfaces
|_chapter01
|_lib
Place your web.xml deployment descriptor within the WEB-INF directory, and place the compiled
SimpleServlet.class file within the chapter01 directory. The entire contents of the SimpleServlet directory can
now be copied within the deployment directory for your application server container to deploy the application.
Restart the application server if using Tomcat, and visit the URL http://localhost:8080/SimpleServlet/
SimpleServlet to see the servlet in action.
17. CHAPTER 1 N INTRODUCTION TO SERVLETS
10
Registering Servlets Without WEB-XML
Registering servlets in the web.xml file is cumbersome. With the later releases of the Servlet specification, it is possible
to deploy servlets without the requirement for a web.xml file. In this section, we will take a look at how to register
servlets without the web.xml requirement.
Example
Use the @WebServlet annotation to register the servlet, and omit the web.xml registration. This will alleviate the
need to modify the web.xml file each time a servlet is added to your application. The following adaptation of the
SimpleServlet class that was used in the previous example includes the @WebServlet annotation and demonstrates
its use:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Registering Servlets without WEB-XML
* @author juneau
*/
@WebServlet(name = "SimpleServletNoDescriptor", urlPatterns = {"/SimpleServletNoDescriptor"})
public class SimpleServletNoDescriptor extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
/*
* TODO output your page here. You may use following sample code.
*/
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet SimpleServlet</title>");
18. CHAPTER 1 N INTRODUCTION TO SERVLETS
11
out.println("</head>");
out.println("<body>");
out.println("<h2>Servlet SimpleServlet at " + request.getContextPath() + "</h2>");
out.println("<br/>Look ma, no WEB-XML!");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
In the end, the servlet will be accessible via a URL in the same way that it would if the servlet were registered
within web.xml.
Explanation
There are a couple of ways to register servlets with a web container. The first way is to register them using the web.xml
deployment descriptor, as demonstrated earlier in the chapter. The second way to register them is to use the
@WebServlet annotation. The Servlet 3.0 API introduced the @WebServlet annotation, which provides an easier
technique to use for mapping a servlet to a URL. The @WebServlet annotation is placed before the declaration of a
class, and it accepts the elements listed in Table 1-2.
19. CHAPTER 1 N INTRODUCTION TO SERVLETS
12
In the solution to this example, the @WebServlet annotation maps the servlet class named
SimpleServletNoDescriptor to the URL pattern of /SimpleServletNoDescriptor, and it also names the servlet
SimpleServletNoDescriptor.
@WebServlet(name="SimpleServletNoDescriptor", urlPatterns={"/SimpleServletNoDescriptor"})
The new @WebServlet can be used rather than altering the web.xml file to register each servlet in an application.
This provides ease of development and manageability. However, in some cases, it may make sense to continue using
the deployment descriptor for servlet registration, such as if you do not want to recompile sources when a URL pattern
changes. If you look at the web.xml file used earlier, you can see the following lines of XML, which map the servlet to a
given URL and provide a name for the servlet. These lines of XML perform essentially the same function as the
@WebServlet annotation in this example.
<servlet>
<servlet-name>SimpleServletNoDescriptor</servlet-name>
<servlet-class>org.javaserverfaces.chapter01.SimpleServletNoDescriptor</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimpleServletNoDescriptor</servlet-name>
<url-pattern>/SimpleServletNoDescriptor</url-pattern>
</servlet-mapping>
Displaying Dynamic Content with a Servlet
As mentioned previously in the chapter, it sometimes makes sense to deliver dynamic content (content that changes
frequently), rather than serving static content that never changes. In this example, we will take a look at how to
develop a servlet that has the ability to display dynamic content.
Table 1-2. @WebServlet Annotation Elements
Element Description
description Description of the servlet
displayName The display name of the servlet
initParams Accepts list of @WebInitParam annotations
largeIcon The large icon of the servlet
loadOnStartup Load on start-up order of the servlet
name Servlet name
smallIcon The small icon of the servlet
urlPatterns URL patterns that invoke the servlet
20. CHAPTER 1 N INTRODUCTION TO SERVLETS
13
Example
Define a field within your servlet to contain the dynamic content that is to be displayed. Post the dynamic content on
the page by appending the field containing it using the PrintWriter println method. The following example servlet
declares a Date field and updates it with the current Date each time the page is loaded:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Displaying Dynamic Content with a Servlet
*
* @author juneau
*/
@WebServlet(name = "CurrentDateAndTime", urlPatterns = {"/CurrentDateAndTime"})
public class CurrentDateAndTime extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet CurrentDateAndTime</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet CurrentDateAndTime at " + request.getContextPath() + "</h1>");
out.println("<br/>");
Date currDateAndTime = new Date();
out.println("The current date and time is: " + currDateAndTime);
21. CHAPTER 1 N INTRODUCTION TO SERVLETS
14
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
The resulting output from this servlet will be the current date and time.
Explanation
One of the reasons why Java servlets are so useful is because they allow dynamic content to be displayed on a web
page. The content can be taken from the server itself, a database, another web site, or many other web-accessible
resources. Servlets are not static web pages; they are dynamic, and that is arguably their biggest strength.
In the solution to this example, a servlet is used to display the current time and date on the server. When the
servlet is processed, the doGet method is called, which subsequently makes a call to the processRequest method,
passing the request and response objects. Therefore, the processRequest method is where the bulk of the work
occurs. The processRequest method creates a PrintWriter by calling the response.getWriter method, and the
PrintWriter is used to display content on the resulting web page. Next, the current date and time are obtained
from the server by creating a new Date and assigning it to the currDateAndTime field. Lastly, the processRequest
method sends the web content through the out.println method, and the contents of the currDateAndTime field
are concatenated to a String and sent to out.println as well. Each time the servlet is processed, it will display the
current date and time at the time in which the servlet is invoked because a new Date is created with each request.
22. CHAPTER 1 N INTRODUCTION TO SERVLETS
15
This example just scratches the surface of what is possible with a Java servlet. Although displaying the current
date and time is trivial, you could alter that logic to display the contents of any field contained within the servlet.
Whether it be an int field that displays a calculation that was performed by the servlet container or a String field
containing some information, the possibilities are endless.
Handling Requests and Responses
Most applications allow forms that accept input, and then produce a response. This is one of the main components of
an HTTP application, and servlets are ideal for handling a request-response lifecycle. It can also be useful to develop
forms in HTML, and have the form submitted to a processing engine, such as a servlet.
Example
To see a request-response example in action, create a standard HTML-based web form, and when the submit
button is clicked, invoke a servlet to process the end-user input and post a response. To examine this technique,
you will see two different pieces of code. The following code is HTML that is used to generate the input form. Pay
particular attention to the <form> and <input> tags. You will see that the form’s action parameter lists a servlet name,
MathServlet.
<html>
<head>
<title>Simple Math Servlet</title>
</head>
<body>
<h1>This is a simple Math Servlet</h1>
<form method="POST" action="MathServlet">
<label for="numa">Enter Number A: </label>
<input type="text" id="numa" name="numa"/><br><br>
<label for="numb">Enter Number B: </label>
<input type="text" id="numb" name="numb"/><br/><br/>
<input type="submit" value="Submit Form"/>
<input type="reset" value="Reset Form"/>
</form>
</body>
</html>
Next, take a look at the following code for a servlet named MathServlet. This is the Java code that receives the
input from the HTML code listed earlier, processes it accordingly, and posts a response.
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
23. CHAPTER 1 N INTRODUCTION TO SERVLETS
16
/**
* Handling Requests and Responses
*/
// Uncomment the following line to run example stand-alone
//@WebServlet(name="SessionServlet", urlPatterns={"/MathServlet"})
// The following will allow the example to run within the context of the JSFByExample example
// enterprise application (JSFByExample.war distro or Netbeans Project)
@WebServlet(name = "MathServlet", urlPatterns = {"/chapter01/MathServlet"})
public class MathServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
res.setContentType("text/html");
// Store the input parameter values into Strings
String numA = req.getParameter("numa");
String numB = req.getParameter("numb");
PrintWriter out = res.getWriter();
out.println("<html><head>");
out.println("<title>Test Math Servlet</title>");
out.println("t<style>body { font-family: 'Lucida Grande', "
+ "'Lucida Sans Unicode';font-size: 13px; }</style>");
out.println("</head>");
out.println("<body>");
try {
int solution = Integer.valueOf(numA) + Integer.valueOf(numB);
/*
* Display some response to the user
*/
out.println("<p>Solution: "
+ numA + " + " + numB + " = " + solution + "</p>");
} catch (java.lang.NumberFormatException ex) {
// Display error if an exception is raised
out.println("<p>Please use numbers only...try again.</p>");
}
out.println("</body></html>");
out.close();
}
}
24. CHAPTER 1 N INTRODUCTION TO SERVLETS
17
Note
N To run the example, deploy the JSFByExample application to your application server container, and then
enter the following address into your browser: http://localhost:8080/JSFByExample/chapter01/math.html.
This assumes you are using default port numbers for your application server installation. If using the NetBeans project
that was packaged with the sources, you do not need to worry about copying the code as everything is pre-configured.
Explanation
Servlets make it easy to create web applications that adhere to a request and response life cycle. They have the
ability to provide HTTP responses and also process business logic within the same body of code. The ability to
process business logic makes servlets much more powerful than standard HTML code. The solution to this example
demonstrates a standard servlet structure for processing requests and sending responses. An HTML web form
contains parameters that are sent to a servlet. The servlet then processes those parameters in some fashion and
publishes a response that can be seen by the client. In the case of an HttpServlet object, the client is a web browser,
and the response is a web page.
Values can be obtained from an HTML form by using HTML <input> tags embedded within an HTML <form>.
In the solution to this example, two values are accepted as input, and they are referenced by their id attributes as
numa and numb. There are two more <input> tags within the form; one of them is used to submit the values to the form
action, and the other is used to reset the form fields to blank. The form action is the name of the servlet that the form
values will be passed to as parameters. In this case, the action is set to MathServlet. The <form> tag also accepts a
form-processing method, either GET or POST. In the example, the POST method is used because form data is being sent
to the action; in this case, data is being sent to MathServlet. You could, of course, create an HTML form as detailed
as you would like and then have that data sent to any servlet in the same manner. This example is relatively basic; it
serves to give you an understanding of how the processing is performed.
The <form> action attribute states that the MathServlet should be used to process the values that are contained
within the form. The MathServlet name is mapped back to the MathServlet class via the web.xml deployment
descriptor or the @WebServlet annotation. Looking at the MathServlet code, you can see that a doPost method is
implemented to handle the processing of the POST form values. The doPost method accepts HttpServletRequest
and HttpServletResponse objects as arguments. The values contained with the HTML form are embodied within the
HttpServletRequest object. To obtain those values, call the request object’s getParameter method, passing the id
of the input parameter you want to obtain. In this example, those values are obtained and stored within local String
fields.
String numA = req.getParameter("numa");
String numB = req.getParameter("numb");
Once the values are obtained, they can be processed as needed. In this case, those String values are converted
into int values, and then they are added together to generate a sum and stored into an int field. That field is then
presented as a response on a resulting web page.
int solution = Integer.valueOf(numA) + Integer.valueOf(numB);
As mentioned, the HTML form could be much more complex, containing any number of <input> fields.
Likewise, the servlet could perform more complex processing of those field values. This example is merely the tip
of the iceberg, and the possibilities are without bounds. Servlet-based web frameworks such as Java Server Pages
and Java Server Faces hide many of the complexities of passing form values to a servlet and processing a response.
However, the same basic framework is used behind the scenes.
25. CHAPTER 1 N INTRODUCTION TO SERVLETS
18
Listening for Servlet Container Events
There are cases when it may be useful for an application to perform some tasks when it is being started up or shut
down. In such cases, servlet context event listeners can become useful.
Example
Create a servlet context event listener to alert when the application has started up or when it has been shut down.
The following solution demonstrates the code for a context listener, which will log application start-up and shutdown
events and send e-mail alerting of such events:
package org.javaserverfaces.chapter01;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.annotation.WebListener;
@WebListener
public class StartupShutdownListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("Servlet startup...");
System.out.println(event.getServletContext().getServerInfo());
System.out.println(System.currentTimeMillis());
sendEmail("Servlet context has initialized");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Servlet shutdown...");
System.out.println(event.getServletContext().getServerInfo());
System.out.println(System.currentTimeMillis());
// See error in server.log file if mail is unsuccessful
sendEmail("Servlet context has been destroyed...");
}
/**
* This implementation uses the GMail smtp server
* @param message
* @return
*/
26. CHAPTER 1 N INTRODUCTION TO SERVLETS
19
private boolean sendEmail(String message) {
boolean result = false;
String smtpHost = "smtp.gmail.com";
String smtpUsername = "username";
String smtpPassword = "password";
String from = "fromaddress";
String to = "toaddress";
int smtpPort = 587;
System.out.println("sending email...");
try {
// Send email here
//Set the host smtp address
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
// create some properties and get the default Session
Session session = Session.getInstance(props);
// create a message
Message msg = new MimeMessage(session);
// set the from and to address
InternetAddress addressFrom = new InternetAddress(from);
msg.setFrom(addressFrom);
InternetAddress[] address = new InternetAddress[1];
address[0] = new InternetAddress(to);
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("Servlet container shutting down");
// Append Footer
msg.setContent(message, "text/plain");
Transport transport = session.getTransport("smtp");
transport.connect(smtpHost, smtpPort, smtpUsername, smtpPassword);
Transport.send(msg);
result = true;
} catch (javax.mail.MessagingException ex) {
ex.printStackTrace();
result = false;
}
return result;
}
}
Note
N To run this example, you may need additional external JARs in your CLASSPATH. Specifically, make sure you
have mail.jar and javaee.jar.
27. CHAPTER 1 N INTRODUCTION TO SERVLETS
20
Explanation
Sometimes it is useful to know when certain events occur within the application server container. This concept can be
useful under many different circumstances, but most often it would likely be used for initializing an application upon
start-up or cleaning up after an application upon shutdown. A servlet listener can be registered with an application
to indicate when it has been started up or shut down. Therefore, by listening for such events, the servlet has the
opportunity to perform some actions when they occur.
To create a listener that performs actions based upon a container event, you must develop a class
that implements the ServletContextListener interface. The methods that need to be implemented are
contextInitialized and contextDestroyed. Both of the methods accept a ServletContextEvent as an argument,
and they are automatically called each time the servlet container is initialized or shut down, respectively. To register
the listener with the container, you can use one of the following techniques:
Utilize the
u @WebListener annotation, as demonstrated by the solution to this example.
Register the listener within the
u web.xml application deployment descriptor.
Use the
u addListener methods defined on ServletContext.
For example, to register this listener within web.xml, you would need to add the following lines of XML:
<listener>
<listener-class> org.javaserverfaces.chapter01.StartupShutdownListener</listener-class>
</listener>
Neither way is better than the other. The only time that listener registration within the application deployment
descriptor (web.xml) would be more helpful is if you had the need to disable the listener in some cases. On the other
hand, to disable a listener when it is registered using @WebListener, you must remove the annotation and recompile
the code. Altering the web deployment descriptor does not require any code to be recompiled.
There are many different listener types, and the interface that the class implements is what determines the
listener type. For instance, in this example, the class implements the ServletContextListener interface. Doing so
creates a listener for servlet context events. If, however, the class implements HttpSessionListener, it would be a
listener for HTTP session events. The following is a complete listing of listener interfaces:
javax.servlet.ServletRequestListener
javax.servlet.ServletRequestAttrbiteListener
javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.HttpSessionListener
javax.servlet.HttpSessionAttributeListener
It is also possible to create a listener that implements multiple listener interfaces. To learn more about listening
for different situations such as attribute changes, please see the section entitled Listening for Attribute Changes.
Setting Initialization Parameters
It is possible to set initialization parameters for servlets as well. Doing so can be handy in cases where you would like
to implement a task with default values if none were given.
28. CHAPTER 1 N INTRODUCTION TO SERVLETS
21
Example #1
Set the servlet initialization parameters using the @WebInitParam annotation. The following code sets an initialization
parameter that is equal to a String value:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name="SimpleServletCtx1", urlPatterns={"/SimpleServletCtx1"},
initParams={ @WebInitParam(name="name", value="Duke") })
public class SimpleServletCtx1 extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
/* Display some response to the user */
out.println("<html><head>");
out.println("<title>Simple Servlet Context Example</title>");
out.println("t<style>body { font-family: 'Lucida Grande', " +
"'Lucida Sans Unicode';font-size: 13px; }</style>");
out.println("</head>");
out.println("<body>");
out.println("<p>This is a simple servlet to demonstrate context! Hello "
+ getServletConfig().getInitParameter("name") + "</p>");
out.println("</body></html>");
out.close();
}
}
To execute the example using the sources for this book, load the following URL into your web browser:
http://localhost:8080/JSFByExample/SimpleServletCtx1. The resulting web page will display the following text:
This is a simple servlet to demonstrate context! Hello Duke
29. CHAPTER 1 N INTRODUCTION TO SERVLETS
22
Example #2
Place the init parameters inside the web.xml deployment descriptor file. The following lines are excerpted from the
web.xml deployment descriptor for the SimpleServlet application. They include the initialization parameter names
and values.
<web-app>
<servlet>
<servlet-name>SimpleServletCtx1</servlet-name>
<servlet-class> org.javaserverfaces.chapter01.SimpleServletCtx1</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>Duke</param-value>
</init-param>
...
</servlet>
...
</web-app>
Explanation
Oftentimes there is a requirement to set initialization parameters for a servlet in order to initialize certain values.
Servlets can accept any number of initialization parameters, and there are a couple of ways in which they can be
set. The first example is to annotate the servlet class with the @WebInitParam annotation, and the second way to set
an initialization parameter is to declare the parameter within the web.xml deployment descriptor, as demonstrated
in the second example. Either way will work; however, the solution using @WebInitParam is based upon the newer
Java Servlet 3.0 API. Therefore, Example #1 is the more contemporary approach, but Example #2 remains valid for
following an older model or using an older Java servlet release.
To use the @WebInitParam annotation, it must be embedded within the @WebServlet annotation. Therefore, the
servlet must be registered with the web application via the @WebServlet annotation rather than within the web.xml
file. For more information on registering a servlet via the @WebServlet annotation, see the section entitled Registering
Servlets Without web.xml.
The @WebInitParam annotation accepts a name-value pair as an initialization parameter. In the solution to this
example, the parameter name is name, and the value is Duke.
@WebInitParam(name="name", value="Duke")
Once set, the parameter can be used within code by calling getServletConfig().getInitializationParameter()
and passing the name of the parameter, as shown in the following line of code:
out.println("<p>This is a simple servlet to demonstrate context! Hello "
+ getServletConfig().getInitParameter("name") + "</p>");
The annotations have the benefit of providing ease of development, and they also make it easier to maintain
servlets as a single package rather than jumping back and forth between the servlet and the deployment descriptor.
However, those benefits come at the cost of compilation because in order to change the value of an initialization
parameter using the @WebInitParam annotation, you must recompile the code. Such is not the case when using the
web.xml deployment descriptor. It is best to evaluate your application circumstances before committing to a standard
for naming initialization parameters.
30. CHAPTER 1 N INTRODUCTION TO SERVLETS
23
Filtering Web Requests
Another useful technique can be to apply a filter against a specified URL for a servlet. A filter can then invoke custom
processing each time the URL is visited, and the filter will be executed prior to the servlet.
Example
Create a servlet filter that will be processed when the specified URL format is used to access the application. In this
example, the filter will be executed when a URL conforming to the format of /* is used. This format pertains to any
URL in the application. Therefore, any page will cause the servlet to be invoked.
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.*;
/**
* This filter obtains the IP address of the remote host and logs
* it.
*
* @author juneau
*/
@WebFilter("/*")
public class LoggingFilter implements Filter {
private FilterConfig filterConf = null;
public void init(FilterConfig filterConf) {
this.filterConf = filterConf;
}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
String userAddy = request.getRemoteHost();
filterConf.getServletContext().log("Vistor User IP: " + userAddy);
chain.doFilter(request, response);
}
@Override
public void destroy() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
31. CHAPTER 1 N INTRODUCTION TO SERVLETS
24
The filter could contain any processing; the important thing to note is that this servlet is processed when a
specified URL is used to access the application.
Note
N To invoke the filter, load a URL for the application with which the filter is associated. For the purposes of this
example, load the following URL (for the previous example) to see the filter add text to the server log:
http://localhost:8080/JSFByExample/SimpleServletCtx1.
How It Works
Web filters are useful for preprocessing requests and invoking certain functionality when a given URL is visited.
Rather than invoking a servlet that exists at a given URL directly, any filter that contains the same URL pattern will be
invoked prior to the servlet. This can be helpful in many situations, perhaps the most useful for performing logging,
authentication, or other services that occur in the background without user interaction.
Filters must implement the javax.servlet.Filter interface. Methods contained within this interface include
init, destroy, and doFilter. The init and destroy methods are invoked by the container. The doFilter method
is used to implement tasks for the filter class. As you can see from this example, the filter class has access to the
ServletRequest and ServletResponse objects. This means the request can be captured, and information can be
obtained from it. This also means the request can be modified if need be. For example, including the user name in the
request after an authentication filter has been used.
If you want to chain filters or if more than one filter exists for a given URL pattern, they will be invoked in the
order in which they are configured in the web.xml deployment descriptor. It is best to manually configure the filters
if you are using more than one per URL pattern rather than using the @WebFilter annotation. To manually configure
the web.xml file to include a filter, use the <filter> and <filter-mapping> XML elements along with their associated
child element tags. The following excerpt from a web.xml configuration file shows how the filter that has been created
for this example may be manually configured within the web.xml file:
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LogingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Of course, the @WebFilter annotation takes care of the configuration for you, so in this case the manual
configuration is not required.
Note
N As of Servlet 3.1 API, if a filter invokes the next entity in the chain, each of the filter service methods must run
in the same thread as all filters that apply to the servlet.
32. CHAPTER 1 N INTRODUCTION TO SERVLETS
25
Listening for Attribute Changes
Servlets can perform listening event tasks when HTTP session attributes are changed by implementing the
HttpSessionAttributeListener interface.
Example
This example demonstrates how to generate an attribute listener servlet to listen for such events as attributes
being added, removed, or modified. The following class demonstrates this technique by implementing
HttpSessionAttributeListener and listening for attributes that are added, removed, or replaced within the HTTP
session:
package org.javaserverfaces.chapter01;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
* Attribute Listener
*/
@WebListener
public final class AttributeListener implements ServletContextListener,
HttpSessionAttributeListener {
private ServletContext context = null;
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
HttpSession session = se.getSession();
String id = session.getId();
String name = se.getName();
String value = (String) se.getValue();
String message = new StringBuffer("New attribute has been added to session: n").
append("Attribute Name: ").append(name).append("n").append("Attribute Value:").
append(value).toString();
log(message);
}
/**
*
* @param se
*/
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
HttpSession session = se.getSession();
String id = session.getId();
33. CHAPTER 1 N INTRODUCTION TO SERVLETS
26
String name = se.getName();
if (name == null) {
name = "Unknown";
}
String value = (String) se.getValue();
String message = new StringBuffer("Attribute has been removed: n")
.append("Attribute Name: ").append(name).append("n").append("Attribute Value:")
.append(value).toString();
log(message);
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
String name = se.getName();
if (name == null) {
name = "Unknown";
}
String value = (String) se.getValue();
String message = new StringBuffer("Attribute has been replaced: n ").append(name).
toString();
log(message);
}
private void log(String message) {
if (context != null) {
context.log("SessionListener: " + message);
} else {
System.out.println("SessionListener: " + message);
}
}
@Override
public void contextInitialized(ServletContextEvent event) {
this.context = event.getServletContext();
log("contextInitialized()");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
// Do something
}
}
Messages will be displayed within the server log file indicating when attributes have been added, removed, or
replaced.
34. CHAPTER 1 N INTRODUCTION TO SERVLETS
27
Explanation
In some situations, it can be useful to know when an attribute has been set or what an attribute value has been set
to. This example demonstrates how to create an attribute listener in order to determine this information. To create a
servlet listener, you must implement one or more of the servlet listener interfaces. To listen for HTTP session attribute
changes, implement HttpSessionAttributeListener. In doing so, the listener will implement the attributeAdded,
attributeRemoved, and attributeReplaced methods. Each of these methods accepts HttpSessionBindingEvent as
an argument, and their implementation defines what will occur when an HTTP session attribute is added, removed,
or changed, respectively.
In this example, you can see that each of the three methods listed in the previous paragraph contains a similar
implementation. Within each method, the HttpSessionBindingEvent is interrogated and broken down into String
values, which represent the ID, name, and value of the attribute that caused the listener to react. For instance,
in the attributeAdded method, the session is obtained from HttpSessionBindingEvent, and then the session
ID is retrieved from that via the use of getSession. The attribute information can be obtained directly from the
HttpSessionBindingEvent using the getId and getName methods, as shown in the following lines of code:
HttpSession session = se.getSession();
String id = session.getId();
String name = se.getName();
String value = (String) se.getValue();
After these values are obtained, the application can do whatever it needs to do with them. In this example, the
attribute ID, name, and session ID are simply logged and printed.
String message = new StringBuffer("New attribute has been added to session: n")
.append("Attribute Name: ").append(name).append("n")
.append("Attribute Value:").append(value).toString();
log(message);
The body of the attributeReplaced and attributeRemoved methods contain similar functionality. In the end,
the same routine is used within each to obtain the attribute name and value, and then something is done with those
values.
A few different options can be used to register the listener with the container. The @WebListener annotation is the
easiest way to do so, and the only downfall to using it is that you will need to recompile code in order to remove the
listener annotation if you ever need to do so. The listener can be registered within the web deployment descriptor, or
it can be registered using one of the addListener methods contained in ServletContext.
Although the example does not perform any life-changing events, it does demonstrate how to create and use an
attribute listener. In the real world, such a listener could become handy if an application needed to capture the user
name of everyone who logs in or needed to send an e-mail whenever a specified attribute is set.
Applying a Listener to a Session
In the same way that a listener can be applied to an HTTP session to listen for attribute changes, a listener can be
applied for performing tasks when sessions are created and destroyedAssume in the following example that you wish
to listen for sessions to be created so that you can count how many active sessions your application currently contains,
as well as perform some initialization for each session.
35. CHAPTER 1 N INTRODUCTION TO SERVLETS
28
Example
Create a session listener, and implement the sessionCreated and sessionDestroyed methods accordingly. In the
following example, a servlet is used to keep track of active sessions. Each time someone works with the application, a
counter has one added to it. Likewise, each time a person leaves the application, then the counter goes down by one.
package org.javaserverfaces.chapter01;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Applying a Session Listener
*
* @author juneau
*/
@WebListener
public class SessionListener implements HttpSessionListener {
private int numberOfSessions;
public SessionListener() {
numberOfSessions = 0;
}
public int getNumberOfSessions() {
return numberOfSessions;
}
@Override
public void sessionCreated(HttpSessionEvent arg) {
HttpSession session = arg.getSession();
session.setMaxInactiveInterval(60);
session.setAttribute("testAttr", "testVal");
synchronized (this) {
numberOfSessions++;
}
System.out.println("Session created, current count: " + numberOfSessions);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg) {
HttpSession session = arg.getSession();
synchronized (this) {
numberOfSessions--;
}
System.out.println("Session destroyed, current count: " + numberOfSessions);
System.out.println("The attribute value: " + session.getAttribute(("testAttr")));
}
}
36. CHAPTER 1 N INTRODUCTION TO SERVLETS
29
Each time a new visitor visits the application, a new session is started, and testAttr is set. When the session
times out, then it will be destroyed, and any attributes that have been set for the session will be removed.
Explanation
A meaningful way to track web application users is to place values in their HttpSession object. Using a Java servlet,
session attributes can be set, which will exist for the life of the HttpSession. Once the session is invalidated, the
attributes will be removed. To set up a session listener, create a Java servlet, annotate it with the @WebListener
annotation, and implement javax.servlet.http.HttpSessionListener. Doing so will force the implementation of
both the sessionCreated and sessionDestroyed methods, which is where the session magic occurs.
In this example, the sessionCreated method first obtains a handle on the current HttpSession object by calling
the HttpSessionEvent object’s getSession method. The handle is assigned to an HttpSession variable named
session. Now that you have that variable initialized with the session object, it can be used to set the time of life and
place attributes that will live and die with the session’s life. The first session configuration performed in the example
is to set the maximum inactive life to 60 (seconds), after which time the servlet container will invalidate the session.
Next an attribute named testAttr is set in the session and given a value of testVal.
HttpSession session = arg.getSession();
session.setMaxInactiveInterval(60);
session.setAttribute("testAttr", "testVal");
A field within the servlet named numberOfSessions is declared, and it is incremented each time a new session
is started. Following the session.setAttribute() call, the counter is incremented within a synchronized statement.
Finally, a message is printed to the server log indicating that a new session was created and providing the total active
session count.
Note
N Placing the increment within the synchronized statement helps avoid concurrency issues with the field.
For more information on Java synchronization and concurrency, please see the online documentation at
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html.
The sessionDestroyed method is called on a session once the maximum number of inactive seconds has passed.
In this example, the method will be called after 60 seconds of inactivity. Within the sessionDestroyed method,
another synchronization statement decrements the numberOfSessions field value by one, and then a couple of lines
are printed to the server log indicating that a session has been destroyed and providing the new total number of active
sessions.
Session listeners can be used to set cookies and perform other useful tactics to help manage a user’s experience.
They are easy to use and very powerful.
Managing Session Attributes
It is possible to maintain information throughout the life of an individual session. Servlets can make use of session
attributes to retain information on a per-session basis. That information can then be used at any time, so long as the
session remains available.
37. CHAPTER 1 N INTRODUCTION TO SERVLETS
30
Example
Make use of session attributes to retain session-based information. To do so, use the HttpServletRequest object
to obtain access to the session, and then use the getAttribute() and setAttribute() methods accordingly to set
information into the session. In the following scenario, an HTML page is used to capture a user’s e-mail address, and
then the e-mail address is placed into a session attribute. The attribute is then used by Java servlets across different
pages of the application in order to maintain state.
The following code demonstrates what the HTML form (chapter01/sessionAttributeDemo.html) may look like
in this scenario:
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Provide an email address to use with this transaction</h1>
<br/>
<form method="POST" action="SessionServlet">
<input type="text" id="email" name="email"/>
<br/>
<input type="submit" value="Submit"/>
</form>
</body>
</html>
Next, the Java servlet named SessionServlet using a URL pattern of /SessionServlet is initiated when the form
is submitted. Any form input values are passed to SessionServlet and processed accordingly.
package org.javaserverfaces.chapter01;
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
// Uncomment the following line to run example stand-alone
//@WebServlet(name="SessionServlet", urlPatterns={"/SessionServlet"})
// The following will allow the example to run within the context of the JSFByExample example
// enterprise application (JSFByExample.war distro or Netbeans Project)
@WebServlet(name="SessionServlet", urlPatterns={"/chapter01/SessionServlet"}) public class
SessionServlet extends HttpServlet {
public void doPost (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// Obtain he Session object
HttpSession session = req.getSession(true);
38. CHAPTER 1 N INTRODUCTION TO SERVLETS
31
// Set up a session attribute
String email = (String)
session.getAttribute ("session.email");
if (email == null) {
email = req.getParameter("email");
session.setAttribute ("session.email", email);
}
String sessionId = session.getId();
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<head><title>Working with sessions</title></head>");
out.println("<body>");
out.println("<h1>Session Test</h1>");
out.println ("Your email address is: " + email + "<br/><br/>");
out.println ("Your session id: " + sessionId);
out.println("</body></html>");
}
}
In the end, the e-mail address that was entered within the original HTML form was captured and used
throughout the different pages in the application.
How It Works
Since the beginning of web development, session attributes have been used to retain important information regarding
a user’s session. This concept holds true when developing using Java servlets as well, and servlets make it easy to
maintain attribute values. All HttpServlet classes must implement doGet or doPost methods in order to process web
application events. In doing so, these methods have access to the HttpServletRequest object as it is passed to them
as an argument. An HttpSession object can be gleaned from the HttpServletRequest, and therefore, it can be used to
retrieve and set attributes as needed.
In this example, an HTTP session attribute is used to store an e-mail address. That address is then used
throughout the application within different servlet classes by obtaining the session object and then retrieving the
attribute value.
// Obtain the Session object
HttpSession session = req.getSession(true);
// Set up a session attribute
String email = (String)
session.getAttribute ("session.email");
if (email == null) {
email = req.getParameter("email");
session.setAttribute ("session.email", email);
}
Any attributes will remain in the HttpSession object as long as the session remains valid. The session ID will
remain consistent when traversing between pages. You can see that the solution to this example obtains and prints the
current session ID for reference. Using attributes in the HttpSession is a good way to pass data around to maintain a
session’s state.
39. CHAPTER 1 N INTRODUCTION TO SERVLETS
32
Downloading a File Using a Servlet
Servlet applications have the ability to download a given file using a series of InputStreams and OutputStreams.
Example
Write a servlet that will accept the name and path of a chosen file and then read the file and stream it to the file
requestor. The following web page can be used to select a file for the servlet to download. Although the following
HTML (chapter01/download.html) contains a statically typed file name, it could very well contain a dynamic list of
files from a database or other source:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Click on the link below to download the file.</h1>
<br/>
<a href="DownloadServlet?filename=downloadTest.txt">Download test file</a>
<br/>
</body>
</html>
Note
N For the example, you can create and edit a file in your root directory next to the WEB-INF folder, and name the
file downloadTest.txt to see the servlet transfer the data to your browser client.
When a user clicks the link presented on the web page from the previous HTML, the following servlet will be used
to download the given file by passing the HttpServletRequest and HttpServletResponse objects to it along with the
file that should be downloaded:
package org.javaserverfaces.chapter01;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
40. CHAPTER 1 N INTRODUCTION TO SERVLETS
33
/**
*
* @author juneau
*/
// Uncomment the following line to run example stand-alone
//@WebServlet(name = "DownloadServlet", urlPatterns = {"/DownloadServlet"})
// The following will allow the example to run within the context of the JSFByExample
// enterprise application (JSFByExample.war distro or Netbeans Project)
@WebServlet(name = "DownloadServlet", urlPatterns = {"/chapter01/DownloadServlet"})
public class DownloadServlet extends HttpServlet {
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Read parameter from form that contains the filename to download
String fileToDownload = request.getParameter("filename");
// Call the download method with the given file
System.err.println("Downloading file now...");
doDownload(request, response, fileToDownload);
}
/**
* Sends a file to the output stream.
*
* @param req The request
* @param resp The response
* @param original_filename The name the browser should receive.
*/
private void doDownload( HttpServletRequest request, HttpServletResponse response,
String originalFile) throws IOException {
final int BYTES = 1024;
int length = 0;
ServletOutputStream outStream = response.getOutputStream();
ServletContext context = getServletConfig().getServletContext();
response.setContentType( (context.getMimeType( originalFile ) != null) ?
context.getMimeType( originalFile ) : "text/plain" );
response.setHeader( "Content-Disposition", "attachment; filename="" + originalFile + """ );
41. CHAPTER 1 N INTRODUCTION TO SERVLETS
34
InputStream in = context.getResourceAsStream("/" + originalFile);
byte[] bbuf = new byte[BYTES];
while ((in != null) && ((length = in.read(bbuf)) != -1))
{
outStream.write(bbuf,0,length);
}
outStream.flush();
outStream.close();
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}
}
The servlet will not produce a response; it will simply download the given file to the end user when the user clicks
the link to download the file.
Explanation
Downloading files is an essential task for almost any web application. Performing the steps that are provided by this
example will make it easy to achieve this task. This example demonstrates an easy case in which users can visit a web
page, click a file to download, and have the file retrieved from the server and copied to their machine. The HTML is
very simplistic in this example, and it lists a URL link that invokes the servlet and passes the name of the file that is to
be downloaded. When the user clicks the link, the name of the file is passed to /DownloadServlet as a parameter with
the name filename. When the link is clicked, the servlet doGet method is invoked. The first task that is performed in
the doGet method is to read the filename parameter from the invoking web page. That information is then passed to
the doDownload method along with the HttpServletRequest and HttpServletResponse objects.
In the doDownload method, the ServletOutputStream is obtained from the HttpServletResponse object, and
the ServletContext is obtained for later use. To download a file, the servlet must provide a response of the same
type that matches that of the file to be downloaded. It must also indicate in the response header that an attachment
is to be included. Therefore, the first tasks to be performed by the doDownload method involve setting up the
HttpServletResponse appropriately.
response.setContentType( (context.getMimeType( originalFile ) != null) ?
context.getMimeType( originalFile ) : "text/plain" );
response.setHeader( "Content-Disposition", "attachment; filename="" + originalFile + """ );
The file name, in this case originalFile, is used to obtain the MIME type of the file. If the MIME type of the file is
null, then text/plain will be returned. The attachment is set up in the response header as well, by appending the file
name as an attachment to the Content-Disposition. Next, the doDownload method obtains a reference to the file that
is to be downloaded by calling the ServletContext getResourceAsStream method and passing the name of the file.
This will return an InputStream object that can be used to read the contents of the indicated file. A byte buffer is then
42. CHAPTER 1 N INTRODUCTION TO SERVLETS
35
created, which will be used to obtain chunks of data from the file when it is being read. The final real task is to read the
file contents and copy them to the output stream. This is done using a while loop, which will continue to read from
the InputStream until everything has been processed. Chunks of data are read in and written to the output stream
using the loop.
while ((in != null) && ((length = in.read(bbuf)) != -1))
{
outStream.write(bbuf,0,length);
}
Lastly, the ServletOutputStream object’s flush method is called to clear the contents, and it is then closed
to release resources. The magic of downloading files using a Java servlet may be a bit obfuscated by this example,
however, because a static file is being used as the download source in this example. In real life, the HTML page would
probably contain a list of files that are contained within a database or on a file system, and then when the user selects
a file to download, the servlet will process that file accordingly, even extracting the file from the database if necessary.
Dispatching Requests
The concept of handing off tasks to other workers to perform action can be mirrored with real-world scenarios. If your
car stops functioning properly, you take it to a mechanic. Servlet processing can follow a similar technique by handing
off tasks to the appropriate worker servlets. This process is also known as dispatching. Furthermore, servlets have the
ability to hand off tasks without redirecting the client to another site, and therefore, the URL in the browser does not
change.
Example
To begin, create a request dispatcher servlet, which will decide which task needs to be completed and then send the
request to an appropriate servlet to achieve that task. The following example demonstrates this concept via an HTML
form that accepts two numbers from the user and allows the user to decide what type of mathematical evaluation
should be performed by the server. The servlet processes the request by first determining which type of mathematical
evaluation should be performed and then dispatching the request to the appropriate servlet to perform the task.
The following HTML form accepts two numbers from the user and allows them to choose which type of math to
perform against the numbers:<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Request Dispatch Example</h1>
<p>Perform a mathematical evaluation. Insert two numbers to be evaluated and then
choose the type of evaluation to perform.</p>
<form method="POST" action="MathDispatcher">
<label for="numa">Enter Number A: </label>
<input type="text" id="numa" name="numa"/><br><br>
<label for="numb">Enter Number B: </label>
<input type="text" id="numb" name="numb"/><br/><br/>
<select id="matheval" name="matheval">
<option value="add">Add the numbers</option>
<option value="subtract">Subtract the numbers</option>
43. CHAPTER 1 N INTRODUCTION TO SERVLETS
36
<option value="multiply">Multiply the numbers</option>
<option value="divide">Divide the numbers</option>
</select>
<input type="submit" value="Submit Form"/>
<input type="reset" value="Reset Form"/>
</form>
</body>
</html>
The next piece of code is the servlet that will dispatch requests accordingly depending upon the value of the
matheval field:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author juneau
*/
// Uncomment the following line to run example stand-alone
//@WebServlet(name = "MathDispatcher", urlPatterns = {"/MathDispatcher"})
// The following will allow the example to run within the context of the JSFByExample
// enterprise application (JSFByExample.war distro or Netbeans Project)
@WebServlet(name = "MathDispatcher", urlPatterns = {"/chapter01/MathDispatcher"})
public class MathDispatcher extends HttpServlet {
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("In the servlet...");
44. CHAPTER 1 N INTRODUCTION TO SERVLETS
37
// Store the input parameter values into Strings
String eval = request.getParameter("matheval");
ServletContext sc = getServletConfig().getServletContext();
RequestDispatcher rd = null;
int evaluate = 0;
int add = 0;
int subtract = 1;
int multiply = 2;
int divide = 3;
if(eval.equals("add"))
evaluate = add;
if (eval.equals("subtract"))
evaluate = subtract;
if (eval.equals("multiply"))
evaluate = multiply;
if(eval.equals("divide")){
evaluate = divide;
}
switch(evaluate){
case(0): rd = sc.getRequestDispatcher("/AddServlet");
rd.forward(request, response);
break;
case(1): rd = sc.getRequestDispatcher("/SubtractServlet");
rd.forward(request, response);
break;
case(2): rd = sc.getRequestDispatcher("/MultiplyServlet");
rd.forward(request, response);
break;
case(3): rd = sc.getRequestDispatcher("/DivideServlet");
rd.forward(request, response);
break;
}
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}
}
45. CHAPTER 1 N INTRODUCTION TO SERVLETS
38
Next is an example of one of the servlets that the request will be dispatched to. The following is the code for the
AddServlet, which will add the two numbers and return the sum to the user:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author juneau
*/
// Uncomment the following line to run example stand-alone
//@WebServlet(name = "AddServlet", urlPatterns = {"/AddServlet"})
// The following will allow the example to run within the context of the JSFByExample
// enterprise application (JSFByExample.war distro or Netbeans Project
@WebServlet(name = "AddServlet", urlPatterns = {"/chapter01/AddServlet"})
public class AddServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// Store the input parameter values into Strings
String numA = request.getParameter("numa");
String numB = request.getParameter("numb");
int sum = Integer.valueOf(numA) + Integer.valueOf(numB);
try {
out.println("<html>");
out.println("<head>");
out.println("<title>The Sum of the Numbers</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Sum: " + sum + "</h1>");
out.println("<br/>");
out.println("<a href=example01_14.html>Try Again</a>");
46. CHAPTER 1 N INTRODUCTION TO SERVLETS
39
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}
}
Each of the other servlets is very similar to AddServlet, except the mathematical evaluation is different. To see a
full listing of the code, please take a look at the sources for this book.
47. CHAPTER 1 N INTRODUCTION TO SERVLETS
40
Explanation
Sometimes it is a good idea to hide the forwarding of requests from the end user. Other times it just makes sense to
hand off a request from one servlet to another so that another type of processing can take place. These are just two
examples of when it is handy to perform a request dispatch within a servlet. Forwarding a request versus dispatching a
request is different because a forwarded request hands off the request on the client side, whereas a dispatched request
hands off the request on the server side. The difference can be quite large since the end user has no idea of server-side
dispatches, whereas the browser is redirected to a different URL when the request is forwarded on the client side.
Dispatching requests is an easy task. The facilities for doing so are built right into the ServletContext, so
once you obtain a reference to ServletContext, then you simply call the getRequestDispatcher method to obtain
a RequestDispatcher object that can be used to dispatch the request. When calling the getRequestDispatcher
method, pass a String containing the name of the servlet that you want to hand off the request to. You can actually
obtain a RequestDisptacher object for any valid HTTP resource within the application by passing the appropriate
URL for the resource in String format to the getRequestDispatcher method. Therefore, if you’d rather dispatch to a
JSP or HTML page, you can do that as well. After a RequestDispatcher object has been obtained, invoke its forward
method by passing the HttpServletRequest and HttpServletResponse objects to it. The forward method performs
the task of handing off the request.
rd = sc.getRequestDispatcher("/AddServlet");
rd.forward(request, response);
In the case of this example, you can dispatch requests to different servlets in order to perform a specific task.
Once handed off, the servlet that has obtained the request is responsible for providing the response to the client. In
this case, the servlet returns the result of the specified mathematical evaluation.
Redirecting to Another Application or Site
In certain situations, it can be useful to redirect from a servlet to a different application on the same server or a
different site altogether.
Example
Use the HttpServletResponse object’s sendRedirect() method to redirect from the servlet to another URL. In the
following example, when a URL that matches the /redirect pattern is used, then the servlet will redirect the browser
to another site:
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name="RedirectServlet", urlPatterns={"/redirect"})
public class RedirectServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
48. CHAPTER 1 N INTRODUCTION TO SERVLETS
41
throws IOException, ServletException {
String site = "http://www.apress.com";
res.sendRedirect(site);
}
}
In this example, the servlet will redirect to the www.apress.com web site.
Explanation
There are some cases in which a web application needs to redirect traffic to another site or URL within the same
or another application. For such cases, the HttpServletResponse sendRedirect method can be of use. The
sendRedirect method accepts a URL in String format and then redirects the web browser to the given URL. Given
that sendRedirect accepts a String-based URL makes it easy to build dynamic URLs as well. For instance, some
applications may redirect to a different URL based upon certain parameters that are passed from a user. Dynamic
generation of a URL in such cases may look something like the following:
String redirectUrl = null;
If(parameter.equals("SOME STRING")
redirectUrl = "/" + urlPathA;
else
redirectUrl = "/" + urlPathB;
res.sendRedirect(redirectUrl);
The sendRedirect() method can also come in handy for creating the control for web menus and other page
items that can send web traffic to different locations.
Note
N This simple redirect, as opposed to servlet chaining, does not pass the HttpRequest object along to the
target address.
Utilizing Cookies Within the Browser Securely
If an application must maintain state, it should be maintained in a secure manner. Cookies are oftentimes used to
pass data around as a means of maintaining state. Servlets can safeguard cookies by marking them as HTTP only.
49. CHAPTER 1 N INTRODUCTION TO SERVLETS
42
Example
Use “HTTP only” browser cookies to save the state. In the following example, one servlet is used to place some session
information into a cookie in the browser. Another servlet is then called, which reads the cookie information and
displays it to the user. The following servlet demonstrates how to store a cookie in the browser using a Java servlet:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Securing State within the Browser
* @author juneau
*/
@WebServlet(name = "SetCookieServlet", urlPatterns = {"/SetCookieServlet"})
public class SetCookieServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Cookie cookie = new Cookie("sessionId","12345");
cookie.setHttpOnly(true);
cookie.setMaxAge(-30);
response.addCookie(cookie);
try {
out.println("<html>");
out.println("<head>");
out.println("<title>SetCookieServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet SetCookieServlet is setting a cookie into the browser</h1>");
out.println("<br/><br/>");
out.println("<a href='DisplayCookieServlet'>Display the cookie contents.</a>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
50. CHAPTER 1 N INTRODUCTION TO SERVLETS
43
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
The next code listing demonstrates a servlet that reads the cookies in the browser and prints out the contents:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Securely Maintaining State within the Browser
* @author juneau
*/
@WebServlet(name = "DisplayCookieServlet", urlPatterns = {"/DisplayCookieServlet"})
public class DisplayCookieServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
try {
out.println("<html>");
out.println("<head>");
out.println("<title>Display Cookies</title>");
out.println("</head>");
out.println("<body>");
for(Cookie cookie:cookies){
out.println("<p>");
out.println("Cookie Name: " + cookie.getName());
out.println("<br/>");
out.println("Value: " + cookie.getValue());
out.println("</p>");
}
51. CHAPTER 1 N INTRODUCTION TO SERVLETS
44
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
Explanation
Using cookies to store data within the browser is a technique that has been in practice for years. Since Servlet 3.0 API,
the ability to mark a cookie as HTTP only has become available. This allows the cookie to be safeguarded against
client-side scripting attacks, making the cookie more secure. Any standard servlet can create a cookie and place it
into the current session. Similarly, any servlet that is contained within the same session can read or update a session’s
cookies values. In this example, two servlets are used to demonstrate how cookies work. The first servlet that is listed
is responsible for creating a new cookie and setting it into the browser session. The second servlet is responsible for
displaying the contents of the cookie to the user.
To create a cookie, simply instantiate a new javax.servlet.http.Cookie object and assign a name and value
to it. Passing both the name and value into the Cookie constructor at the time of instantiation can assign a name and
value, or it can be done by passing values to the cookie’s setName and setValue methods. Once the cookie has been
instantiated, properties can be set that will help to configure the cookie. In this example, the cookie’s setMaxAge and
setHttpOnly methods are called, setting the time of life for the cookie and ensuring that it will be guarded against
client-side scripting. For a complete listing of cookie properties, please refer to Table 1-3. Finally, the cookie is placed
into the response by passing it to the response object’s addCookie method.
Cookie cookie = new Cookie("sessionId","12345");
cookie.setHttpOnly(true);
cookie.setMaxAge(-30);
response.addCookie(cookie);
52. CHAPTER 1 N INTRODUCTION TO SERVLETS
45
The second servlet, DisplayCookieServlet, is responsible for reading and displaying the session’s cookies
values. When DisplayCookieServlet is invoked, its processRequest method is called, which obtains the cookies
within the response object by calling response.getCookies() and setting the result to an array of Cookie objects.
Cookie[] cookies = request.getCookies();
The cookie object array can now be iterated over in order to obtain each cookie and print out its contents. The
servlet does so by using a for loop and printing out each cookie’s name and value.
for(Cookie cookie:cookies){
out.println("<p>");
out.println("Cookie Name: " + cookie.getName());
out.println("<br/>");
out.println("Value: " + cookie.getValue());
out.println("</p>");
}
Finalizing Servlet Tasks
It is easy to perform cleanup tasks within the context of a servlet.
Example
To cleanup or perform finalization within a servlet, first provide code for performing any cleanup within the servlet
destroy method. Second, in the case that there are potentially long-running methods, code them so that you will
become aware of a shutdown and, if necessary, halt and return so that the servlet can shut down cleanly. The
following code excerpt is a small example of a destroy method. In this code, it is being used to initialize local variables
and is setting the beingDestroyed boolean value to indicate that the servlet is shutting down.
Table 1-3. Cookie Property Methods
Property Description
setComment Sets a comment to describe the cookie.
setDomain Specifies the domain in which the cookie belongs.
setHttpOnly Marks the cookie as HTTP only.
setMaxAge Sets the maximum lifetime of the cookie. A negative value indicates that the cookie will expire
when the session ends.
setPath Specifies a path for the cookie to which the client should return it.
setSecure Indicates that the cookie should be sent only using a secure protocol.
setValue Assigns a value to the cookie.
setVersion Specifies the version of the cookie protocol that the cookie will comply with.
53. CHAPTER 1 N INTRODUCTION TO SERVLETS
46
...
/**
* Used to finalize the servlet
*/
public void destroy() {
// Tell the servlet it is shutting down
setBeingDestroyed(true);
// Perform any cleanup
thisString = null;
}
...
The code within the destroy method may successfully achieve a full cleanup of the servlet, but in the case where
there may be a long-running task, then it must be notified of a shutdown. The following excerpt is a block of code that
signifies a long-running task. The task should stop processing once the shutdown is indicated by the beingDestroyed
value becoming true.
for (int x = 0; (x <= 100000 && !isBeingDestroyed()); x++) {
doSomething();
}
Explanation
The finalization of a servlet can be very important, especially if the servlet is using some resources that may lead to a
memory leak, making use of a reusable resource such as a database connection or in order to persist some values for
another session. In such cases, it is a good idea to perform cleanup within the servlet destroy method. Every servlet
contains a destroy method (which may be implemented to overload default behavior) that is initiated once the
servlet container determines that a servlet should be taken out of service.
The destroy method is called once all of a servlet’s service methods have stopped running. However, if there is a
long-running service method, then a server grace period can be set that would cause any running service to be shut
down when the grace period is reached. As mentioned earlier, the destroy method is the perfect place to clean up
resources. However, the destroy method is also a good place to help clean up after long-running services. Cleanup
can be done by setting a servlet-specific local variable to indicate that the servlet is being destroyed and by having the
long-running service check the state of that variable periodically. If the variable indicates that the destroy method
has been called, then it should stop executing.
Reading and Writing with Nonblocking I/O
First generation web applications oftentimes were plagued with the user clicking a button to submit a request to
perform a read or write operation, and then waiting for a period of time so that the task could complete. Sometimes
this was a momentary wait, and other timesit was a longer wait. Modern implementations of the Servlet API make it
possible to perform asynchronous I/O, helping to alleviate this issue.
Example
Use the Non-Blocking I/O API that is part of the Servlet 3.1 release to create an asynchronous solution. To use the
new technology, implement the new ReadListener interface when performing nonblocking reads, and implement
the WriteListener interface for performing nonblocking writes. The implementation class can then be registered to
a ServletInputStream or ServletOutputStream so that reads or writes can be performed when the listener finds that
servlet content can be read or written without blocking.
54. CHAPTER 1 N INTRODUCTION TO SERVLETS
47
The following sources are those of a ReadListener implementation that reside in the source file
org.javaserverfaces.chapter01.AcmeReadListenerImpl.java, and they demonstrate how to implement the
ReadListener:
package org.javaserverfaces.chapter01;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
public class AcmeReadListenerImpl implements ReadListener {
private ServletInputStream is = null;
private AsyncContext async = null;
public AcmeReadListenerImpl(ServletInputStream in, AsyncContext ac) {
this.is = in;
this.async = ac;
System.out.println("read listener initialized");
}
@Override
public void onDataAvailable() {
System.out.println("onDataAvailable");
try {
StringBuilder sb = new StringBuilder();
int len = -1;
byte b[] = new byte[1024];
while (is.isReady()
&& (len = is.read(b)) != -1) {
String data = new String(b, 0, len);
System.out.println(data);
}
} catch (IOException ex) {
Logger.getLogger(AcmeReadListenerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void onAllDataRead() {
System.out.println("onAllDataRead");
async.complete();
}
56. WHAT HAPPENED AT MOOSE FACTORY
DURING SUMMER AND FALL, 1920
Extracts from the Post Journal from Entries by J. L. Gaudet, Post Manager
July 1st—Our steamer, the "Inenew," left this morning on her first trip to Charlton
Island, taking the District staff to the island for the summer, as this is our summer
distributing point. Dr. Stewart and Rev. W. G. Walton were passengers.
July 6th—The steamer returned with a cargo for Moose Factory of Charlton Depot
stock. The steamer returned to Charlton with a load of lumber which I am shipping
to the Straits.
July 14th—The steamer returned with her second cargo from Charlton, and took
another load of lumber for the Strait Posts. Mr. Johansen of the Biological Branch of
the Naval Department of the Canadian Government, was a passenger on his way to
Fort George. Mr. Fred McLeod and family were also passengers on their way to
Woswonaby Post. Mr. McLeod is going there in the capacity of Post Manager.
July 21st—Mr. F. D. Wilson arrived here to-day with two apprentice clerks, Messrs.
Beveridge and Findlay, both from Aberdeen, Scotland.
Aug. 3rd—Mr. Aurey, the government treaty paymaster, arrived here on his annual
trip, paying treaty to the Indians. Mr. Aurey is assisted by Dr. Baker.
Aug. 10th—Mr. Russell and family, Mr. John Louttit and family, arrived with the
schooner "Fort George." These gentlemen are on their way out to civilization. Mr.
Russell was in charge of Fort George Post.
Aug. 14th—Mr. Romanet, general fur trade inspector, arrived here with Mrs. Romanet
and two children. Mr. Romanet says he is here on an official visit from the Fur Trade
Commissioner's Office. Inspector Phillips and Sgt. Joy, of the R.C.M. Police, also
arrived to-day. They are on their way to the Belcher Islands to investigate some
Eskimo murder case.
Aug. 17th—A large seaplane, "The Caaz," with Capt. Maxwell as pilot and Mr. Doan
as engineer, landed here this afternoon. This is the first flying machine to come to
Moose Factory and was quite a sight for our Indians.
Aug. 19th—The general inspector left on the schooner "Fort George" for Charlton
Island this morning at 7 o'clock. A canoe carrying the ship's papers and two
apprentice clerks, Mr. Gregory and Mr. Bremner, arrived at 1 p.m., just a few hours
late to catch the schooner which I was holding for that purpose, so I had to get busy
and send off our hay-boat with this mail to Charlton Island.
Aug. 23rd—The seaplane landed here to-day on her second trip from Remy Lake,
which is a few miles from Cochrane, with two moving picture men, Mr. Blake and Mr.
57. Tash. They claim that they are being sent by the Ontario Government to take
pictures.
Aug. 26th—We had a visit from Capt. Mack to-day. He came with our schooner "Fort
Charles" from Charlton Island, and states that they had a hard and trying trip coming
through the Straits. Mr. and Mrs. Mayer were also passengers. Mr. Mayer is our
worthy Post Manager at Great Whale River and is on his way out to civilization on a
few months' leave.
Aug. 27th—The seaplane "Caaz" brought us some newspapers from Cochrane, dated
Aug. 25th, with the latest news.
Aug. 31st—We have at last managed to extinguish the bush fire which was started
by the Rev. Mr. Haythornthwaite on the 25th inst., after working day and night since
it started. This will be quite a relief to the many families who are still camped across
the river, as they were afraid to come back.
Sept. 2nd—Our steamer "Inenew" landed here to-day with our District Manager, Mr.
Rackham, Mr. Romanet, the general inspector, Mr. Griffith, manager of Albany Post,
who is acting as private secretary to the general inspector, Messrs. Blake and Tash,
movie men, and the Rev. Mr. Walton were passengers. The seaplane "Caaz" also
arrived from Remy Lake with Mr. Griffin, representing the Toronto Star, as passenger.
Sept. 21st—Mr. A. Nicolson and family arrived this evening from Rupert's House,
after a hard and trying trip around the coast. Mr. Nicolson has been in the employ of
the Hudson's Bay Company for forty years. It is with much regret that we see Mr.
Nicolson severing his active services with the good old Company.
Sept. 23rd—Mr. and Mrs. J. W. Anderson and child landed here to-day after spending
a few months' holiday in civilization. Mr. Anderson is on his way to his Post, which is
Attawapiskat.
Oct. 1st—The steamer "Inenew" landed here to-day with the District Office staff and
the balance of our outfit. This finishes our season's transport.
Oct. 7th—Capt. G. R. Redfearn, A. Guibeau, engineer, Inspector Phillips, Sgt. Joy, Mr.
Johansen and Mr. Sainsbury left this morning for Clute.
Oct. 9th—Hauled out the S.S. "Inenew" to winter quarters and stored away the
hauling gear.
Oct. 27th—Packet canoes returned from the line to-day and by them received the
first issue of our magazine, The Beaver.
Oct. 29th—Mr. G. R. Ray, fur trade inspector, and Mr. J. B. Neil arrived here to-day at
mid day.
Nov. 10th—The river is frozen over, and hardly any snow on the ground as yet. We
are having fine weather.—J. L. Gaudet, Post Manager.
58. The Ghost is Foiled in Lac Seul's Haunted Room
By R. O. OTTEN
It was Christmas at Lac Seul Post, that historic place, well known to men of the North.
Quite a number of the Outpost managers had come in to spend Christmas with the Post
Manager and his family. The last to arrive was Mr. R. He had travelled over 200 miles by
dog team and cariole to get there. After the hand-shaking was over, Mr. M., the Post
Manager, drew Mr. R. aside and asked if he believed in ghosts. Mr. R. laughed and said he
didn't believe in any kind of spirits, except the kind they used to have at Christmas in the
old days, but wanted to know what the joke was. The Post Manager told him that he had
only one room left vacant, and nobody had slept in that room for years as it was
supposed to be haunted.
The story was that on two different occasions at the usual Christmas gathering of the
Outpost managers, there had been tragic endings to several guests who had occupied
that room. Both had died from having their throats cut from ear to ear—and no one had
slept there since. Mr. R. said he didn't believe in such nonsense as ghosts, and wanted to
be shown to the room, as he wanted to get a shave and clean-up before dinner. He said
any kind of a room would look good to him after sleeping in the snow for the past week.
The Post Manager showed him to the room which was situated at the rear of the large
dwelling house, away from the rest of the guests. Mr. R. had just laid out his "glad rags"
and was commencing to shave—he had the razor in his hand—when a feeling came over
him that he was not alone in the room. Looking into the mirror, he was horrified to see
there the reflection of a horrible face peering over his shoulder. He felt his wrist grasped
by a claw-like hand. His hand was being forced slowly up and up, towards his throat. Mr.
R. tried to call out for help, but he was powerless to utter a sound. The hand was still
forcing the razor towards his victim's throat, then it started to draw it across. Mr. R. gave
himself up for lost, when he felt the grip on his wrist loosen and a baffled expression
came over the horrible face. That ghost was up against modern science. Mr. R. was using
a safety razor.
59. SASKATCHEWAN DISTRICT OFFICE NEWS
Congratulations would appear to be in order for Mr. and Mrs. Armstrong, of Fort a la
Corne Post, and their daughter Norah on the success attained by the latter at the recent
St. Alban's College (Prince Albert) term examinations. The following is a quotation from
the local paper:
"Miss Norah Armstrong, the gold medalist of the year at St. Alban's college, Prince
Albert, holds an enviable record in the college. Miss Armstrong has been a student at
St. Alban's for the past four years, taking her grade 8 diploma in 1917. She was
successful in passing her junior matriculation examination in June, and now holds
the St. Alban's scholarship to the University of Saskatchewan. In addition to her
marked progress in her studies, Miss Armstrong has found time to distinguish herself
along athletic lines, having won the tennis cup in singles, and also with Miss Phyllis
Clarke in the doubles."
60. "SKIPPERING A SCOW" ON THE ATHABASCA
(Continued from last number)
By N. A. Howland
When the men in the scow realized their position they did not shout frenziedly for help.
To them the most important business of the moment was to get a smoke.
They Smoked While Facing Death
The frenzied people were all on shore. Under the calming influence of tobacco, the
wrecked crew surveyed the damage. The boat was intact though leaking a little. It was
impossible for them to extricate themselves. Even if any of them could swim, an attempt
to make the shore would have proved fatal. They relied on us. Their hope was founded
on a rock as surely as their craft.
Getting Ready for the Rescue
It was not long ere some of the sixty odd men, at Mr. Cornwall's direction, on the island
had run to the warehouse to get rope. Fortunately being on the scene, he took matters in
hand, and as soon as the necessary tackle had been brought, essayed to rescue the
endangered crew. The only way that this could be done was to get a line aboard the
scow and pull her off. The distance from shore was too great to permit of a rope being
thrown, but there was a rock standing well out of the water about half way between,
from which it might be possible to hurl a stick; so Cornwall, taking a club in his hand to
which was attached a long cord held by the men on shore, started to work his way out to
the vantage point through the rock-studded stream, struggling from boulder to boulder,
the swirling water gripping and tearing at his legs in an effort to sweep him away.
Fighting the Torrent
61. To the tense crowd of men watching it seemed impossible that he could attain his object,
but in spite of the great physical strain slowly and surely the figure—now waist deep in
the current, now pulling himself up on to a rock, clinging always to the meagre support
with a tenacity that the raging torrent could not break—reached its goal.
Getting A Line Aboard the Wreck
A sense of relief came to those who watched, but not for long. He rested for a moment
to recover his breath; then coolly gathering the small rope into a coil he made the first
throw. A gasp went up from the crowd on shore. The distance was too great; the stick hit
the water fully twenty feet short. Again and again the attempt failed. Sometimes the
missile fell so close that the rope could almost be reached but they had no boat-hook
aboard. The thrower could not stand up with good footing to do his work, but from a
precarious position threw with arms alone. He rested, tired by his exertions. Suddenly he
gathered all his strength and at imminent hazard of hurling himself into the river sent the
stick with unerring aim over its mark.
We Pulled the Scow Off the Rock
A mighty cheer went up from all the watchers. It was but a moment's work to haul in the
cable and make it fast to the end of the scow; every available man on shore found a
place on the line, and pulled with might and main to the cry of "Yo heave ho!" that she
creaked in every seam and her square end was drawn bow-shaped under the strain on
that fragile rope. Pull as we might, our efforts to dislodge her were unavailing. Something
had to give, however. It was the line which parted with a snap, hurling us to the ground.
A groan went up from those in danger, for in a moment they fell from the highest hope to
the lowest depth of despair. They were in worse plight than before, but steadfastly the
business of renewing communication with the scow proceeded without delay. Cornwall's
efforts were again crowned with success. Little by little our task was accomplished and
we were gratified to see the men who were in the water scramble aboard in great haste,
as with a rousing cheer we let go the cable.
A Tenderfoot Spectator
When we had first arrived at the head of the rapids the previous day, a little man with a
large outfit was found encamped on the river bank unable to proceed any further, waiting
for something or somebody to turn up. Ten days had passed before help arrived. He had
been brought hither by a gasoline engine and canoe, his only companions so far as is
known being two spaniels. This gentleman styled himself a prospector ostensibly bound
for Fond-du-Lac to investigate the silver strike there; but his proceedings and appearance
belied the assertion, for if there were a man who should not have left the shelter of the
paternal wings, it was he. The impression gained was that he was one of those helpless
useless atoms of humanity that are misfits anywhere, but in the North, where one must
be self-reliant, doubly out of place. He having arranged with Mr. Cornwall for a "lift" from
there to Fort McMurray, lay all day on his bedding in the sand surrounded by his goods
and chattels, playing with his dogs, bestirring himself only to take a photograph
occasionally or get a bite to eat.
Fondled His Spaniels and Looked On
62. He was apparently oblivious to the tragedy being enacted within a hundred yards of him.
This man called down upon himself the contempt and scorn of all men present by
remaining inert, lazily fondling his spaniels whilst men's lives trembled in the balance. His
hand upon the rope would not perhaps have helped much, but we should at least have
known that he was a man. The sequel to his apathy was that next day he was deposited
on the main land below the rapids and where it was intimated to him that his company
was no longer desirable.
An All Night Mosquito Raid
Whether fired by a spirit of recklessness by the events of the day, or whether the writer
was too tired to return to his camp on the mainland with the men is of little consequence,
but be it known that his mosquito-bar was there. Needless to say, the mosquitoes were
victorious. We needed no alarm clock that morning because the enemy forced me out of
bed during the night to upbraid myself for a fool. Not a wink of sleep for me as a result;
however, we got an early breakfast out of it.
The Tug "Crester" Wrecked
My Russians were making good progress removing the rails, the freight having been all
portaged, and the scows run through the previous day were being drawn up to the Island
and reloaded. About 10 o'clock Captain Barber started to run the tug "Crester" through
the rapids without steam, steering with auxiliary in case of accident. Disaster dogged the
footsteps of the railroad party apparently. Nothing had gone well so far. The climax had
arrived. Those who were watching the river gave a shout. All eyes went to the rapid
immediately; there was the "Crester" shooting down through the roughest of the water
well over on the land side, out of control. We learned later that her rudder had been
smashed. We saw her take a few bad bumps from a distance of two hundred yards; then
with a final heave she seemed to be lifted bodily and dashed on the rocks close inshore
where she lay a wreck with her bottom stove in, broadside to the current with the waves
breaking over her.
63. The "Crester" Dismantled
There were no casualties. With the aid of spars, the crew were easily able to make the
land. It was the middle of the afternoon before it was possible for me to go over and see
the tug. In the space of six hours the captain, engineer and boatmen had her completely
dismantled and all her "innards" ashore, whilst preparations were being made to pull her
off and float her down the rest of the way into the Big Eddy, where she could be patched
up.
(To be continued)
64. Moose Island Afire
Clergyman's Bonfire Grows Into Conflagration, Threatening H.B.C. Post and Natives'
Homes
BY GEO. FINDLAY, Moose Factory
A Journal extract, dated August 25th, 1920, states briefly that:
"The Rev. Mr. Haythornthwaite while burning old tree stumps at the back of the
Mission allowed the fire to run on, thereby setting alight the adjoining bush."
That day, a Wednesday, was excessively hot, and, as the whole summer had been very
warm, all the bush and undergrowth must have been perfectly dry. At 2 o'clock in the
afternoon the cry of "Fire" went up, and from the southwest end of the island a big
column of smoke began to darken the air, blowing in the direction of the Post.
For some minutes the natives stood gazing and then the realization that the Island was
afire broke upon them. Something akin to panic set in. Canoes were loaded. Food,
blankets and tents were thrown haphazardly into them, and they were swiftly paddled to
the opposite bank of the river by the fear-stricken natives.
Imagine the scene: The river dotted with canoes, with their multicoloured loads; the roar
of the ever-increasing fire, as it was fanned by a slight breeze, and the strange stillness
that pervaded the Post, which can be sensed only in a deserted place.
The servants returned as soon as their families were safely "entrenched" on the other
side of the river, and each with his axe hurried to the scene of the outbreak.
In company with Mr. Gaudet, our Post Manager, I went to see the progress made by the
fire. Often we were compelled to change our route through the bush on account of the
terrific heat and the choking, blinding smoke. In many places great patches of
undergrowth were blazing quite a distance from the body of the fire, sparks having been
blown ahead by the wind.
The roar of the fire was deafening as it caught fresh trees, shooting great lurid tongues
of flame up their entire thirty feet. Darker and darker grew the air; the heat became
fiercer; the fire advanced as if to satisfy its terrible hunger by enveloping the entire
Island in its scorching clutch; and as we walked back to the deserted Post thoughts of
having to abandon it ran through our minds.
However the wind dropped, and the little band of fire fighters worked hard to accomplish
their task. Had the wind risen, the whole island would have been devastated.
All that night, and the succeeding five days and nights, gangs of natives (who had by this
time got over their fright) and servants watched the fire until it was successfully stamped
out.
65. Assembly of Indians who received H.B.C. Long Service
Medals at Fort Alexander
Robust sons of Post manager W. A. Murray, at
Fort Alexander, Manitoba
67. WINNIPEG
RESOLVED
Jan. 1, 1921
that New Year's resolutions are not going out of fashion, as witnessed by the following
answers to the query, "What is One of your New Year's Resolutions."
J. H. Pearen—To remain young that I may laugh with my children. To be considerate at all
times of the aged and infirm or those in need of encouragement.
W. Ogden—To think more, talk less and to go through each day fully realizing that the
opportunities which come to me lie in the present and not in the future.
Thos. F. Reith, Card-writer—That I try to emulate the well-known Beaver and turn out
heaps of
Bright
Effective
Artistic
Vigorous
Enterprising and
Readable
show cards, tickets and signs during 1921, in which case I expect to "BE-A-VER-"Y busy
Card-writer.
Geo. W. Ashbrook—It is my opinion that a New Year's resolution, if sincere, should be
confined to the individual's eye alone and not open to the gaze of the public.
S. Kaufman—One of my resolutions for 1921 is to endeavor to reduce my weight twenty
pounds by applying myself assiduously to the royal sport of curling during the winter
season and by strenuously playing tennis during leisure hours in the summer time.
Miss D. Bens—To be true to my word, my work and my friends. To make all I can, to save
all I can and give all I can.
J. W. Frankish—We are aiming at 100% efficiency in selling our merchandise. It should be
sold on the same basis as we buy it. More attention by sales staff in introducing all the
new merchandise as it enters the department. This is our intention in departments 3 and
5 for 1921.
Chas. Healey—Do it now! This is my New Year's resolution. It is so easy to put things off
when just a little "pep," a little extra energy is needed. So much can be gained and
greater satisfaction can be given to all. Do it now!
A. C. Dunbar—I will increase my efficiency—(power to produce)—by studying, plus
analyzing, plus determination, plus application, equals increased efficiency.
68. J. Whalley—That every business act of mine will be executed with the full belief that it is
for the best interest of the firm.
Saml. Drennan—To continue placing more confidence in the washboard than in the Ouija
board.
I. N. Cognito—Not to engage any more handsome looking salesgirls, as those I now have
are all engaged—and may get married.
W. R. Ogston—One of my resolutions for the New Year will be to govern my actions,
thought and speech towards my fellowmen by the well-known principle of "The Golden
Rule" and to do my work in such a way that at the close of each day I may feel that I
have accomplished something.
Winnipeg Moustache Club
Semi-Annual Report
Just prior to the closing of the outfit ending January 31st, 1920, a careful inventory
discloses the following state of affairs. The showing is not entirely satisfactory, but it is
felt that some progress is being made.
Moustaches on Hand—None.
Moustaches on Upper Lip—Twenty divided among the following "heads of stocks":
Messrs. Frankish, Goody, Grant, Moore (tailoring), Lade, Fuller, Hughes, Lackie, Weeden,
Blowers, Leveque, Dickens, Harrison, Hardiman, Keeley, Chambers, Duckneau, Breitner,
Clark, Pugsley (?).
New Member—Mr. T. Nichols. (Greetings, brother).
Under Suspicion—Mr. C. M. Thomas, Mr. C. Robinson, Mr. Robt. Cunningham.
The Club's National Anthem—"The Bonnie Bloomin' Heather."
Legend for Club's New Escutcheon—"The Weight of a Hair Will Turn the Scales."—
Shakespeare.
Remarks—All members and supporters are urged to consult Mr. Saalfeld re irregularities
of growth observed from time to time. Renovation for spring should be undertaken early.
Special rates to members for loan of Hoover electric sweepers. Use of garden rakes or
weeders will result in suspension from Club privileges. Special attention is called to the
alarming recurrence of the grasshopper plague prophesied for June and July.
69. DO YOU REMEMBER this remarkable aggregation? This is
the formidable H.B.C. Football Team, Season 1911-12.
From left to right—Madill, Jones, Medland, Isaacs, Everitt,
Paul, Brodie, Dyde, Foulks, Sheldon, Campbell, Mr. A. H.
Doc, Law, Smith, Allan.
Managers' Social Dramatic Affair
As merry a company as ever graced a festal board met at the store buyers', managers'
and assistants' social in the lunchroom, Thursday evening, January sixth. The highly
edible and diversified "wittles" were disposed of with a display of "wim" and "wigor"
which did justice to all traditions. Entire arrangements for the occasion were undertaken
by the ladies, and the zest with which the entertainment proceeded brought down the
applause of the whole assembly.
Speech, anecdote, jest, song and a three-act drama, starring the celebrated tragedian,
Samuel Drennan, were features of an altogether enjoyable and profitable evening.
Are We 100 Per Cent Efficient?
By R. J. HUGHES
I wonder how many of us could answer the question at the head of this article truthfully
without a considerable amount of self-study, and if we did stop and analyze ourselves
would we find that we could say, "Yes, I am 100 per cent. efficient." Now, let us consider
for a minute what "efficient" really means.
Turning to your dictionary, you will find the definition, "capable of producing the desired
results." Are we really prepared to say "yes, I am capable of producing the desired
results." If you can't, you are not 100 per cent. efficient and must find the reason why. It
does not matter what position you hold or what the nature of your work is, if you are
efficient, advancement is bound to be waiting.
In a recent issue of The Beaver was a copy of what was called "A man-rating chart" and
a statement that stores' staff promotions are governed by efficiency. Study this chart and
70. see how many points you can honestly claim to have mastered. Whatever you do, don't
go round like some people saying, "I am 100 per cent. efficient." If you really are, the
management will soon notice it and promotion will come your way. Next month I will tell
you what an important part memory takes in efficiency.
Y-O-U!
What's the Matter With You, Anyway?
By ELMER PUGSLEY
There are two ways, 'tis said, by which to get into "society"—either by flattering or
shocking it. But though the writer had the honeyed tongue of the anteater, this is no time
to coddle and soothe you with some linseed-poultice sort of caressing lullaby. It's New
Year's and I am deliberately setting out to fire up your "dander." Of course, you may be
able to prove an alibi, but, otherwise, if these few plodding lines succeed in making you
really boiling, red-hot "mad"—(not just angry, you understand)—that will be the best
proof that you're still conscious—and there's hope for you. We shudder when we read of
"so and so" being picked up unconscious, but I could pick up numbers of people in that
pitiable predicament any day—people who somehow got into the business world, strange
to say.
You stand at the outset of a New Year. Scientists think there have been living beings on
this old planet for 500,000 of those time-measures we call years—but there is only one
you can be sure of—that's this year. It's a wonder you didn't think of that without being
told! Glance back over the old year's glimmering trail now fading into whatever such
things fade into. It is strewed with regrets and wasted opportunities that slipped through
your careless fingers! Aren't you ashamed?
What's the matter with you anyway? Don't you care much? Aren't you interested in the
big proposition called "life", more than just enough to watch the procession of
progressive mortals passing? You'll never keep up with them if you don't pad right along!
Wouldn't you like to strike out for a real goal, eh? You have the stuff in you if you'd just
shake yourself a little to rouse your rusting gifts. Don't turn over the key to the bailiff just
because you weren't born under a favorable sign in the zodiac. Even if your teacup
doesn't read right—pshaw! you wouldn't let a thing like that spoil your future! Never mind
if the bumps on your head are in the wrong place; jump into the scuffle and you'll receive
any other bumps you need before you're through. A chap is said to have advertised his
brains for sale the other day—"good as new—never been used." He never served in The
Hudson's Bay, that fellow. No, sir!
The very air is surcharged with pleas to you to launch out and distinguish yourself. Self
advancement is the theme of the age. No one can do as much for you as you can do for
yourself. You're a regular "powerhouse" of possibilities if you have enough gumption to
utilize them. You remember you turned down a smashing good chance to get ahead,
when, for the sake of a few paltry frivolities, you sacrificed that special study course
which you could have mastered in 1920. You know better than that. You saunter along
71. through life as if you had a thousand years to put in here. Train the microscope on your
freckled career and set about to remedy things. Come now, get hold of yourself! It's all
beginning over again—New Year—new page—new everything! Tackle something that's so
much bigger than you that it scares you! That's the way to grow accustomed to
accomplishing big things. This is your year! How do you know that you're going to have
another as good? Make this your motto—pin it to your New Year's resolutions—"This is
My Year!"—and in sooth it will be your year!
Miss McCheyne's name was inadvertently omitted from the formerly published list of
names of those completing ten years' service.
Since the change in markets Miss Winslow, our postmistress-in-general, is worried for
fear someone is going to tear in one of these days and ask what the new replacement
price is on two cent postage stamps.
Someone turns in an unsigned report about the prevalence of "sparklers" getting hard on
the eyes around the bureau of adjustment.
First Snowshoe Tramp
By Land Staff
Eighteen members of the Land Department staff snowshoed out to the home of Mr. B.
Everitt, our genial associate editor, at East Kildonan, Saturday evening, December 18th.
The party gathered at Redwood bridge and tramped north by way of Red River.
About half way it was found necessary to call a halt owing to the guide being missing. His
rejuvenated appearance upon eventually overtaking the main party led to some doubt as
to the generally accepted meaning of "air holes," which were reported to be the cause of
the delay.
While there was not sufficient snow to make real good tramping, what was lacking in this
respect was more than compensated for by the enjoyable time provided by the host and
hostess at the conclusion of the hike. Here games and dancing were indulged in until
midnight, when the party was brought to an end with the singing of "Auld Lang Syne."—
F.H.N.
An Error Rectified
As some error in the names of the long service medalists had been made at the opening
of the Anniversary Celebration, our general manager's office was the scene the other day
of a pleasant little ceremony when Mr. Chas. E. Robinson was made the recipient of his
long service medal. It was presented by Sir Augustus Nanton, chairman of the Canadian
Advisory Committee, Mr. FitzGerald and Mr. Sparling being also present. "Charlie" has
been with the Store since June 6, 1904, and is one of the bulwarks.
Mr. James Thomson, former Commissioner of lands and furs, was warmly welcomed
home at Winnipeg, December 23rd, after an absence of several months in the Orkney's
and Scotland.
72. EDMONTON
LAND OFFICE
Our photograph shows Mr. J. R. McIntosh, H.B.C. Land
Agent in charge of the Edmonton Land Office, with his
secretary and Mr. Henderson (standing). Mr. McIntosh and
staff who are actively associated with the Company's
housing scheme, operate from these modern offices in the
McLeod Building.
Retail Store Notes
Recent Changes Among Store's Department Heads
Changes never seem to come singly, for since the first appearance of The Beaver no less
than five important executive appointments have been made in the store; and another is
scheduled for the very near future.
Mr. Chasey, the new buyer for the men's clothing departments, and Miss M. Doherty, the
new buyer for the hosiery and gloves, are now firmly established on their feet and are
making noteworthy progress.
We now welcome to our ranks three more recent arrivals:
73. Mr. Pallett is another Easterner who has heard the call of the West. Mr. Pallett succeeds
Mr. Jenkins as buyer of the trimmings and ribbons. He was previously with the T. Eaton
Company for several years. Mr. Pallett is very favorably impressed with the City of
Edmonton and predicts a great future for the store.
Mr. Secord is the new buyer of the ladies' ready-to-wear, and successor to Mr. Woodman.
Mr. Secord was previously with the Robert Simpson Co., of Toronto, nine years buyer of
the ladies' ready-to-wear and fur department. Since coming to the store, Mr. Secord has
won the esteem of the entire staff and we predict a rosy future for the department under
his supervision.
Mr. J. McLeod has succeeded Mr. McKee as buyer of the cigar and candy departments. Mr.
McLeod was recently floor manager on the second floor and was previously manager of
the grocery department, Hudson's Bay Company, Retail, Vernon, B.C.
Hail to Our New Assistant "Chief"
This new appointment was effective on December 13th, 1920. Besides holding the
position of assistant manager, Mr. McKenzie will also act in the capacity of merchandise
manager, thereby relieving Mr. F. F. Harker of a big burden. Mr. Harker has for the past
twelve months acted in the dual capacity of manager of the store as well as merchandise
manager.
Mr. G. M. McKenzie was born in Edinburgh, Scotland, serving his apprenticeship in the dry
goods and men's wear business. In 1901 he came to Canada and joined the firm of
Jaeger & Company, subsequently holding the position of stores manager and supervisor
of the factory in Montreal. In 1916 Mr. McKenzie heard the call of his country and
proceeded to the front, serving with His Majesty's forces in France until March, 1919.
Upon returning to Canada he accepted a position with the R. J. Tooke Company as
general manager of the retail stores in Montreal. His recent appointment as assistant
manager of the Edmonton store will fill a long felt want.
74. Mr. P. A. Stone, president of the Amusement and
Athletic Association, which has grown to embrace
a dozen varied athletic and social activities since
its inauguration in September, 1919.
Mrs. Lewis recently rejoined the staff after an absence of two years. She is in charge of
the lace and neckwear department. We are glad to welcome her back.
Miss Law is also an old member of the staff who has recently come back to the store.
During her absence she was with the Company's store at Calgary. She is resuming her
duties here in the ribbon department.
Miss McAdam, who has been in the Company's service for the past seven years, has left
us for the coast. Miss McAdam was a very popular member of the staff and we regret
75. exceedingly to lose her.
Mr. Howey, of the men's furnishings department, is an expert hockey player. We have no
doubt he will be a valuable acquisition to the store's team.
Mr. C. Stapells, house furnishings buyer, and Mr. Hewes are very busy these days
supervising the draperies and furnishings for the palatial new Empire theatre.
We have heard that a certain young lady on the third floor has lost her heart and is going
to sign a life contract in the very near future.
The A. and A. A. Concert Reveals Real Artists
Another of those very enjoyable concerts which are staged periodically through the
winter months by the Amusement and Athletic Association, was held in the "Hudsonia"
dining room on Thursday evening, December 2nd, at which about 150 members and their
friends were present.
The association was again fortunate in hearing Mr. R. L. Bateman, who rendered "She Is
Far from the Land" and, in response to a hearty encore, "For You Alone" was all that
could be desired.
Miss Kate Hamilton sang "Bird Songs" in which her beautiful voice was heard to very
great advantage.
Mrs. Roy Carbert sang Tosti's "Good Bye," and as an encore, "Angus MacDonald."
Mr. Bert Crockett sang "There's Life in the Old Dog Yet," which was very much
appreciated, he being vociferously encored.
All the other artists are members of the staff and their songs were all rendered in
admirable style.
One exceptionally pleasing number was the duet, "Tenor and Baritone," Mr. T. A.
Crockett's tenor and Mr. Digney's baritone voices blending in perfect harmony.
Miss Edna Southen and Miss K. Riddle were two excellent sopranos, whilst Miss W. E.
Crowther's sweet contralto voice has never been heard to greater advantage.
Mr. T. A. Crockett and Mr. George Saunders have fine tenor voices, whilst Mr. G. Robert's
deep bass was used with effect in "Out on the Deep."
Mr. C. Digney was splendid in "Captain Mack" and later his rendering of "My Old Shako"
was perfect.
Miss Moore acted as accompanist throughout and in addition gave a duet in company,
with her sister.
One cannot speak too highly of Miss Moore's assistance, as she is always ready and
willing to help in any way that will add to the enjoyment of the staff, whether it be as
accompanist or soloist.
Mr. P. A. Stone, president of the Amusement and Athletic Association, acted as chairman.
Community Singing is Getting Results
76. Community singing for the staff, which was inaugurated at the Edmonton store,
November 1st, 1920, is reported to be an unqualified success.
The staff arrive at 8.45 a.m. and sing usually two songs before 8.55 a.m. bell sounds,
when the covers are removed preparatory to the day's business.
The initiative was taken by the Amusement and Athletic Association. The fact that it is
still retaining the original interest proves that the all-important co-operation has been
obtained; hence the success.
Whilst it is impossible yet to gauge the full extent of the benefits derived from community
singing, it may be said that the early morning "grouch" is dissipated, and that alone
makes it worth while, as it leaves the staff in a happier frame of mind. This cannot but
conduce to the betterment of the service afforded to customers.
From community singing to a trained choir is but a step, since even the untrained singer
gradually falls into and holds the time and rhythm of the piece being sung, so that from
an untrained band of voices a perfectly functioning choir is created.
This is the aim of the Edmonton Amusement and Athletic Association, and with a
continuance of the staff's co-operation that end will be attained.
The Ad. Man's Destiny
Mr. Jack Prest was going home one night in the street car. It was late, and the man
sitting next to him began to talk. "What business are you in?" he asked. "The
advertising business," replied Jack. "Is that so? Well, well, I used to be in the
advertising business myself. I gave it up though and went into the rag-and-old-bottle
business. I was a sandwich man for the Empire Theatre for six months." "Say," and
he leaned over confidentially, "Ain't it hard when the wind blows?"
77. CALGARY
The Rank and File
By F. R. REEVE
The newspapers recently had much to say concerning the remarkable honors paid in
England and France to the bodies of two unknown soldiers who fell on the battlefields.
It was a nation's whole-hearted recognition of the fact that Victory was after all due to
the efforts and self-sacrifice of the rank and file.
In the scheme of life each one of us has a definite sphere to fill. Lest those who now
constitute the rank and file in the service of the Company should be inclined to regard
their positions with something of dissatisfaction, as being of no importance, I would have
them take a lesson from the honors paid to these two unknown soldiers.
Upon those who constitute the front rank, those who come in contact with the public, the
whole success of this great Company depends.
Behind you it is true, stretches a long line that reaches back from the junior buyer,
through to the Governor himself, but the work accomplished by this wonderful
organization does not reach its greatest success except through your co-operation.
The transaction between a customer and salesperson is not just so much money
changing hands for a certain article. It represents the crowning success of a long series
of operations, that, through your hands as the H.B.C. representative, reaches the goal for
which it was intended, an appreciative buying public.
Upon the conduct of the rank and file—upon the impressions that are derived from your
personality—is this Company judged.
The courtesy, helpfulness and efficiency that are displayed by you are the greatest assets
this Company has. To know and to realize that no matter what your position in the
service of the Company may be, that the Company is absolutely depending on your
efforts will be to create in you a greater desire for helpfulness and efficiency which
cannot fail to mean greater success for yourself and Company too.
78. VANCOUVER
Everybody Boost for Our 1921 Hockey Team
It has been asked of the editor why there were not more attending the hockey games
last winter, and why the H.B.C. employees were very backward in supporting their own
team, being especially conspicuous by their absence. We've a dandy team this year, folks,
and the boys sure would like some "rooters." Come along and bring your friends and the
horn off the old Ford. Help the team make a name for themselves in the Commercial
League. The following are the names of our players:
W. E. Almas (Capt.)
E. Herbert
P. Timmins
Chub Anderson
R. M. Mair
J. Gilroy
J.C. Hamm
J. McDonald
J. D. Barber
C. Boe
We were very grieved to hear on December 10th of the death of Mr. Patterson, husband
of Mrs. W. Patterson, cashier in our children's shoe department.
We are also bereaved of one of our old employees, Mr. James Hallisy, who passed away
at his home on December 10th. The deceased was on our night staff, and had been in
the Company's employ since 1918.
The army and Navy League Hall again witnessed a popular H.B.C. dance. Approximately
350 attended and tripped the light fantastic to the strains of Garden's orchestra. Mr.
Skelly, chairman, and his competent committee had charge of the affair, which was
carried off without a hitch to a very successful ending.
Mr. Lockyer Elected President of Vancouver Exhibition Association
79. Holding their first meeting since taking office, the directors of the Vancouver Exhibition
Association on Dec. 16th elected Mr. H. T. Lockyer, manager of the Hudson's Bay
Company, Vancouver retail store, as president for the ensuing year.—Vancouver Province.
Mr. W. W. Frazer, the popular buyer for china and glass, left for Europe in the interests of
his section, early this month. Many laudatory remarks were overheard by Eastern and
American tourists anent his last collection of lovely china. Mr. Frazer apparently knows
where to get them. "Where do they get all these pretty patterns—there's not an ugly one
among them"—exclaimed a lady from Ottawa recently, and went on to say she had never
seen a better display in New York, Montreal or Toronto. But that's Mr. Frazer's secret. We
wish him bon voyage and the best of luck this time.
Miss A. K. Smith, too, buyer of notions, neckwear, laces, trimmings, hankies and fancy
jewellery, has been chosen for a trip abroad after the airy fairy "nothings"—"the stuff that
dreams are made of"—that are so dear to feminine hearts. Her return from Europe
ladened with spoils will be looked forward to with interest by her constituency in
Vancouver. You may be sure Miss Smith will not overlook any of the cute or smart little
knick-knacks that are being shown in the marts over there, and we shall all have an
opportunity to be more than ever up-to-date on her return. Vancouver is to be
congratulated on having two buyers in whom the Company has so much faith and
confidence as to entrust with this important foreign buying.
The Tell-Tale Inventory
A Vancouver bailiff went out to levy on the contents of a house. The inventory began in
the attic and ended in the cellar. When the dining-room was reached the tally of furniture
ran thus:
One dining room table, oak.
One set of chairs (6), oak.
One sideboard, oak.
Two bottles of whiskey, (full)!
Then the word "full" was stricken over and replaced by "empty" and the inventory went
on in a hand that struggled and lurched across the page, until it closed with:
"One revolving door mat."
Mr. Greer Gets a Regular Shower of Good Things
By E. Bell
Of the recent year end festivities enjoyed by Hudson's Bay employees perhaps none had
more of the vivres and relish of the days of real sport than the banquet tendered Mr.
80. Greer by his staff in the display department.
This event took place in the Barron Hotel to begin with and ended at a box party to the
opera to witness the "Dance Shop." The menu of the dinner, which was enjoyed both
wisely and well, gives some of the unlucky individuals who were not invited an appetizer
even to read:
Greer Soup
Goose a la Greer
Oyster Cocktail, Y.M.C.A.
Celery a la Celestial Citizen
Brussels Sprouts a la Lulu Island
Fried Sweet Potatoes, Brunette
Hot Toasted Rolls, Blonde
Combination Salad a la Display
French Pastry Translated Cake, Devilled
Creme de Chaufroid Cafe d'Hots D'el
(N.B.—S.O.S. Calgary. M. Laparique, please note. Can you beat it?)
Having done full justice to these delectable viands the innocent occasion of so much
mirth was next trotted to the opera, where his friends had taken the precaution to
present him with a lorgnette or opera glass, we forget which. (Anyway it was not a
monocle.) Notwithstanding, to the everlasting credit of the display department, they all
turned up next morning on time and in the best of spirits.
Old-Time Employees Visit the Store
Among the guests of the Store last month were Mr. and Mrs. Alexander J. Baird, both old-
time employees of the Company, who devoted a number of years of faithful service in the
old store and two or three years in the new store.
Mr. Baird was secretary to the general manager, Mr. Lockyer. In 1917, he went to
Honolulu for a new field to conquer. He was there but a little while before he sent for his
fiancee, Miss Beck, then the general manager's stenographer. As soon as she arrived in
Honolulu they were married. Being accustomed to speculating and used to seeing money
made out of land, Mr. Baird (in face of much opposition) bought a piece of land and built
three cottages thereon—an investment which proved a good one and a money maker.
81. KAMLOOPS
H.B.C. Kamloops Store Dates Back to 1812
Location Has Changed Several Times to Keep Pace With Growth of City
By A.E. DODMAN
The Company's store at Kamloops dates back to the year 1812 and it is therefore one of
the oldest establishments at present existing in the stores department.
The original location was some distance from the present store site, as, like all Western
towns, the business centre has changed several times, and the Company found it
necessary to change from time to time in order to keep pace with the natural growth of
the city.
The present premises were purchased and remodelled by the Company in 1911, and
have a frontage of 75 feet on Victoria Street, extending 125 feet on Second Avenue with
two entrances on Victoria and one on Second Avenue.
The building consists of two stories and basement. In addition the Company also
operates a wholesale and retail tobacco and candy business on rented premises situated
at the corner of Victoria Street and Third Avenue.
The business at Kamloops comprises eight departments—general dry goods, ladies' wear,
men's furnishings, boots and shoes, crockery and hardware, house furnishing, groceries
and tobaccos.
Miss Brooke, of the grocery staff, resigned her position with the Company and was
married on January 1st, 1921. She was presented with a travelling bag by the staff. We
wish her all kinds of joy and happiness in her new venture. She was a real "good fellow"
and will be greatly missed by us.
Miss Muir has accepted the position made vacant by Miss Brooke of the Grocery
Department. We wish Miss Muir every success.
Miss Cozens says she was never "locked out" in her life, but she experienced the feeling
of being "locked in." She says "never again."
The Staff presented Mr. A.E. Dodman, our store manager, and Mrs. Dodman with a
Christmas gift of a very handsome tea set with best wishes.
A rumour is heard to the effect that Mr. McDonald, the accountant, has become an expert
dancer, and has accepted an invitation to teach three ladies the fine points in dancing.
Nice for Mac, but kind of tough on the ladies.
82. After a very busy and most successful Christmas trade the staff have settled down for the
most successful January sale we have ever had.
83. VERNON
Entire Staff a Santa Claus to Mr. Pout, Xmas
On Christmas Eve, at the close of the biggest day in the history of the Vernon Store, the
staff gathered for a few minutes to extend good wishes and exchange tokens of
friendship. At the conclusion, Mr. Pout was captured when trying to tip-toe off, set
securely within the smiling circle, and compelled to listen to the following effusion which
Tom Bone, the store poet, says he did not compose. It is now being blamed on Jack
Ricketts, and so far Jack hasn't denied it.
84. Our dear respected Mister Pout
We guess you guess what we're about;
If not, you won't be long in doubt,
But get the sense,
So we shall quickly put to rout
Your dread suspense.
It's Christmas time, as you well know,
And we have gathered here to show
That years may come and years may go,
With rush and zest,
But our good feelings far outgrow
This timely test?
It gives us joy to give to you
This coffee service, bright and new,
And wish that all things good and true
That hope conjures,
May travel all the next year through
With you and yours.
Mr. Pout was too full for words (honi soit qui mal y pense), but he managed to express
his hearty thanks for the splendid support and co-operation he had received from the
entire staff during the Christmas rush, also for the kind thought which prompted the
giving of such a beautiful gift.
The coffee pot was one of those long narrow "prohibition" coffee pots that you are
unable to tell what is inside of until you taste the contents.
Tom Harrison struck up "He's a Jolly Good Fellow." "Arry" thought it was "Auld Lang
Syne" and started off on his own, while James Henderson, in an endeavour to put them
both right, commenced "Will You No Come Back Again."
When the company broke up, those three were still at it, and nobody could tell which was
winning.—R.W.
Miss Cridland, treasurer of our Sisters' Sewing Circle, has been absent from the meeting
several week. We were surprised to see her at the last meeting. She says her absence
has been due to the fact that she had to attend "prayer meetings." We have since
learned that a certain young man's "tin Lizzie" is being overhauled. May it take all winter
—so Gladys will be at every meeting.
85. Miss Phillys Ripley, the girl with the sparkling eyes, assisted for several weeks in the
hardware department but is back once again at her old stand tying bows for the kiddies.
Her eyes still sparkle and there are many beaus waiting for her to cast her spell on one of
them so that two may be tied into one bow.
"Wonderful how popular some men are," said Watson, when he heard what happened
Christmas Eve. The girls in the dry goods department placed mistletoe on the light over
Mr. Andrews' desk—and not one missed him, even Mabel had hers. Nuff sed.
Mr. Tom Bone, assistant manager of the grocery department, the staff poet, has changed
his vocation and now spends his evenings making musical instruments. We wonder if it
will be jazz or operatic music.
We are glad to learn that Mrs. Griffin, wife of C. Griffin of the men's department, is home
once again after being confined to the Hospital several weeks with typhoid fever. We all
wish her a speedy recovery.
Vernon, Gem of the Okanagan
—and the H.B.C. Store, One of Its Institutions
Thirty years ago, there were only two stores in Vernon, The Hudson's Bay Company and
W.F. Cameron, both firms carrying a general line of merchandise. The only other stores in
the Okanagan Valley, at this period, were one at Enderby, Landsdowne, Okanagan
Mission and Penticton, so that these stores supplied the necessities of life practically to
the whole of the Okanagan Valley, reaching from Sicamous to fifty miles beyond
Penticton and from Grand Prairie to the White Valley district. The towns of Armstrong and
Kelowna, at this period, were not in existence.
Travelling in the early days was by stage and boat in Summer, the boat running from
Sicamous to Enderby, thence by stage to Vernon, and the only method of travelling in
Winter was by stage or pack horse. Mail, also, was received by these means of
transportation.
The great bulk of trading, at that time, was done with Victoria, which was a greater
commercial centre than Vancouver. All merchandise from the Coast was carried by freight
trains to Sicamous, transferred there to a small steamer as far as Enderby and thence by
wagon to Vernon.
Business conditions and the manner of trading in the early days were entirely different to
the present day method. There were no banks in the Valley, all banking being done
through Vancouver, cheques often passing around as currency and would have as many
as a dozen endorsations before reaching the bank.
Yearly credit was the system of trading. Farmers, ranchers, trappers and Indians paid
their accounts once a year after they had received money for their crops and catch of
furs; the amusing feature in regard to the credit in these days being that the average
customer would ask of his account, simply looking at the total and settling up without
checking up. Considerable business was done in the bulk, tea sold by the chest, flour and
sugar by the ton, and other commodities in similar large quantities.
86. Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com