Hello World Servlet Tutorial

From Resin 4.0 Wiki

(Difference between revisions)
Jump to: navigation, search
 
Line 12: Line 12:
  
 
Servlets belong in <em>WEB-INF/classes</em>.  On this machine,
 
Servlets belong in <em>WEB-INF/classes</em>.  On this machine,
the source is in Java source in <em>/var/www/webapps/ROOT/WEB-INF/classes</em>.
+
the source is in Java source in <em>/var/resin/webapps/ROOT/WEB-INF/classes</em>.
 
WEB-INF/classes is the standard location
 
WEB-INF/classes is the standard location
 
for servlets and other Java classes.  Resin automatically reloads and
 
for servlets and other Java classes.  Resin automatically reloads and
Line 22: Line 22:
  
 
* WEB-INF/classes/test/HelloServlet.java
 
* WEB-INF/classes/test/HelloServlet.java
* WEB-INF/web.xml
 
  
There are two files that you will create for the tutorial: a Java class and an XML file. The Java class implements the  
+
There is one file that you need to create for the tutorial, the Java class implements the  
servlet itself. The XML file tells the servlet engine which URLs go to the servlet.
+
servlet itself.  
  
 
= Creating the Servlet class =
 
= Creating the Servlet class =
Line 38: Line 37:
 
   import java.io.*;
 
   import java.io.*;
 
   
 
   
 +
  import javax.servlet.annotation.*;
 
   import javax.servlet.http.*;
 
   import javax.servlet.http.*;
 
   import javax.servlet.*;
 
   import javax.servlet.*;
 
   
 
   
 +
  @WebServlet("/hello")
 
   public class HelloServlet extends HttpServlet {
 
   public class HelloServlet extends HttpServlet {
 
     public void doGet (HttpServletRequest req,
 
     public void doGet (HttpServletRequest req,
Line 49: Line 50:
 
   
 
   
 
       out.println("Hello, world!");
 
       out.println("Hello, world!");
      out.close();
 
 
     }
 
     }
 
   }
 
   }
Line 59: Line 59:
 
The ''/hello'' URL is configured for the hello, world servlet below.
 
The ''/hello'' URL is configured for the hello, world servlet below.
  
== WEB-INF/web.xml Configuration ==
+
= installing and deploying a servlet application =
  
Configuration for the servlet is in the ''WEB-INF/web.xml'' file.
+
To test this tutorial, you'll need to have a servlet engine like Resin installed on your computer.
 +
The Resin servlet engine download is at http://resin.caucho.com.
  
The servlet needs to be configured and it needs to be mapped
+
== Using Eclipse and the Resin Servlet Container ==
to a URL.  The &lt;servlet> tag
+
configures the servlet.  In our simple example, we just need to
+
specify the class name for the servlet.
+
  
The <servlet-mapping> tag specifies the URLs which will invoke the servlet.  In our case,
+
First go here to get Eclipse for Java EE:
the ''/hello'' URL invokes the servlet.
+
[http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr2 Install Guide for Eclipse for Java EE Indigo or higher].
  
=== WEB-INF/web.xml ===
 
  &lt;web-app xmlns=<nowiki>"http://java.sun.com/xml/ns/j2ee"</nowiki> version="2.4"
 
          xmlns:xsi=<nowiki>"http://www.w3.org/2001/XMLSchema-instance"</nowiki>
 
          xsi:schemaLocation=<nowiki>"http:/java.sun.com/dtd/web-app_2_3.dtd"</nowiki>>
 
    &lt;servlet>
 
      &lt;servlet-name>hello&lt;/servlet-name>
 
      &lt;servlet-class>test.HelloServlet&lt;/servlet-class>
 
    &lt;/servlet>
 
 
    &lt;servlet-mapping>
 
      &lt;servlet-name>hello&lt;/servlet-name>
 
      &lt;url-pattern>/hello&lt;/url-pattern>
 
    &lt;/servlet-mapping>
 
  &lt;/web-app>
 
  
Resin allows a short cut for the XML configuration in the example above;
+
Using Eclipse Indigo or higher
you can use XML attributes in place of elements.  The
+
Servlet 2.4 standard uses only elements.  So the servlet-mapping
+
configuration following the Servlet 2.4 standard would look like:
+
  
=== WEB-INF/resin-web.xml ===
+
Install Resin (lightweight, fast, easy to use Java EE 6 servlet container) plugin:
  &lt;web-app xmlns=<nowiki>"http://caucho.com/ns/resin"</nowiki>>
+
# Go to File menu -> New Project -> Dynamic Web Project
    &lt;servlet servlet-name="hello"
+
# In New Dynamic Web Project Dialog-> New Runtime...
              servlet-class="test.HelloServlet"/>
+
# In New Runtime Dialog -> Download Additional Server Adapters -> Select Resin (Java EE Web Profile) 4.0.x
+
# (Click Next and Ok until it installs Resin runtime)
    &lt;servlet-mapping url-pattern="/hello"
+
# (Eclipse needs to restart)
              servlet-name="test.HelloServlet"/>
+
  &lt;/web-app>
+
  
The two are entirely equivalent.  For larger configurations,
 
using attributes makes the resin.conf or web.xml more readable.
 
  
{|
+
Setup new Web Project in Eclipse
! tag
+
# File -> New Project -> Dynamic Web Project
! meaning
+
# In New Dynamic Web Project Dialog-> New Runtime...->Select Resin->Check create local server checkbox
|-
+
# Step 2 of New Runtime...->Click Download and Install (you only have to do this once)
! web-app
+
# Fill out project name etc. (bookstore).
| Web application top-level tag.
+
# (Click Next and Ok until you are done)
|-
+
! servlet
+
| defines the servlet class and gives the servlet a name
+
|-
+
! servlet-mapping
+
| translates the URL to the servlet
+
|}
+
  
The ''<nowiki>xmlns="http://caucho.com/ns/resin"</nowiki>'' lets Resin
+
== Ubuntu install of Resin servlet container ==
validate the web.xml configuration.  The validator will catch most
+
errors in the web.xml.
+
  
= installing and deploying a servlet application =
+
On ubuntu system, you can install Resin servlet container directly with the following three steps:
 
+
To test this tutorial, you'll need to have a servlet engine like Resin installed on your computer.
+
The Resin servlet engine download is at http://resin.caucho.com.
+
 
+
== installing Resin servlet engine on ubuntu ==
+
 
+
On ubuntu system, you can install resin directly with the following three steps:
+
  
 
   unix# add-apt-repository http://resin.caucho.com/download/debian
 
   unix# add-apt-repository http://resin.caucho.com/download/debian
Line 134: Line 95:
 
   unix# apt-get install resin
 
   unix# apt-get install resin
  
The Resin directory for you application will be in /var/www/resin/webapps/ROOT, and the default port
+
The Resin directory for your application will be in /var/resin/webapps/ROOT, and the default port
 
will be port 8080, as in this tutorial.
 
will be port 8080, as in this tutorial.
 +
 +
== Windows install of Resin servlet container ==
 +
 +
# On windows, download the Resin zip from http://resin.caucho.com.
 +
# unzip Resin into something like resin-4.0.32
 +
# resin-4.0.32/resin start-all
 +
# resin-4.0.32/resin deploy ROOT.war
 +
 +
You can also deploy the example in resin-4.0.32/webapps/ROOT. The "ROOT" means the top-level URL.
  
 
== deploying an application ==
 
== deploying an application ==
  
You can also bundle up your application into a .war archive, which is just a zip file with a java ".war" extension,
+
You can also bundle up your application into a .war archive, which is just a zip file with a java ".war" extension
and then deploy the application using Resin's command-line tool:
+
that you create with the "jar" command (like zip). You'll deploy the .war archived application using Resin's command-line tool:
  
 
   unix> cd myapp; jar -cf ../ROOT.war *
 
   unix> cd myapp; jar -cf ../ROOT.war *
Line 150: Line 120:
 
= Review =
 
= Review =
  
* The servlet is a Java class that implements the Servlet interface, usually by extending HttpServlet
+
* The servlet is a Java class that handles HTTP web requests by implementing the Servlet interface, usually by extending HttpServlet
 
* The servlet classes belong in WEB-INF/classes, or in .jar files in WEB-INF/lib
 
* The servlet classes belong in WEB-INF/classes, or in .jar files in WEB-INF/lib
 
* The servlet to URL mapping is configured in WEB-INF/web.xml
 
* The servlet to URL mapping is configured in WEB-INF/web.xml
 
* The servlet ''doGet'' method serves a standard HTTP request
 
* The servlet ''doGet'' method serves a standard HTTP request
* The servlet output is generated from ServletResponse.getWriter
+
* The servlet text output is generated from ServletResponse.getWriter
 
* Servlet applications are usually bundled in *.war files and deployed in webapps directories
 
* Servlet applications are usually bundled in *.war files and deployed in webapps directories
* To deploy a war file, use ''resinctl deploy myapp.war''
+
* Applications bundled as war files are deploy using ''resinctl deploy myapp.war''
 +
 
 +
= Programming Patterns in the Servlet Hello World Tutorial =
 +
 
 +
[[Image:fractal.png|right]]
 +
 
 +
Since all servlets use the same basic structure as this tutorial, it's a good idea to understand this most
 +
basic example completely.
 +
 
 +
While a cookbook example like the hello, world servlet is primarily useful to get you started, you can use it more effectively
 +
by studying the patterns it introduces to develop your programming skills. Expert programmers can recognize a huge
 +
number of patterns, which is why they are effective. Beginning programmers only know a few patterns and can't always recognize
 +
when the pattern should be used. So although you can just take the cookbook above and work with it, you will gain more benefit
 +
from the discussion below. Like all expertise, it's also worth coming back as you learn more.
 +
 
 +
The fractal diagram on the right shows why patterns are valuable not just as a cookbook, but also for building complex applications.
 +
A fractal uses a simple rule or pattern repeated at finer levels of detail. The fractal on the right cuts each box in half. The key insight of
 +
fractals is to use the same patterns when you're looking at a high abstraction as when you're looking at the detail. This hello servlet
 +
tutorial is at the highest level possible, since it's the entire application, but the principles also apply to details of complex applications.
 +
 
 +
Servlets are some of the fastest web application, from web servers, to JSON/REST web services, to high-performance
 +
websocket mobile messaging applications, web sites, and even fast PHP servers written in Java. For example, the Resin
 +
web server uses servlets to implement a web server that's faster than the best C-based web servers, including Apache httpd
 +
and nginx. If you understand these tutorials, you'll be on the path to developing the best applications on the internet.
 +
 
 +
Focus and encapsulation is the key general pattern for server applications, and for most programming. People can only focus on a few
 +
ideas at a time, and cannot multitask effectively. You might be able to manage three ideas at a time, but not twenty. To use focus in
 +
your programs, each part should have its own job, and it should be ignorant of the details of the internals of other parts. Ignorance is
 +
good in programs. Each part should be as ignorant as possible, and should keep its own details hidden from others to avoid distracting
 +
them. Encapsulation is the programming principle of keeping the details hidden from other components. The better you understand encapsulation and
 +
how to use it effectively, the better your programs will be.
 +
 
 +
== Service and Dispatch Pattern ==
 +
 
 +
[[Image:servlet-dispatch.png|right]]
 +
 
 +
All servlets follow the service and dispatch pattern, which is why they are called servlets. In a sense, every servlet application is an example of
 +
a service-oriented architecture on the internet. There are two key parts of the service pattern: the address of the service and the general server interface.
 +
For servlets, the address is the HTTP URL, and the interface is the servlet interface, where the ''HttpServletRequest'' and ''HttpServletResponse'' are
 +
the most important part. For the browser client on the internet, the address is the URL, and the interface is the HTTP protocol. The same service pattern is
 +
used for REST applications, where the address is the URL again, and the interface is often a JSON-encoded HTTP response. All of these use the same basic service pattern.
 +
 
 +
# address of the service (examples: the URL is the address for most internet applications)
 +
# interface of the service (examples: the servlet request/response, or HTTP, or a custom Java interface, or JSON/REST)
 +
 
 +
Following the general encapsulation pattern, the service pattern has two characters or actors, the ''dispatcher'' and the ''service'' each of which knows as little as possible about the other.
 +
For this hello tutorial, the service is hello servlet itself and it focuses on implementing the hello service. The dispatcher is the Resin servlet engine. The hello servlet knows about writing "hello",
 +
but does not know or care how the dispatching works. Most importantly, the service does not know or care about any other services in the system; it is isolated from them. The Resin servlet engine knows
 +
how to take the URL address and dispatch to the hello servlet, but does not know or care how the servlet processes the servlet. The dispatcher knows all the services and their addresses,
 +
but doesn't know what they do. The dispatcher and service characters only need to know about the common interface, which acts like a contract.
 +
 
 +
# service implementation (examples: servlet, REST service, bean in a dependency-injection system)
 +
# dispatcher (examples: servlet engine, CDI engine for JavaEE standard dependency-injection)
 +
 
 +
The service and dispatch pattern has two phases: a registration phase where the service tells the dispatcher its address, and a dispatch phase where the dispatcher sends a request to
 +
the service. In the servlet tutorial, the @WebServlet is the key to the registration phase. When the servlet container starts, it looks for all classes with a @WebServlet annotation. For each one
 +
that it finds, it registers the URL with the dispatcher. When a new request comes in, it will use the URL to dispatch to the servlet. The dispatcher essentially works like a post office or a phone service.
 +
When you move to a new house, or get a phone, you need to register your address or phone number with the post office or phone company. Once you're registered, you'll receive new messages automatically.
 +
 
 +
# the servlet registers with the dispatcher at a URL address
 +
# the dispatcher sends matching requests to the servlet
 +
 
 +
==== registration of servlet with servlet container dispatcher ====
 +
  @WebServlet("/hello")
 +
  public class HelloServlet extends HttpServlet {
 +
 
 +
== Interfaces and Abstract classes ==
 +
 
 +
The hello tutorial is a good example of using both interfaces and abstract classes. Interfaces are used to communicate between different code, for
 +
example the Servlet and HttpServletRequest and HttpServletResponse are used by the servlet container and the servlet to pass information back and forth.
 +
Abstract classes, like HttpServlet let implementations like the HelloServlet focus on the important behavior, leaving the standard shared code to the common code.
 +
 
 +
Abstract classes are good for managing upgrades and version changes when you use interfaces and abstract classes in your own code. When you add a new method to an interface, you
 +
can add a stub method to the abstract class, and your implementations do not need to change.
 +
 
 +
The following example is like the servlet API, where ''MyInterface'' is ''javax.servlet.Servlet'' and ''MyAbstract'' is ''HttpServlet'', and ''MyImpl'' is ''HelloServlet''.
 +
 
 +
==== MyInterface.java ====
 +
  public interface MyInterface {
 +
    public String hello();  // original method
 +
 
 +
    public String newHello(); // new method
 +
  }
 +
 
 +
==== MyAbstract ====
 +
  abstract public class MyAbstract implements MyInterface {
 +
    abstract public String hello();  // original method
 +
 +
    public String newHello() { return "default-value"; }
 +
  }
 +
 
 +
==== MyImpl.java ====
 +
  public class MyImpl extends MyAbstract {
 +
    public String hello() { return "hello, world"; }
 +
  }
 +
 
 +
In general, it's a good idea when you use interfaces in your own code to also provide abstract classes to let you upgrade your application as you
 +
develop it.
 +
 
 +
== Multithreading and Concurrency ==
 +
 
 +
To get the highest performance, servlets are multithreaded, which means multiple HTTP requests will run through your servlet at the same time.
 +
While multithreading is a huge topic, there are a few key concepts that can help understand the issue.
 +
 
 +
# data specific to a request is thread safe
 +
# multithreading is only a problem for shared data.
 +
# shared data needs to be protected or managed to be thread safe
 +
 
 +
In the servlet API, the HttpServletRequest and HttpServletResponse objects are specific to the request thread, so they are thread safe. Any local
 +
variables or objects you create for a thread will also be thread safe. The servlet class itself is shared, so it is not thread safe.
 +
 
 +
The following bad example shows a broken, unsafe servlet. Because multiple requests might run through the servlet at the same time, the
 +
''_badSharedVariableXXX'' can get an incorrect value. For example, the first request 'A' might see an output "1" and the second request B might
 +
also see an output "1" and even though two requests came through, the counter was only incremented once.
 +
 
 +
==== Bad, non-thread safe code ====
 +
public class BadServlet extends HttpServlet {
 +
 +
    private int _badSharedCounterXXX;
 +
 
 +
    public void doGet (HttpServletRequest req,
 +
                                HttpServletResponse res)
 +
      throws ServletException, IOException
 +
    {
 +
      PrintWriter out = res.getWriter();
 +
 +
      int badValue = _badSharedCounterXXX++;
 +
 
 +
      out.println("Bad counter: " + badValue);
 +
    }
 +
 
 +
How do you manage the multithreading problem? There's no simple answer, but here are some general things to keep in mind:
 +
 
 +
* emphasize request-based data, except where necessary (like actual shared resources), and pass the current request state as arguments
 +
* know which data is shared and which is per-request
 +
* use frameworks that manage some of the multithreading, for example JPA for persistence and JCache for caching and MVC frameworks
 +
* in some cases, use messaging systems like JMS to convert multithreaded problems into single-threaded queues
 +
 
 +
You should know that multithreading and concurrency is not as simple as using synchronized methods or ConcurrentXXX data structures like
 +
the ConcurrentHashMap.
 +
 
 +
= Cookbooks and Tutorials =
 +
 
 +
* [[Building a simple listing in JSP]]: covers model 2, Servlets, JSP intro.
 +
* [[Java EE Servlet tutorial : Adding create, update and delete to the bookstore listing]]: covers more interactions.
 +
* [[Java EE Servlet tutorial : Using JSPs to create header, footer area, formatting, and basic CSS for bookstore]].
 +
* [[Java EE Servlet tutorial : Adding MySQL and JDBC to bookstore example]].
 +
* [[Java EE Servlet tutorial : Adding validation and JSP tag files to bookstore example]].
 +
* [[Java EE Servlet tutorial : Adding I18N support to bookstore example]].
 +
* [[Java EE Servlet tutorial : Load testing and health monitoring using bookstore example]].
 +
* [[Java EE Servlet tutorial : Setting up clustering and session replication]].
 +
* [[Java EE Servlet tutorial : Setting up security for bookstore example]].
 +
* [[Java EE Servlet tutorial : File uploads for bookstore example]].
 +
* [[Java EE Servlet tutorial : Using JPA for bookstore example]].
 +
* [[Java EE Servlet tutorial : Using JCache for bookstore example]].

Latest revision as of 00:00, 1 October 2012

Cookbook-48.png

Servlets are the pure Java solution to handle web requests. Many web application will use servlets instead of JSP and others will use servlets in conjunction with JSP. Experienced JSP programmers use servlets in conjunction with JSP to create clearer and simpler applications. The servlets handle Java processing: form handing, calculation and database queries. JSP formats the results.

REST web-applications will also use servlets. The REST output will typically use XML or JSON instead of HTML, but will use the same servlet container as for web pages.

Servlets belong in WEB-INF/classes. On this machine, the source is in Java source in /var/resin/webapps/ROOT/WEB-INF/classes. WEB-INF/classes is the standard location for servlets and other Java classes. Resin automatically reloads and recompiles servlets, beans, and classes placed in WEB-INF/classes. You should make some changes and add errors to become familiar with Resin's recompilation and the error reporting.

Contents

[edit] Files in the Tutorial

  • WEB-INF/classes/test/HelloServlet.java

There is one file that you need to create for the tutorial, the Java class implements the servlet itself.

[edit] Creating the Servlet class

Create the following servlet in WEB-INF/classes/test/HelloServlet.java with your favorite editor: eclipse, notepad, emacs, vi, or whatever.

[edit] WEB-INF/classes/test/HelloServlet.java

 package test;

 import java.io.*;

 import javax.servlet.annotation.*;
 import javax.servlet.http.*;
 import javax.servlet.*;

 @WebServlet("/hello")
 public class HelloServlet extends HttpServlet {
   public void doGet (HttpServletRequest req,
                      HttpServletResponse res)
     throws ServletException, IOException
   {
     PrintWriter out = res.getWriter();

     out.println("Hello, world!");
   }
 }

Now browse the servlet at http://localhost:8080/hello. Resin will automatically compile the servlet for you. Browsing servlets differs from page browsing because you're executing a servlet class, not looking at a page. The /hello URL is configured for the hello, world servlet below.

[edit] installing and deploying a servlet application

To test this tutorial, you'll need to have a servlet engine like Resin installed on your computer. The Resin servlet engine download is at http://resin.caucho.com.

[edit] Using Eclipse and the Resin Servlet Container

First go here to get Eclipse for Java EE: Install Guide for Eclipse for Java EE Indigo or higher.


Using Eclipse Indigo or higher

Install Resin (lightweight, fast, easy to use Java EE 6 servlet container) plugin:

  1. Go to File menu -> New Project -> Dynamic Web Project
  2. In New Dynamic Web Project Dialog-> New Runtime...
  3. In New Runtime Dialog -> Download Additional Server Adapters -> Select Resin (Java EE Web Profile) 4.0.x
  4. (Click Next and Ok until it installs Resin runtime)
  5. (Eclipse needs to restart)


Setup new Web Project in Eclipse

  1. File -> New Project -> Dynamic Web Project
  2. In New Dynamic Web Project Dialog-> New Runtime...->Select Resin->Check create local server checkbox
  3. Step 2 of New Runtime...->Click Download and Install (you only have to do this once)
  4. Fill out project name etc. (bookstore).
  5. (Click Next and Ok until you are done)

[edit] Ubuntu install of Resin servlet container

On ubuntu system, you can install Resin servlet container directly with the following three steps:

 unix# add-apt-repository http://resin.caucho.com/download/debian
 unix# apt-get update
 unix# apt-get install resin

The Resin directory for your application will be in /var/resin/webapps/ROOT, and the default port will be port 8080, as in this tutorial.

[edit] Windows install of Resin servlet container

  1. On windows, download the Resin zip from http://resin.caucho.com.
  2. unzip Resin into something like resin-4.0.32
  3. resin-4.0.32/resin start-all
  4. resin-4.0.32/resin deploy ROOT.war

You can also deploy the example in resin-4.0.32/webapps/ROOT. The "ROOT" means the top-level URL.

[edit] deploying an application

You can also bundle up your application into a .war archive, which is just a zip file with a java ".war" extension that you create with the "jar" command (like zip). You'll deploy the .war archived application using Resin's command-line tool:

 unix> cd myapp; jar -cf ../ROOT.war *
 unix> resinctl deploy ROOT.war

The "deploy" will copy the ROOT.war to the webapps directory and deploy your application. Most servlet applications are bundled into .war files and deployed like this.

[edit] Review

  • The servlet is a Java class that handles HTTP web requests by implementing the Servlet interface, usually by extending HttpServlet
  • The servlet classes belong in WEB-INF/classes, or in .jar files in WEB-INF/lib
  • The servlet to URL mapping is configured in WEB-INF/web.xml
  • The servlet doGet method serves a standard HTTP request
  • The servlet text output is generated from ServletResponse.getWriter
  • Servlet applications are usually bundled in *.war files and deployed in webapps directories
  • Applications bundled as war files are deploy using resinctl deploy myapp.war

[edit] Programming Patterns in the Servlet Hello World Tutorial

Fractal.png

Since all servlets use the same basic structure as this tutorial, it's a good idea to understand this most basic example completely.

While a cookbook example like the hello, world servlet is primarily useful to get you started, you can use it more effectively by studying the patterns it introduces to develop your programming skills. Expert programmers can recognize a huge number of patterns, which is why they are effective. Beginning programmers only know a few patterns and can't always recognize when the pattern should be used. So although you can just take the cookbook above and work with it, you will gain more benefit from the discussion below. Like all expertise, it's also worth coming back as you learn more.

The fractal diagram on the right shows why patterns are valuable not just as a cookbook, but also for building complex applications. A fractal uses a simple rule or pattern repeated at finer levels of detail. The fractal on the right cuts each box in half. The key insight of fractals is to use the same patterns when you're looking at a high abstraction as when you're looking at the detail. This hello servlet tutorial is at the highest level possible, since it's the entire application, but the principles also apply to details of complex applications.

Servlets are some of the fastest web application, from web servers, to JSON/REST web services, to high-performance websocket mobile messaging applications, web sites, and even fast PHP servers written in Java. For example, the Resin web server uses servlets to implement a web server that's faster than the best C-based web servers, including Apache httpd and nginx. If you understand these tutorials, you'll be on the path to developing the best applications on the internet.

Focus and encapsulation is the key general pattern for server applications, and for most programming. People can only focus on a few ideas at a time, and cannot multitask effectively. You might be able to manage three ideas at a time, but not twenty. To use focus in your programs, each part should have its own job, and it should be ignorant of the details of the internals of other parts. Ignorance is good in programs. Each part should be as ignorant as possible, and should keep its own details hidden from others to avoid distracting them. Encapsulation is the programming principle of keeping the details hidden from other components. The better you understand encapsulation and how to use it effectively, the better your programs will be.

[edit] Service and Dispatch Pattern

Servlet-dispatch.png

All servlets follow the service and dispatch pattern, which is why they are called servlets. In a sense, every servlet application is an example of a service-oriented architecture on the internet. There are two key parts of the service pattern: the address of the service and the general server interface. For servlets, the address is the HTTP URL, and the interface is the servlet interface, where the HttpServletRequest and HttpServletResponse are the most important part. For the browser client on the internet, the address is the URL, and the interface is the HTTP protocol. The same service pattern is used for REST applications, where the address is the URL again, and the interface is often a JSON-encoded HTTP response. All of these use the same basic service pattern.

  1. address of the service (examples: the URL is the address for most internet applications)
  2. interface of the service (examples: the servlet request/response, or HTTP, or a custom Java interface, or JSON/REST)

Following the general encapsulation pattern, the service pattern has two characters or actors, the dispatcher and the service each of which knows as little as possible about the other. For this hello tutorial, the service is hello servlet itself and it focuses on implementing the hello service. The dispatcher is the Resin servlet engine. The hello servlet knows about writing "hello", but does not know or care how the dispatching works. Most importantly, the service does not know or care about any other services in the system; it is isolated from them. The Resin servlet engine knows how to take the URL address and dispatch to the hello servlet, but does not know or care how the servlet processes the servlet. The dispatcher knows all the services and their addresses, but doesn't know what they do. The dispatcher and service characters only need to know about the common interface, which acts like a contract.

  1. service implementation (examples: servlet, REST service, bean in a dependency-injection system)
  2. dispatcher (examples: servlet engine, CDI engine for JavaEE standard dependency-injection)

The service and dispatch pattern has two phases: a registration phase where the service tells the dispatcher its address, and a dispatch phase where the dispatcher sends a request to the service. In the servlet tutorial, the @WebServlet is the key to the registration phase. When the servlet container starts, it looks for all classes with a @WebServlet annotation. For each one that it finds, it registers the URL with the dispatcher. When a new request comes in, it will use the URL to dispatch to the servlet. The dispatcher essentially works like a post office or a phone service. When you move to a new house, or get a phone, you need to register your address or phone number with the post office or phone company. Once you're registered, you'll receive new messages automatically.

  1. the servlet registers with the dispatcher at a URL address
  2. the dispatcher sends matching requests to the servlet

[edit] registration of servlet with servlet container dispatcher

 @WebServlet("/hello")
 public class HelloServlet extends HttpServlet {

[edit] Interfaces and Abstract classes

The hello tutorial is a good example of using both interfaces and abstract classes. Interfaces are used to communicate between different code, for example the Servlet and HttpServletRequest and HttpServletResponse are used by the servlet container and the servlet to pass information back and forth. Abstract classes, like HttpServlet let implementations like the HelloServlet focus on the important behavior, leaving the standard shared code to the common code.

Abstract classes are good for managing upgrades and version changes when you use interfaces and abstract classes in your own code. When you add a new method to an interface, you can add a stub method to the abstract class, and your implementations do not need to change.

The following example is like the servlet API, where MyInterface is javax.servlet.Servlet and MyAbstract is HttpServlet, and MyImpl is HelloServlet.

[edit] MyInterface.java

 public interface MyInterface {
   public String hello();  // original method
 
   public String newHello(); // new method
 }

[edit] MyAbstract

 abstract public class MyAbstract implements MyInterface {
   abstract public String hello();  // original method

   public String newHello() { return "default-value"; }
 }

[edit] MyImpl.java

 public class MyImpl extends MyAbstract {
   public String hello() { return "hello, world"; }
 }

In general, it's a good idea when you use interfaces in your own code to also provide abstract classes to let you upgrade your application as you develop it.

[edit] Multithreading and Concurrency

To get the highest performance, servlets are multithreaded, which means multiple HTTP requests will run through your servlet at the same time. While multithreading is a huge topic, there are a few key concepts that can help understand the issue.

  1. data specific to a request is thread safe
  2. multithreading is only a problem for shared data.
  3. shared data needs to be protected or managed to be thread safe

In the servlet API, the HttpServletRequest and HttpServletResponse objects are specific to the request thread, so they are thread safe. Any local variables or objects you create for a thread will also be thread safe. The servlet class itself is shared, so it is not thread safe.

The following bad example shows a broken, unsafe servlet. Because multiple requests might run through the servlet at the same time, the _badSharedVariableXXX can get an incorrect value. For example, the first request 'A' might see an output "1" and the second request B might also see an output "1" and even though two requests came through, the counter was only incremented once.

[edit] Bad, non-thread safe code

public class BadServlet extends HttpServlet {

   private int _badSharedCounterXXX;
 
   public void doGet (HttpServletRequest req,
                               HttpServletResponse res)
     throws ServletException, IOException
   {
     PrintWriter out = res.getWriter();

     int badValue = _badSharedCounterXXX++;
 
     out.println("Bad counter: " + badValue);
   }

How do you manage the multithreading problem? There's no simple answer, but here are some general things to keep in mind:

  • emphasize request-based data, except where necessary (like actual shared resources), and pass the current request state as arguments
  • know which data is shared and which is per-request
  • use frameworks that manage some of the multithreading, for example JPA for persistence and JCache for caching and MVC frameworks
  • in some cases, use messaging systems like JMS to convert multithreaded problems into single-threaded queues

You should know that multithreading and concurrency is not as simple as using synchronized methods or ConcurrentXXX data structures like the ConcurrentHashMap.

[edit] Cookbooks and Tutorials

Personal tools
TOOLBOX
LANGUAGES