1

I have a Controller Servlet that has to forward a request to a specific JSP. However, whenever I forward the request it loads the JSP but the URL in the browser does something quite strange.

For example:

Via index.jsp I click: <a href="/login" />

In the Controller I have a method

if(request.getPathInfo().equals("/login"){
  dispatcher = this.getServletContext().getRequestDispatcher("/login.jsp");
  dispatcher.forward(request, response);
}

The URL in the browser will say:

http://mywebsite.com/my_work/do/login

and not:

http://mywebsite.com/my_work/login.jsp

The login.jsp page will be shown, just the URL is wrong. This causes problems, as I have to include 2 x References to Javascript and CSS files in each JSP as the relative URL changes depending on if I accessed the page manually by typing http://mywebsite.com/my_work/login.jsp into the browser, or whether it was accessed via a forward from the Controller servlet.

My web.xml:

    <?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>Controller</servlet-name>
        <servlet-class>controller.Controller</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Controller</servlet-name>
        <url-pattern>/do/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <resource-ref>
        <res-ref-name>jdbc/LessonDatabase</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
</web-app>

Screenshot of the Servlet tab

Any help would be great. I've got everything to work, but I'm guessing that this is not correct!

It should be noted that this occurs for any forwarding.

monster
  • 1,762
  • 3
  • 20
  • 38

3 Answers3

4

It is because you are forwarding the request to your JSP.

if(request.getPathInfo().equals("/login"){
  dispatcher = this.getServletContext().getRequestDispatcher("/login.jsp");
  dispatcher.forward(request, response);
}

When you forward a request to the next JSP or Servlet it keeps on showing the URL pattern of the Servlet in browser's address bar from where you are forwarding.

If you want the URL to be changed, you should redirect it.

response.sendRedirect("YOUR_JSP");

Therefore, your code should be,

if(request.getPathInfo().equals("/login"){
  response.sendRedirect("/login.jsp");
}

NOTE

The difference between Forwarding a request (i.e. using RequestDispatcher) and redirecting the request (i.e. using sendRedirect) is that if you forward a request to next resource then your same request object is passed to the next resource, therefore all its attributes & parameters are sent to the next JSP or Servlet.

Instead if you redirect your request then the client (browser) is asked to send a new request to the next resource. Therefore all your previous parameters and attributes in the request are not accessible in the new request at next resource.

However the information (parameters & attributes) stored in session or context is not affected by redirecting the request.

gprathour
  • 14,813
  • 5
  • 66
  • 90
  • 1
    Great answer. Link for basic difference between redirect and request forward: http://www.javapractices.com/topic/TopicAction.do?Id=181 – Sid Dec 18 '14 at 11:13
  • @Sid Thanks for the link. I was kind of lazy enough to get a link in the answer. – gprathour Dec 18 '14 at 11:14
  • Thanks for the in-depth reply, it's really cleared it up for me! However, let's say I type: `www.mywebsite.com/myView.jsp` into the browser, in this case I get a **HTTP Status 500 error - javax.ServletException**. I'm assuming it's got something to do with the fact that the JSP creates a form from data in the session, if no session exists then it throws this error. Is this normal behaviour for JSP files? If it is normal, when working with PHP you can say (pseudocode) `if(session.is_null()) { redirect; }`, is there a comparable option in JSP? Thanks again! – monster Dec 18 '14 at 14:02
  • As noted in my answer you are opening yourself up to all kinds of issues by implementing redirect simply to fix path issue with static resources. The answer you have have accepted is the wrong way to solve the issue. Don't do it unless you fully understand the implications. – Alan Hay Dec 18 '14 at 14:21
  • @AlanHay Thanks for the reply. However, I have not implemented either answer as my lecturer has changed her mind and decided that the `dispatcher.forward` is fine even though it doesn't change the URL. She didn't realise that the URL was not meant to change with the `forward` method. Thanks again. – monster Dec 18 '14 at 15:03
1

Doing a redirect rather than forward (and dealing with the implications of that) is the completely wrong approach to fixing an issue with the way static resources are referenced.

Unless you understand the implications of doing a redirect then the best (and easiest) solution is to fix the way your static resources are referenced.

You can do this in a framework agnostic way as follows (although your framework may offer other means) by computing and setting the base path.

http://www.w3schools.com/tags/tag_base.asp

In the following, JS and CSS files will always be referenced relative to the root of the webapp regardless of the path of the current resource.

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!--
  To avoid scriptlets and use JSTL see: 
  http://stackoverflow.com/questions/6271075/how-to-get-the-base-url-from-jsp-request-object
-->
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()
            + "://"
            + request.getServerName()
            + ":"
            + (request.getServerPort() != 80
                    ? request.getServerPort()
                    : "") + path + "/";
%>


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ABC</title>

<base href="<%=basePath%>" />

<link href="css/styles.css" rel="stylesheet"
    media="screen" />

<script src="js/jquery-1.8.3.js"></script>

</head>
Alan Hay
  • 22,665
  • 4
  • 56
  • 110
  • Hi Alan, Appreciate the answer. However, I'm not allowed to use `<% %>` for this piece of work. But what you've said is great, and make sense and I'll be sure to implement it in future work. – monster Dec 18 '14 at 15:00
  • Yes, avoid scriptlets wherever possible. You can also do in JSTL. See update. – Alan Hay Dec 18 '14 at 15:03
0

Just make sure the address for the URL pattern exactly matches the pattern. **These patterns are case sensitive. Took me hours to figure out a similar issue. **