Tuesday, December 17, 2013

How to create or invoke a java servlet in Eclipse IDE using servlet 3.0 specification in a dynamic Java Web Project


I am creating a post for java users who are getting introduced to Java servlets and would like to use an Eclipse IDE environment to write a servlet. This small tutorial hopes to provide step by step instructions, so that users can avoid the pain points they usually experience while attempting to invoke a servlet from a html/Java server page landing page.

This simple example provided below is developed in Eclipse IDE and the example i am referencing is from O'reilly Heads first Servlets and JSP book. - Chapter 3.

For this sample, I have used
  •  Eclipse Java EE IDE for Web Developers Version: Juno Service release one. Eclipse is installed under c:\eclipse.
  • In addition, I have installed Apache Web server with tomcat container 7.0.25 release. Apache/Tomcat is installed under c:\tomcat directory.

1. First of, in order to incorporate Tomcat server instance as a web server/ servlet container into your Eclipse IDE for testing your java applications, here is a good tutorial link.
http://www.eclipse.org/webtools/jst/components/ws/M4/tutorials/InstallTomcat.html

2. Next, we will create a dynamic Java Web Project to build our sample application.
In order to create this web project in Eclipse IDE, we have to first enable/activate the Java EE perspective.To activate the perspective in Eclipse IDE, go to Window-->Open Perspective-->Other and choose Java EE (default)  perspective.

3. Next, we will create a new Java Web project in Eclipse IDE. Choose "File" menu-->New-->Dynamic Web Project. Give your project a name - "MyServlet" is the project name in this example. Select dynamic web module = 3.0 and Apache Tomcat 7.0 as the target run time environment.

4. Click Next and select default values. Make sure build\classes is the default value for "Default output folder".
5. Click Next and select the generate web.xml deployment descriptor check box. this deployment descriptor will get created in the projects' WEB-INF folder.
6.Click Finish to complete creation of the dynamic java web project.
7. Before we add our servlet code and insert the servlet mappings, here is an important difference to note between Servlet specification 2.5 to servlet specification 3.0.

  • The servlet mappings and servlets xml tags must be used when using servlet 2.5 specification in the web.xml deployment descriptor to provide the association of servlet-url to servlet name and servlet-name to servlet class. 

  • With servlet 3.0 specification, you can instead use annotations to perform the servlet to url-mapping inside of a servlet java file. 

You can check which specification your dynamic web application is using by taking a look at point #3 step above. In this example, we created the dynamic java web application project with dynamic web module version 3.0.

An annotation is written in the following format and written in the servlet's .java file.
@WebServlet("/Beer.do")
public class Hello extends HttpServlet {}

Therefore if you are using Servlets3.0 then the servlets will be configured by @WebServlet annotation.
Therefore, there is no need for web.xml configuration to add servlet and servlet-mapping tags.

8. Using the Eclipse IDE, in the Java EE perspective, you will first create a servlet. You can right click on either servlets or servlet mapping under Deployment Descriptor of your project and create a new servlet.  The wizard will automatically create you servlet and servlet-mapping when we create the servlet. We have used the package - com.example.web under which will create the servlet.

 
In this example, we have added Servlet mapping - Servlet name=Beer to Servlet url pattern /Beer.do and Servlet name=Beer to servlet class com.example.web.BeerSelect (points to compiled BeerSelect.class file of source file BeerSelect.java). I will explain adding the servlet file later below.

Sometimes, you may be surprised to see why Eclipse doesn't update web.xml file automatically when you create servlets and servletmapping in a Eclipse IDE environment, Most likely, it is because you  created the dynamic web project using web module version 3.0 (Check point #3 above) . Instead it added annotations to your servlet's java code (see example servlet code below).

9. In case you are comfortable in using servlet and servlet-mapping inside of a web.xml deployment descriptor vs annotations directly inside of that servlet's .java file,  you will need to revert/change your dynamic web module from 3.0 to 2.5.

Note:- You may not be able to directly revert to 2.5 web module from the Project's properties -->Project Facets and change dynamic web module from 3.0 to 2.5 because it will complain about Java 1.5 dependency.

10. (Optional step - in case you prefer to use servlet specification 2.5).
The workaround is to make the changes inside of "org.eclipse.wst.common.project.facet.core.xml" which is viewable inside of .settings folder of the project. In order to view the .settings folder, change to Navigator view (Window-->Show View-->Navigator) in your Eclipse IDE.
Make sure to change java version from 1.7 to 1.5 and web module from 3.0 to 2.5 and save the settings.

The same annotation in orange highlight
@WebServlet("/Beer.do")
public class BeerSelect extends HttpServlet {}

is represented in the sample web.xml deployment descriptor below using servlet specification 2.5.
 


 The servlet and servlet-mapping lines replaced the simpler annotation format
@WebServlet(value="/Beer.do", name="BeerSelect")
public class BeerSelect extends HttpServlet {}

11. Your sample html landing page which calls the servlet  uses "/Beer.do" url-pattern the servlet mapping is shown below

Make sure the action value  does not have the back-slash "\" in front of Beer.do. Essentially the html page is telling to servlet to look in the relative path and not the absolute path for the servlet class.
The html page can be saved anywhere in the WebContent folder of the Eclipse project.
In case the form.html is located in a sub folder of WebContent the action value should be "../Beer.do". If the form.html is 2 level down sub folder of WebContent. the action value will be "../../Beer.do". You get the gist... the url path is relative path.
 

12. Now the most important point is the adding the servlet code 

package com.example.web;

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;

/**
 * Servlet implementation class BeerSelect

Annotation used below in the example.
 */
@WebServlet(value="/Beer.do", name="BeerSelect")
public class BeerSelect extends HttpServlet {

    private static final long serialVersionUID = 1L;
      
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BeerSelect() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("Beer Selection advice<br>");
        String c = request.getParameter("color");
        out.println("Got color:" + c);
    }

}



The servlet code has access to servlet's request and response object through the inherited overloaded doPost  method. This code just prints back the selection made by the web-user in the form.html using a PrintWriter object. The intention of this tutorial is not to explain the java code for the servlet but to help in understanding how servlets are invoked.
 
13. To make understanding of "structure" of java dynamic web project used in this sample coded in Eclipse IDE, hopefully this screenshot below should prove helpful.





  • The landing page - form.html which calls the servlet BeerSelect with pattern "Beer.do" as the action value and "post" method is located in WebContent folder. In case, the form.html is located in a sub folder of WebContent the action value should be "../Beer.do". If the "form.html" is 2 sub directories below WebContent, the action value will be "../../Beer.do". You get the gist... the url path to calling the servlet is a relative path.
  • The web.xml deployment descriptor must in all cases be located under WebContent/WEB-INF folder. 
  • The servlet java file is located under package com.example.web and the package is first created under src directory and servlet java file is created under this package.

14. When the application is deployed and run in the eclipse IDE, the class file are generated in the build/classes folder.
To know where the tomcat instance executes under Eclipse IDE environment, you can take a look at Run Configurations (Arguments tab) to find the exact location of the application deployment. You can navigate here by right clicking on project name,select Run as-->Run Configurations.
The arguments tab should read something as shown below and the yellow highlights point to the tomcat deployment location.

-Dcatalina.base="C:\Users\dushyantg\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1" -Dcatalina.home="C:\tomcat" -Dwtp.deploy="C:\Users\foouser\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps" -Djava.endorsed.dirs="C:\tomcat\endorsed"

You can verify that the servlet class file exists under the <deployment path>\<PROJECT NAME>\WEB-INF\classes\<package name>\