0

For the past few months, I've been trying to figure out how servlet mapping works (to no avail). I don't know what part of my brain is incapable of processing this concept, but I just can't seem to figure it out.

I've asked 4-5 similar questions, but all responses have been inconclusive...and I can't delete the posts.

I know that there are dozens, maybe hundreds of duplicates but I've looked through at least 30 of them and still cannot grasp the basic concept of servlet mapping. My directory structure is just TOO different.

Disclaimer: I'm using software from 10 years ago, against my will. The topics should still be (somewhat) relevant. I recently transitioned from Java SE7 to a much older version.

  • J2SE 1.4.2
  • Sun Application Server PE 8
  • Sun Deploytool
  • EJB 2.1

Error:

HTTP Status 404 - /send_message

type Status report

message /send_message

description The requested resource (/send_message) is not available.

Sun-Java-System/Application-Server


Application structure:

├───SendMail_app
    │   index.jsp
    │   SendMailApp.ear
    │
    └───sendmail
            SendMail.class
            SendMail.java
            SendMailBean.class
            SendMailBean.java
            SendMailHome.class
            SendMailHome.java
            SendMailServlet.class
            SendMailServlet.java

Note: My instructor noted that the older versions of Java don't require META-INF, or WEB-INF to be in the directory structure explicitly. It wasn't my hapless decision. Supposedly this was the norm in 2005.


application.xml

<?xml version='1.0' encoding='UTF-8'?>

    http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">        Application description    SendMailApp                   ejb-jar-ic.jar                                           war-ic.war                sendmail                       

web.xml

<?xml version='1.0' encoding='UTF-8'?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>WebApp</display-name>
    <servlet>
        <display-name>SendMailServlet</display-name>
        <servlet-name>SendMailServlet</servlet-name>
        <servlet-class>sendmail.SendMailServlet</servlet-class>
    </servlet>
    <servlet>
        <display-name>index</display-name>
        <servlet-name>index</servlet-name>
        <jsp-file>/index.jsp</jsp-file>
    </servlet>
    <servlet-mapping>
        <servlet-name>SendMailServlet</servlet-name>
        <url-pattern>/send_message</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>index</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>
</web-app>

sun-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
<sun-web-app>
    <context-root>sendmail</context-root>
    <session-config>
        <session-manager persistence-type="memory">
            <manager-properties/>
            <store-properties/>
        </session-manager>
        <session-properties/>
            <cookie-properties/>
        </session-config>
        <cache enabled="true" max-entries="4096" timeout-in-seconds="30">
            <default-helper/>
        </cache>
        <class-loader delegate="true"/>
        <jsp-config/>
        <parameter-encoding default-charset="UTF8"/>
</sun-web-app>

**EAR file: C:\ejb_apps\SendMail_app\SendMailApp.ear EAR Display Name: SendMailApp

├───META-INF
    │   application.xml
    │   sun-application.xml
    |   sun-j2ee-ri.project
    │
    └───ejb-jar-ic.jar
    |___war-ic.war

war-ic.war WAR Display Name: WebApp Context Root: sendmail

├───WEB-INF
|    │   classes
|    │      |____sendmail
|    |----lib
|    |----tags
|    |----wsdl
|    │----sun-j2ee-ri.project
|    |----sun-web.xml
|    |----web.xml
|
|____index.jsp

ejb-jar-ic.jar JAR Display Name: SendMailJAR

├───META-INF
|    |----wsdl
|    |----ejb-jar.xml
|    |----sun-ejb-jar.xml
|    │----sun-j2ee-ri.project
|
|____sendmail
       |----SendMail.class
       |----SendMailBean.class
       |----SendMailHome.class

Index.jsp

<%@ page import="sendmail.*" %>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>Hermod</title>
        <link rel="stylesheet" href="master.css"/>
    </head>

    <body>
        <section id="sendmail_form">
            <form method="post" action="/sendmail/send_message">
                <label>From</label><input type="email" name="from" size="32" maxlength="256"/><br>
                <label>To</label><input type="email" name="from" size="32" maxlength="256"/><br>
                <label>CC</label><input type="email" name="cc" size="32"/><br>
                <label>BCC</label><input type="email" name="bcc" size="32"/><br>
                <label>Subject</label><input type="text" name="subject" size="32" maxlength="256"/><br>
                <label>Body</label><input type="text" name="body" size="32"/><br>

                <button id="submit" type="submit">Submit</button>
                <button id="clear" type="reset">Clear</button>
            </form> 
        </section>

        <section id="sendmail_result">
            <!--${requestScope.message_status}-->
        </section>
    </body>
</html>

SendMailServlet.java

package sendmail;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.ejb.CreateException;
import java.io.IOException;

 public class SendMailServlet extends HttpServlet {
    private ServletContext context = null;

    public SendMailServlet(){
        super();
    }

    public void init(ServletConfig config) throws ServletException {
        context = config.getServletContext();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {

        try {
            Context initial = new InitialContext();
            Object objref = initial.lookup("java:comp/env/ejb/SendMail");
            SendMailHome home = (SendMailHome)PortableRemoteObject.narrow(objref, SendMailHome.class);
            SendMail sendmail = home.create();

            String status = sendmail.send(request);

            request.setAttribute("message_status", "status");
            RequestDispatcher RD = context.getRequestDispatcher("/index");
            RD.forward(request, response);

        } catch (ServletException SE){
            //TODO: log exception
        } catch (IOException IOE){
            //TODO: log exception
        } catch (CreateException CE){
            //TODO: log exception
        } catch (NamingException NE){
            //TODO: log exception
        } finally {
            super.destroy();
        }
    }
}

Of course, the code is riddled with neophytic errors but semantically what I'm trying to do is there. It's wrong, but if you think of it abstractly it's not so bad.

*What's happening: *

  • I've tried dozens of incorrect servlet mappings to try to call SendMailServlet.java from index.jsp
  • They're horrifically, pathetically incorrect.

localhost:8080/sendmail

  • JSP loaded properly
  • On submit (to be forwarded to /send_message (i.e. sendmail.SendMailServlet)):

HTTP Status 404 - /send_message

type Status report

message /send_message

description The requested resource (/send_message) is not available.

Sun-Java-System/Application-Server

I'm not sure how to enumerate 2 months of failure, but I've tried ~40-50 different servlet mappings.

Where did I fail as a programmer?

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • In your browser can you try `localhost:8080/sendmail/send_message` – Arun P Johny Mar 04 '13 at 03:47
  • Looks like you need to implement the `doGet` in your servlet to handle GET requests. – Luiggi Mendoza Mar 04 '13 at 03:48
  • @ArunPJohny: HTTP Status 405 - HTTP method GET is not supported by this URL. I'm using POST in SendMailServlet. If I'm using POST to call the servlet from the JSP, do I need to implement GET on the servlet? That doesn't make sense... –  Mar 04 '13 at 03:48
  • 1
    ok since it is not throwing a `404`, it is safe to assume that the problem is your context-path – Arun P Johny Mar 04 '13 at 03:49
  • Can you use the browser developer tools to inspect the form action attribute – Arun P Johny Mar 04 '13 at 03:50
  • @ArunPJohny: I can download a copy of Firebug - I'm forced to develop under WinXP since the software I'm using is so old. The action is /send_message which maps to the SendMailServlet. I'll add pastebin links to the poorly formatted XML files. –  Mar 04 '13 at 03:52
  • If someone can edit the XML files to display, that would be incredible. It's a justification error. –  Mar 04 '13 at 03:52
  • 1
    that is the problem, it should be `/sendmail/send_message`. Can you change `${pageContext.request.contextPath}/send_mail` to `/sendmail/send_message` and try – Arun P Johny Mar 04 '13 at 03:56
  • Alright, so that loads the servlet via the JSP page. I'm working on sending the result from the EJB (which may not be feasible) to the servlet, to the JSP. –  Mar 04 '13 at 04:00
  • What part of *you need to implement the **`doGet`** in your servlet **to handle GET requests*** was unclear? – Luiggi Mendoza Mar 04 '13 at 04:02
  • @LuiggiMendoza: Calm down, doPost seems to be working. It's worked in the past for multiple projects. I know that my actions are unforgiveable, but Arun's suggestions seem to be working. –  Mar 04 '13 at 04:04
  • When you access directly to the servlet URL mapping it will fire a GET request (and you aren't handling it, getting the 404 error). – Luiggi Mendoza Mar 04 '13 at 04:06
  • @TylerJFisher is the solution working – Arun P Johny Mar 04 '13 at 04:07
  • @LuiggiMendoza: is it possible to access a servlet via POST? I'm not sure how previous examples have used POST. I'm not trying to be a fool, but it's worked before. I just don't want to pass request parameters in the URL string for the world to see. –  Mar 04 '13 at 04:09
  • @ArunPJohny: I'm not sure. Working on it. I'll return a bogus result to see if the JSP mappings are correct. One second. –  Mar 04 '13 at 04:10
  • @LuiggiMendoza: thank you for formatting the XML. I'll try GET, will post results. –  Mar 04 '13 at 04:11
  • Yes, you can access to the servlet via POST when submitting the form having `method="POST"`. – Luiggi Mendoza Mar 04 '13 at 04:12
  • 1
    mine is not a solution, it was a step to figure out what is wrong. – Arun P Johny Mar 04 '13 at 04:13
  • @LuiggiMendoza: I've been using `method="POST"` (not GET). –  Mar 04 '13 at 04:14
  • if you are working with a IDE why don't you put a break point in the servlet? – Arun P Johny Mar 04 '13 at 04:15
  • your servlet mapping seems to be fine since your are getting a 405 on `GET` requests, which means if you can send a `POST` request to the same URL it should work – Arun P Johny Mar 04 '13 at 04:16
  • @ArunPJohny: I'm not permitted to use IDEs for this class. I'm getting somewhere though with Marco's suggestion. I'm getting a `NamingException` somewhere. –  Mar 04 '13 at 04:18
  • @TylerJFisher not permitted for what – Arun P Johny Mar 04 '13 at 04:20
  • @ArunPJohny: Revised. Sorry, I hit enter too soon. –  Mar 04 '13 at 04:20
  • Check my answer, sorry for all the other boilerplate in comments. – Luiggi Mendoza Mar 04 '13 at 04:20
  • 3
    Please, **please** don't update your question code with the code proposed in answers, otherwise future readers won't understand what was the problem and how to solve it! – Luiggi Mendoza Mar 04 '13 at 04:30
  • @LuiggiMendoza: very true - point taken. I'm trying to find the root cause of the NamingException right now. Returning a dummy value from the EJB for the time being. –  Mar 04 '13 at 04:31
  • 1
    By the way, if you still have *problems* with this, try to clean and rebuild your project, re deploy it in your web application server, and depending on the browser you use (i.e. IE), **clear the browser history** and try again. – Luiggi Mendoza Mar 04 '13 at 04:34

3 Answers3

1

So far as I see your web.xml is correct. You're looking probably at the wrong place.

Change all those catches for a single one catching a less specialized exception(Exception e) and re-throw the exception with throw new RuntimeException(e); Try to never ignore exceptions. If you don't have anything to do to rescue, then just wrap it in a RuntimeException and throw it again.

IPlanet is a nightmare, and probably you're having an error when you try to lookup this EJB, but as you are ignoring the exceptions you haven't been able to see it so far. JNDI lookup is always a bizarre source of stupid errors.

And please, also don't call destroy also as it's not needed and because Servlet Instances are meant to be reused. destroy was meant to be called by the container, not the user. It's only there so you could override it in your server if you had some kind of resource that needed to be properly disposed of whenever the server wanted to dispose of your Servlet. But it's not for you too call it. And even overriding it is rarely necessary.

  • +1 for warning on destroy(). Also, the decision to `throw new RunTimeException("foobar");` has worked tremendously. Thank you. Your suggestion resolved part II of the problem. –  Mar 04 '13 at 04:47
  • 1
    Yep. Just one more thing. Intead of passing a random string to RuntimeException, you'd better pass the originating exception. Then your stack trace will have something like Caused by... your original exception at line XXXXXX – Marcos Eliziário Santos Mar 07 '13 at 03:06
0

In your web.xml I didn't find any mapping for send_mail and there is only one servlet configuration available for URL pattern /send_message, so please verify you configuration.

Also I think in your jsp you should replace:

action="${pageContext.request.contextPath}/send_mail"

with:

action="/send_mail"

i.e. remove the context path: /send_mail, otherwise will be converted into localhost:8080/sendmail/send_mail as request URL.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Abhishek Kumar
  • 229
  • 1
  • 5
  • Ah, Arun P. Johny suggested that I revise a mapping. See `index.jsp` for revised JNDI lookup string. –  Mar 04 '13 at 04:15
  • 1
    The `${pageContext.request.contextPath}` will work only if OP configures JSTL (that I don't see anywhere). Also, your solution won't work if `index.jsp` is in a different folder than root web folder. – Luiggi Mendoza Mar 04 '13 at 04:16
0

Found the culprit. You're trying to forward to /index when you should forward to index.jsp in your servlet doPost

//wrong line
//RequestDispatcher RD = context.getRequestDispatcher("/index");
//solved!
RequestDispatcher RD = context.getRequestDispatcher("index.jsp");

Also, follow Marcos Eliziário Santos suggestion about the super.destroy() usage, just remove it form your code.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • I've followed Marcos Eliziário Santos suggestion on removing `super.destroy()`. I'm updating the code in the OP since it's changed. –  Mar 04 '13 at 04:23
  • 1
    @TylerJFisher do not do that. If you do, then Marcos' answer will be invalid. Let the errors in your actual code stay. – Luiggi Mendoza Mar 04 '13 at 04:25
  • Oddly enough, I reverted back to `RequestDispatcher RD = context.getRequestDispatcher("/index");` and the JSP loaded successfully. Thank you for your assistance. –  Mar 04 '13 at 04:43
  • Maybe you're using the war that contains this change. – Luiggi Mendoza Mar 04 '13 at 04:48
  • Maybe. `index.jsp` also has a URL pattern of `/index` in `web.xml`. Needless to say, I'm baffled. –  Mar 04 '13 at 04:50