Implementing your very first Java servlet using Eclipse WTP

First, we will explain how to implement servlets using Eclipse WTP, and then we will come around to implementing JSPs later. We will create a quite simple servlet that prints the classic phrase "Hello, World!". You will see that writing and deploying servlets using Eclipse WTP is a breeze. Certain aspects of developing web applications using Eclipse WTP are so easy that you may not need to type almost anything. So, if you are really serious about learning how to develop web applications using servlets and JSP, we recommend you to skim through this chapter just to get a feel of how to use WTP, and then take a break from Eclipse altogether and start arranging all the structure of your web applications by hand. That will help you to better understand how this sort of applications are organized and the number of steps Eclipse has graciously automated for you. After getting the gist of how to assemble, develop, and deploy web applications, you can go back to Eclipse in order to speed up the development process. We direct the interested readers to http://tomcat.apache.org/tomcat-7.0-doc/appdev/index.html for further information on web application development.

To develop servlets and JSPs using Eclipse WTP, first, we need to create a new dynamic web project: go to File | New | Other… | Web. In the New wizard, expand Web, and then select Dynamic Web Project. You should reach the wizard shown in the following screenshot.

If you take some time observing the items under the option Web, you will see that there are two types of web projects: dynamic and static. Dynamic web projects contain dynamic resources, such as servlets, JSPs, and a bunch of metadata, to name but a few items. Static web projects include only static resources, for instance, cascading stylesheets.

Tip

The Java conventions entail a lot of overhead; you have to comply with a directory structure that specifies the location of class paths, supporting metadata, and deployment descriptors. So, when you want to create a simple web application that has only static content, you might want to use the static web project type.

Implementing your very first Java servlet using Eclipse WTP

After selecting Dynamic Web Project, hit Next. Let's name our project chapter7.examples (type it in the Project name textfield). Some words about the New Dynamic Web Project wizard (shown in the following screenshot) are in order. First, as you can see in the following screenshot, it is possible to specify the server you want to use by selecting an option from the Target runtime drop-down list. Given that we installed Tomcat, it should be the default option. Second, as for the number under Dynamic web module version, it has to do with the servlet API version that will be used throughout the project. As of this writing, 3.0 is the latest version, and the one that we will use in this chapter. So, set this option to 3.0 before clicking on Next. Lastly, you can either leave the Configuration option set to <custom> or Default Configuration for Apache Tomcat v7.0.

Implementing your very first Java servlet using Eclipse WTP

The next window, named Configure project for building Java application (this window is not shown), can be used to add folders for your source on the build path. In this window, do not change anything, just accept the default value (src), and hit Next again.

Finally, the last window asks whether an application deployment description (web.xml) should be generated or not. Note that generating this XML file is not the default option. For the time being, we do not need such a file, so leave this option unselected.

Implementing your very first Java servlet using Eclipse WTP

Upon clicking on Finish, Eclipse will prompt you to change perspective. Dynamic web projects are associated with the Java EE perspective. To proceed, select Yes. You just created a new project that sports the structure of Java web applications. Note that you did not have to create a myriad of folders nor XML files. The next screenshot shows an overview of how dynamic web projects are organized. For the time being, the important parts for us are the folders, WebContent and Java Resources, which is where your servlet will go. WebContent comprises two subfolders: META-INF and WEB-INF. The latter is of particular importance here. WEB-INF contains the application deployment descriptor (web.xml, a file that contains configuration information) and subfolders for other sorts of resources, for instance, configuration files. It is important to mention that clients do not have access to the files under this folder, which makes it a safe place for files that are not meant to be publicly available. Inside WEB-INF there is a subfolder named lib, where you place JAR files. Class files that are not packaged in JAR files are placed into another folder named classes. However, it bears mentioning that you should not place any .class file into this directory. Instead, these files are placed there automatically when Eclipse's Java compiler translates Java source files that are in the Java Resources directory. When the compiler runs, it deletes all files placed directly in this directory.

Tip

Java files in the classes folder must be stored in a directory structure that mirrors their package structure. For instance, a class that belongs to a package named foo.bar must be stored in the WEB-INF/classes/foo/bar folder. When developing inside Eclipse, it takes care of most of these deployment-related issues for you. However, because this structure is common to most Java web applications, knowing where each file should be placed can help you to get your bearings when inspecting someone else's web application.

Implementing your very first Java servlet using Eclipse WTP

Eclipse has not created any servlet yet. To get Eclipse to create our first servlet, right-click on the folder WebContent, and navigate to New | Other… | Web | Servlet. Fill the blank fields out, as shown in the following screenshot:

Implementing your very first Java servlet using Eclipse WTP

You just named your servlet HelloWorldServlet and placed it within a package named chapter7.examples.servlets. The generated code is shown as follows. For brevity's sake, most of the generated comments are omitted:

package chapter7.examples.servlets;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/HelloWorldServlet")
public class HelloWorldServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
   public HelloWorldServlet() {
      super();
   }
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
   }
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
   }
}

We do not want you to type stuff into your computer mindlessly, so before modifying the generated code to suit our needs, let's go over some of the details of this piece of code. Servlet 3.0 API introduced a lot of new features. One of the new features is the introduction of annotations, which has made the XML file (web.xml) that is used to declare servlets—among other things—optional. These annotations reside in the package javax.servlet.annotation. Using them you can define metadata regarding a servlet by simply annotating it with @WebServlet. You use @WebServlet to let Tomcat know that the class in question is a servlet. @WebServlet can take a number of parameters, and metadata can be specified for the servlet using such parameters. In this example, /HelloWorldServlet represents the URL of the servlet.

Tip

The URL of the servlet can be seen as the name the client knows about. In other words, this is the name that appears in the HTML code accessed by the client—it is a made-up name for clients. It is up to the container to invoke the correct servlet based on the URL provided by the client.

Apart from @WebServlet, another characteristic that sort of gives the previous class away as being a servlet is that it extends javax.servlet.http.HttpServlet. The auto-generated code also provides stub implementations of the two methods that you will override most of the time when implementing servlets, namely, doGet and doPost. As you can see, both doGet and doPost methods take an instance of HttpServletRequest and HttpServletResponse. These instances provide the input and output streams, respectively, and are used to read and write client data, respectively.

When writing servlets, you will find yourself thinking about the implications of the operation your servlet needs to carry out. In other words, first you need to determine which HTTP-related method conforms to the purpose of the operations you are about to implement. GET and POST have different semantics. For instance, in HTML parlance, GET is a request for retrieving something at a given URL, while POST is used to send an arbitrary amount of data to the server. In addition, GET operations are idempotent: they can be executed more than once without causing any side effects on the server. POST operations, on the other hand, are not idempotent by definition. So, with that in mind, which HTTP-related method do you think we should override? Because HelloWorldServlet is only going to show us a message, we can see its implementation as if we were retrieving something: the Hello, World! message. Therefore, you guessed right if you thought about overriding doGet.

Go ahead and delete doPost or comment it out. You will not need it. While you are at it, you can also safely get rid of the auto-generated constructor. Once you have removed them, implement doGet as follows:

package chapter7.examples.servlets;
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;
@WebServlet("/HelloWorldServlet")
public class HelloWorldServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
   protected void doGet(HttpServletRequest request, HttpServletResponse response)   throws ServletException, IOException {
      response.setContentType("text/html");
      
      PrintWriter pw = response.getWriter();
      pw.println("<html><head><title>Warm Greeting</title></head>" +
      "<body>" +
          "<h1> Hello, World! </h1>" +
      "</body></html>"
      );
      pw.close();
   }
}

Before running your servlet, let's take a look at what you just typed inside doGet. First, you should keep in mind that we are overriding doGet to handle client requests. Within the context of this example, the GET requests to /HelloWorldServlet will be answered by an HTML document that prints the message Hello, World!. Initially, you need to indicate to the container that the data that is being sent back is an HTML document. To do so, you invoke the method of the HttpServletResponse object named setContentType. In this example, we set the content type to text/html. Information concerning the content type goes in the header of the HTTP response. Such information tells the client what to expect as result from the request. It is through this information that the client browser knows what to do next: render the HTML, launch a PDF viewer, save the returned data as a downloaded file, and so on.

Tip

When you invoke setContentType, you are setting the MIME type for the data returned by the servlet. Most of the time, the MIME type used by servlets is text/html. However, other MIME types might be used. For instance, a servlet that returns a PDF document should set the MIME type to application/pdf.

Through setContentType you can also specify the character encoding. Let's say we wanted the servlet container to set the character encoding to UTF-8, we would invoke setContentType as follows:

response.setContentType("text/html; charset=UTF-8");

Tip

From Java 5 onwards, you can also set the character encoding via the servlet response object's setCharacterEnconding method.

The next step is to fetch the output stream and write the desired HTML content to it. The servlet response object provides the output stream for sending data back to the client. To get the output stream, you need to invoke getWriter, which returns a PrintWriter instance. If you have already used java.io, then you are already familiar with PrintWriter. If you have not used java.io, here is a crash course on PrintWriter: it is designed to handle character data. When you need to return something else from your servlet, you will use an OuputStream instance. You can obtain an OuputStream instance by invoking getOutputStream on a response object as shown in the following snippet:

ServletOutputStream out = response.getOutputStream();

PrintWriter has a lot of methods; however, most of the time you will be using just println or print to print text data to the character stream. As shown in the previous example, in order to write HTML to the stream, you simply perform I/O operations. To be more specific, HTML is embedded into Java strings and sent to the output stream.

At this point you should be able to run the recently created servlet. Running our example inside Eclipse is quite straightforward. Select HelloWorldServlet, right-click on it, and then select Run on Server from Run As, as shown in the following screenshot:

Implementing your very first Java servlet using Eclipse WTP

Tip

It is worth mentioning that Eclipse also allows you to debug web applications. You can even set breakpoints within JSP files. So if you ever face any problem during development, it is good to know that you can resort to a step-by-step execution in order to uncover bugs.

A window listing the available servers will appear. Because we configured Tomcat previously, it should be included in this list (as shown in the following screenshot). After selecting Tomcat, click on Finish. You can check the option Always use this server when running this project, so that this dialog will not pop up whenever you run your application.

Implementing your very first Java servlet using Eclipse WTP

Upon pressing Finish, Eclipse will configure the example servlet on Tomcat. You should see the following message being displayed in Eclipse's internal browser. If you got this message, congratulations, you have just created your first servlet using Eclipse WTP:

Implementing your very first Java servlet using Eclipse WTP

We can make the message shown by this servlet more interesting. So far, there is nothing dynamic about it. Every time you run the example, you get the same message. In other words, it does not matter how many times you refresh Eclipse's internal browser, you will see the Hello, World! message. Let's add the current time to this message. To do so, modify the doGet method as shown in the following code. Note that whenever you need to change the HTML data that is sent back to the client you will have to change the HTML data that is embedded in your Java code:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   response.setContentType("text/html");
  
   java.util.Date currentTime = new java.util.Date();
   PrintWriter pw = response.getWriter();
   pw.println("<html><head><title>Warm Greeting</title></head>" +
      "<body>" +
          "<h1> Hello, World! </h1>" +
      "<ul> <li>current time: " + currentTime + "</li></ul>" +
      "</body></html>"
   );
   pw.close();
}

To see the new servlet at work, run it as described before. Upon running the previous code, you should see something similar to the following screenshot. Now, every time you hit Refresh, you get a brand new timestamp. This timestamp is obtained during runtime and dynamically added to the response:

Implementing your very first Java servlet using Eclipse WTP

A more elaborate example – yet another calculator

Now that you know the basics, let's move on to a more elaborate example. We are going to develop a simple calculator (by this time, you might have realized that one of the authors is a calculator buff). To keep things simple, our web calculator will be able to deal with only two operands at a time. After typing the value for each operand, the user will be able to select the operation that he or she wants the calculator to compute. The result of the operation will be shown in a new page.

Our example will comprise three classes, of which two are servlets and one is a plain Java class. The plain class implements our calculator itself, while the servlets are responsible for the presentation and the interplay between the presentation and the calculator class. Let's start small by implementing the first servlet, the one in which the user will type the value of the two operands. It bears mentioning that we could have implemented the same functionality using plain HTML, but we like to make things more interesting. Moreover, implementing this functionality as a servlet will give you another opportunity to put your recently acquired knowledge into practice. Okay, let's get down to business.

We are going to develop our calculator in a new project. So, first, create a new dynamic web project, and name it webcalculator (if you do not remember how to create a dynamic web project, go back to the beginning of the section in which we explain how to create servlets in Eclipse). Then, create a servlet named OperationSelect and place it in the package com.example.calculator.web. The next screenshot shows what you should type in the Create Servlet window. Remember that you do not need to create the package beforehand. Upon creating your servlet, Eclipse makes sure to create its associated package structure. Because our project comprises both servlets and plain Java classes, we will use a widely used convention to organize these elements. Servlets will be placed in the package com.example.calculator.web, while our calculator class will be placed in a package named com.example.calculator.model.

A more elaborate example – yet another calculator

Click on Next twice so that you can get to the following window. Then unselect the doPost option; we will not override this method for this servlet. While you are at it, also unselect the Constructors from superclass option; we do not need a constructor either. Lastly, hit Finish:

A more elaborate example – yet another calculator

Eclipse will generate a servlet containing an empty doGet method. Although the generated code does do much, we do not need to type everything from scratch now. Let's start changing our generated servlet by modifying the doGet method, as shown in the following code. Note that we are performing the same operations shown in the previous example. First, we set the content type to text/html. Second, we fetched the output stream in order to write our HTML content to the output.

As you can see, the more HTML you have to add to the output, the more unwieldy your code becomes. For the sake of simplicity, we did not use complex HTML constructs inside our example servlet. The first two elements are textfields, and the last one is a drop-down list from which the user can select the operation to be performed using the two operators. We also add a Submit button that will forward the operands and operation information to another servlet that, in turn, will trigger the execution of our calculator class:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   response.setContentType("text/html");
   PrintWriter pw = response.getWriter();
   pw.write("<html><body>");
   pw.write("<h1 allign="center">Web Calculator v1.0</h1>");
   pw.write("<form method="POST" action="PerformCalculation.do">");
   pw.write("<tt>1st operand:</tt> <input type="text"" +     "name="firstOperand"><br>");
   pw.write("<tt>2nd operand:</tt> <input type="text"" +  "name="secondOperand"><br>");
   pw.write("Operation to be performed: ");
   pw.write("<select name="operation" size="1">");
   pw.write("<option value="+"> + </option>");
   pw.write("<option value="-"> - </option>");
   pw.write("<option value="*"> * </option>");
   pw.write("<option value="/"> / </option>");
   pw.write("</select></br></br>");
   pw.write("<input type="submit" value="Submit">");
   pw.write("</form>");
   pw.write("</body></html>");
   pw.close();
}

Deploying the calculator example

After typing the previously shown method, we are ready to take the first part of our calculator example for a spin. In case you do not remember how to run web applications inside Eclipse, here is a quick reminder: select the desired program (in this case, OperationSelect), right-click on it, and then navigate to Run on Server in Run As. Select Tomcat from the list of available servers, and click on Finish. The next screenshot shows what you will see after executing this servlet:

Deploying the calculator example

We have not implemented the servlet responsible for forwarding the values and operation to the class that implements the calculator. Therefore, if you type two numbers in the 1st operand and 2nd operand fields, select an operation, and press Submit, you will get the page shown in the next screenshot. This indicates that the resource we are looking for was not found by the servlet container. So, let's take a step back and see why the servlet container is trying to forward the data to webcalculator/PerformCalculation.do.

The answer to this question boils down to the fact that our form is submitting information to something named PerformCalculation.do (take a look at the previous chunk of code). Further, given that there is no resource (servlet or HTML page, for instance) with such a name, the container shows an error message. In this example, PerformCalculation.do is a logical name. That is to say, it is no actual filename. We do not want the client to have access to the names of our servlet classes. So, we use made-up names that are mapped to actual servlets instead. That explains why we got an error page: we have not informed the container yet about which servlet answers by the logical name PerformCalculation.do.

Tip

The .do extension (which implies do something) is just a convention.

Deploying the calculator example

Implementing the second part of our example entails mapping a servlet to the aforementioned made-up name. Again, use Eclipse to generate the servlet for you. Name it ArithmeticExpert, and place it into the same package of the previous servlet (com.example.calculator.web). When creating ArithmeticExpert, and after going through the first window where you type the servlet's name and package, click on Next, and then click on Edit… as shown in the following screenshot. Here you can edit the servlet URL mapping. Given that we want to inform the container that the new servlet can be mapped to PerformCalculation.do, edit this option as shown in the following code snippet (make sure you do not start with a / character) and press Next:

Deploying the calculator example

Rather than overriding doGet, this time we will override doPost. Because the form in OperationSelect generates a POST operation, we have to override doPost. Otherwise, pressing the Submit button will not invoke our method. Therefore, unselect the doGet and Constructors from superclass options. Lastly, hit Finish. Change the generated code, as shown in the following snippet:

@WebServlet("/PerformCalculation.do")
public class ArithmeticExpert extends HttpServlet {
  private static final long serialVersionUID = 1L;
  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter pw = response.getWriter();
    pw.write("<html><body>");
    pw.write("The result of " +
   request.getParameter("firstOperand") + " " +
   request.getParameter("operation") + " " +
   request.getParameter("secondOperand") +
   " is surprise, surprise");
    pw.write("</body></html>");
    pw.close();
  }
}

We are implementing our calculator example in stages. In this first version, our goal is to make sure that the communication link between the first and second servlets is working properly. Therefore, our code does not invoke the calculator class to perform the selected operation. Instead, it will just print out a message indicating that the communication between both servlets is working and that we are able to share information between them. There are two important points to note in the preceding code. First, see how the mapping between the servlet and its made-up name, which appears in the output of OperationSelect, is implemented using the @WebServlet annotation. Note that the string enclosed in parentheses is the pattern we typed during the creation of the underlying servlet (check the previous screenshot). Second, note how we access the parameters from the request. We use the method getParameter from HttpServletRequest (actually, this method is defined in the interface ServletRequest, and implemented by subclasses including HttpServletRequest). Using getParameter, each parameter is retrieved by its name.

Tip

Parameter names are case sensitive.

Upon running the previous servlet and typing 2 in the 1st operand textfield, 1 in the 2nd operand textfield, selecting subtraction as the operation to be performed, and pressing Submit, you should see something like the next screenshot. As you can see in the following screenshot, now the application can access data entered by the user in one of the servlets to perform the calculations in the other servlet:

Deploying the calculator example

To finish the calculator example, we need to implement a calculator class that is able to perform the arithmetic operations shown in the first servlet. That should be straightforward for you now. Before checking our solution shown in the following snippet, try to write this class by yourself. Just make sure to name it Calculator, and place it into a package named com.example.calculator.model. The following is how we implemented Calculator:

package com.example.calculator.model;
public class Calculator {
  private double op1, op2;
  private String operation;
  public Calculator(String op1, String op2, String operation) {
    try {
      this.op1 = Double.parseDouble(op1);
      this.op2 = Double.parseDouble(op2);
      this.operation = operation;
    }
    catch (NumberFormatException e) {
      //reset the value of both operands
      this.op1 = 0.0;
      this.op2 = 0.0;
   }
 }
 public double performCalculation() {
   if (operation.equals("+")) {
     return op1 + op2;
   } else if (operation.equals("-")) {
     return op1 - op2;
   } else if (operation.equals("/")) {
     return op1 / op2;
   } else if (operation.equals("*")) {
     return op1 * op2;
   }
   return 0;	
 }

After implementing Calculator, you just need to integrate it to the ArithmeticExpert servlet, as shown in the following snippet. Note that our implementation does not deal with edge cases as division by zero. Upon executing the example again, you will see something similar to what is shown in the following screenshot:

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
   ServletException, IOException {
  response.setContentType("text/html");
  PrintWriter pw = response.getWriter();
  pw.write("<html><body>");
  String operandOne = request.getParameter("firstOperand");
  String operandTwo = request.getParameter("secondOperand");
  String operation = request.getParameter("operation");
  pw.write("The result of " +
   operandOne + " " +
   operation + " " +
   operandTwo +
   " is " +
   new Calculator(operandOne, operandTwo,
     operation).performCalculation());
pw.write("</body></html>");
pw.close();
}
Deploying the calculator example
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset