tags:

views:

124

answers:

3

I'm having trouble with loading css and images when I have a servlet forward to a JSP. Specifically, when I set my welcome-file to index.jsp, the css is being loaded and my images are being displayed. However, if I set my welcome-file to HomeServlet and forward control to index.jsp, the css is not being applied and my images are not being displayed.

My css file is in web/styles/default.css. My images are in web/images/.

I'm linking to my CSS like so:

<link href="styles/default.css" rel="stylesheet" type="text/css" />

I'm displaying my images as follows:

<img src="images/image1.png" alt="Image1" />

Anyone know what is going on?

Thanks for any help.

UPDATE:

I've added the structure of the application, as well as some other information that might help.

alt text

The header.jsp file is the file that contains the link tag for the CSS:

<link href="${pageContext.request.contextPath}/styles/default.css" rel="stylesheet" type="text/css" />

The HomeServlet is set as my welcome-file (web.xml):

<welcome-file-list>
    <welcome-file>HomeServlet</welcome-file>
</welcome-file-list>

The servlet is declared as followed in the web.xml:

<servlet>
    <servlet-name>HomeServlet</servlet-name>
    <servlet-class>com.brianblog.frontend.HomeServlet</servlet-class>
</servlet>

The servlet is mapped as follows (in web.xml):

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Thanks again.

UPDATE #2:

I found the problem finally - my servlet was mapped incorrectly. Apparently when setting a Servlet as your welcome-file it can't have a URL pattern of "\". Which I find sort of weird, because wouldn't that stand for the root directory of the site?...

The new mapping is as follows:

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
+1  A: 

You must analyse the actual HTML output, for the hint.

By giving the path like this means "from current location", on the other hand if you start with a / that would mean "from the context".

Adeel Ansari
I'm unsure of what you mean. If I change the css link to this:
Brian D.
I mean you can view the HTML source from your browser, to find out if the path is right or not. If it is not, what should you need to do in order to make it correct.
Adeel Ansari
I've been viewing the source, and what comes up for my link tags is what I posted in my question. I guess I'm unsure of why if I link directly to my jsp, that the files can be found, and if I do a forward, they can't be found? Where can I store my images so they can be found from any location in the web app?
Brian D.
Okay, it is because your `index.jsp` is on the same location/level as your `styles` and `images` directories are. Therefore, when you directly use `index.jsp` as a welcome file, everything appears like charm. On the other hand, when you forward the same resource through the servlet, the matter is not the same anymore. [to be continued...]
Adeel Ansari
@Brian D.: ...To direct a request to a particular servlet we don't consider the path, we use servlet mapping. Now, we must understand the `context path` here. As you have seen in the docs that `/` has some specific meaning when used in the path we want to forward the request, or redirect the request. Without the slash it will be taken from the current location, not from the context path. I hope you are getting me now.
Adeel Ansari
A: 

Your welcome page is set as That Servlet . So all css , images path should be given relative to that servlet DIR . which is a bad idea ! why do you need the servlet as a home page ? set .jsp as index page and redirect to any page from there ?

are you trying to populate any fields from db is that why you are using servlet ?

kantu
Using a servlet as (MVC) front controller is *certainly not* a bad idea.
BalusC
+2  A: 

All relative URL's inside the JSP page are relative to the current request URL (the URL as you see in the browser address bar) and not to the location of the forwarded JSP page as you seem to expect.

Apart from changing the relative URL's to make them relative to the URL of the servlet instead of the JSP, another way to fix this problem is to make them relative to the domain root (i.e. start with a /). This way you don't need to worry about changing the relative paths once again when you change the URL of the servlet.

<link rel="stylesheet" href="/context/css/default.css">
<script src="/context/js/default.js"></script>
<img src="/context/img/logo.png">

However, you would probably like not to hardcode the context path. Very reasonable. You can obtain the context path in EL by ${pageContext.request.contextPath}.

<link rel="stylesheet" href="${pageContext.request.contextPath}/css/default.css">
<script src="${pageContext.request.contextPath}/js/default.js"></script>
<img src="${pageContext.request.contextPath}/img/logo.png">

This is in turn pretty cumbersome if you have a lot of relative URL's. For that you can use the <base> tag. All relative URL's will instantly become relative to it. It has however to start with the scheme (http://, https://, etc). There's no neat way to obtain the base context path in plain EL, so we need a little help of JSTL here.

<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"  %>
...
<base href="${fn:replace(pageContext.request.requestURL, pageContext.request.requestURI, '')}${pageContext.request.contextPath}/">
<link rel="stylesheet" href="css/default.css">
<script src="js/default.js"></script>
<img src="img/logo.png">

This has in turn (again) some caveats. Anchors (the #identifier URL's) will become relative to the base path as well! You would like to make it relative to the request URL (URI) instead. So, change like

<a href="#identifier">jump</a>

to

<a href="${pageContext.request.requestURI}#identifier">jump</a>

Each way has its own pros and cons. It's up to you which to choose. At least, you should now understand how this problem is caused and how to solve it :)

See also:

BalusC
I was really hoping that this would work as it makes sense, but the browser still can't locate the files. I've added some more information to my question (app structure, and some other general info). Thanks for the help!
Brian D.
You've mapped the servlet on `/` (smell, smell ;) ). So it also intercepts on CSS files (every HTTP request in fact). Is it handling them correctly? I.e. you are able to access the CSS file directly in webbrowser by http://localhost:8080/context/styles/default.css ?
BalusC
Not when it was mapped to "/". I can when it is mapped as "/HomeServlet" though.
Brian D.
I am not sure why you initially mapped it on `/*`, but if you're trying to create kind of a front controller, I'd suggest to get yourself through [this answer](http://stackoverflow.com/questions/3541077/design-patterns-web-based-applications/3542297#3542297) and maybe also [this answer](http://stackoverflow.com/questions/870150/how-to-access-static-resources-when-using-default-servlet/3593513#3593513).
BalusC