This gist concerns AEROGEAR-732.
The problem was discovered by Sebastian how needed to use a path parameter for a view in AeroGear Controller. The view in question was simple jsp page that displayed information about a user which is part of an admin section of aerogear-controller-demo. The idea is that when logged in as an administrator you can register and manage users.
To access information about a user you follow a link, for example:
<div class="sixteen columns">
<table style="border: 1;border-color: gray; border-style: solid">
<c:forEach var="user" items="${arrayList}">
<tr><td><a href="show/${user.id}">${user.id}</a></td></tr>
</c:forEach>
</table>
</div>
This is a list of users which are links. So if you have a user named fletch the link would be show/fletch
. The Route for this looks like this:
route()
.from("/show/{id}").roles("admin")
.on(RequestMethod.GET)
.to(Admin.class).show(pathParam("id"));
So, by the mapping conventions in AeroGear Controller the view for this Route will be WEB-INF/Pages/Admin/show.jsp
.
Like the other jsp pages show.jsp includes a header.jsp and a footer.jsp like this:
<jsp:include page="../../template/header.jsp" />
When AeroGear Controller has routed to show.jsp the following error will be displayed in the browsers console:
GET http://localhost:8080/aerogear-controller-demo/show/stylesheets/base.css 404 (Not Found)
GET http://localhost:8080/aerogear-controller-demo/show/stylesheets/layout.css 404 (Not Found)
GET http://localhost:8080/aerogear-controller-demo/show/stylesheets/skeleton.css 404 (Not Found)
The above stylesheets are include in header.jsp:
<link rel="stylesheet" href="stylesheets/base.css">
<link rel="stylesheet" href="stylesheets/skeleton.css">
<link rel="stylesheet" href="stylesheets/layout.css">
Lets looks at the register.jsp page and see if we can spot a difference:
request.context_path=/aerogear-controller-demo
forward.request_uri=/aerogear-controller-demo/admin
forward.context_path=/aerogear-controller-demo
forward.servlet_path=/admin
forward.path_info=
forward.query_string=
include.request_uri=
include.context_path=
include.servlet_path=
include.path_info=
include.query_string=
And the same attributes when accessing show.jsp:
request.context_path=/aerogear-controller-demo
forward.request_uri=/aerogear-controller-demo/show/beve
forward.context_path=/aerogear-controller-demo
forward.servlet_path=/show/beve
forward.path_info=
forward.query_string=
include.request_uri=
include.context_path=
include.servlet_path=
include.path_info=
include.query_string=
Just to remind myself about the actual error, look at the path:
http://localhost:8080/aerogear-controller-demo/show/stylesheets/base.css
Compare this with the path for base.css from register.jsp:
http://localhost:8080/aerogear-controller-demo/stylesheets/base.css
If we take a look at the generated jsp page for header.jsp:
out.write("<link rel=\"stylesheet\" href=\"stylesheets/base.css\">\n");
So it is the browser that will determine try to resolve this relative to the current context.
Since the current page is http://localhost:8080/aerogear-controller-demo/show/beve
, the browser will look for stylesheets/base.css
in the same "directory": http://localhost:8080/aerogear-controller-demo/show/stylesheets/base.css
.
The reason that the other pages work is that they do now use path parameters, take http://localhost:8080/aerogear-controller-demo/admin
for example, when the browser tries to resolve the stylesheets it will try using path relative to the current "directory" which will be http://localhost:8080/aerogear-controller-demo/stylesheets/base.css
.
I think the proper way to handle this is indeed to add ${pageContext.request.contextPath}
to header.jsp:
<link rel="stylesheet" href="${pageContext.request.contextPath}/stylesheets/base.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/stylesheets/skeleton.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/stylesheets/layout.css">