I am an advanced beginner in
Java, but an utter beginner when it comes to deploying
servlets. I can get a simple doPost servlet to run on my local machine, but when I deploy the .war file to my real web domain, I always get the error message:
404 Not Found
The requested URL /natal/ClassA was not found on this server.
My initial suspicions were that the doPost action of my HTML form did not properly match the settings of my web.xml file, but I have tried so many combinations that I suspect that the problem is something else.
I am developing on NetBeans 6.9.1. I am using GlassFish Server 3 (not
Tomcat). My ISP says that I have the necessary permissions to run servlets on my web site. In creating this servlet class, the project-package-class structure is:
ProjectA -> PackageA -> ClassA
The form calling the servlet has HTML code:
***************************************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<form action="ClassA" method="post" name="TestA">
<input name="Button" type="submit" value="PleaseWork" /></form>
</body>
</html>
***************************************************************
though I have tried many different actions such as "PackageA/ClassA", "ProjectA/PackageA/ClassA", "./zapp/ClassA" (I want to put the servlet in a directory /zapp).
/natal has chmod permission 755
/natal/zapp has 755
/natal/testa.html has 644
/natal/zapp/ProjectA.war has 755
I have tried many variations of web.xml, but here is the default that GlassFish created for me (I had to explictly ask for its creation, it did not happen by default). I always kept servlet-name as ClassA, but have varied the URL-pattern (mostly) and servlet-class (occasionally).
**************************************************************
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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">
<servlet>
<servlet-name>ClassA</servlet-name>
<servlet-class>PackageA.ClassA</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ClassA</servlet-name>
<url-pattern>/ClassA</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
**************************************************************
The servlet code, which is created by default:
*************************************************************
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package PackageA;
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;
/**
*
* @author Josef Stern
*/
public class ClassA 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 */
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet ClassA</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet ClassA at " + request.getContextPath () + "</h1>");
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>
}
*************************************************************
When I re-create the .war file, I invoke the Run -> Clean and Build Main Project menu. I then ftp the ProjectA.war file to .../natal/zapp on my website. The HTML form, testA.html, resides in .../natal, and I want it to call the servlet in .../natal/zapp/ProjectA.war.
I know that the browser senses the presence of the .war file because when I enter this URL directly into the browser:
http://my-web-domain-reaching-to/natal/zapp/ProjectA.war
the browser wants to "open" it, and asks whether I want to open or save it, and what application I should use to open it.
I can get this servlet to run on my local machine if I directly enter this url in the browser:
http://localhost:8080/ProjectA/PackageA/ClassA
and have the web.xml settings:
<servlet>
<servlet-name>ClassA</servlet-name>
<servlet-class>PackageA.ClassA</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ClassA</servlet-name>
<url-pattern>/PackageA/ClassA</url-pattern>
</servlet-mapping>
Assuming that these web.xml settings are correct, I have tried form actions of
ClassA
PackageA/ClassA
ProjectA/PackageA/ClassA
./zapp/ClassA
./zapp/PackageA/ClassA
./zapp/ProjectA/PackageA/ClassA
on the web site, but all generate the same error message, though the messages reference different url's.
I am at my wit's end. The odds are that I am missing something fundamental, and I will be embarassed when I learn the solution. There is also a possibility that GlassFish is doing something non-standard (I have to explicitly create web.xml files, they do not happen automatically). I could still be missing the exact form action & web.xml settings that would work, but I have tried so many variations that I now doubt that this is the problem. If it is not a fundamental mistake on my part, my wild guess would be that NetBeans/GlassFish have not put their files in the expected directories on my machine.
I have checked around 50 relevant web pages, but none have helped me solve this. This forum seems the clearest and most helpful to in other issues that I have faced.
I would appreciate any information, suggestions, or debugging techniques. Thank you to all who reply.
Josef