Java servlets - navigate to page - java

I have the following project structure:
I am trying to navigate to concerts.jsp from index.jsp:
index.jsp
<li class="active">Concerts</li>
This is my ConcertsController:
#WebServlet("/ConcertsController")
public class ConcertsController extends HttpServlet {
private static final long serialVersionUID = 1L;
public ConcertsController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
request.getRequestDispatcher("/WEB-INF/pages/concerts.jsp").forward(request, response);
}
...
}
When I run the app, and click on the link in index.jsp, localhost:8080/ConcertsController URL opens and I get the
The requested resource is not available
error.
Edit 1: I am using Tomcat v7.0, servlets v3.0 and Java 8.
Edit 2 (possible duplicate): Well, surely I need to be able to do this without using the jstl library.
Edit 3: When localhost:8080/ConcertsController opens, I get the "resource not found" error. But when I manually edit the url to localhost:8080/AppName/ConcertsController, it works.

URL localhost:8080/ConcertsController means Application name is ConcertsController, port number is 8080 and the application is run locally. But you do not have ConcertsController Application.
so you are getting error
The requested resource is not available
There are 2 solutions
if you are not using JSTL.
Change <a href="/ConcertsController"> to <a href="<%${pageContext.request.contextPath}%>/ConcertsController">
If JSTL is used then <c:set var="contextPath" value="${pageContext.request.contextPath}" />
and then
change <a href="/ConcertsController"> to <a href="${contextPath}/ConcertsController">

Use
<a href="${pageContext.request.contextPath}/ConcertsController">
Also when forwarding the request to cencerts.jsp use ServletContext.getRequestDispatcher(....)
ServletRequest.getRequestDispatcher() method will evaluate the path relative to the path of the request. But for the method of ServletContext, the path parameter cannot be relative and must start with /( / means at the root of web application not current relative path).

Try using the following:
request.getRequestDispatcher("/pages/concerts.jsp").forward(request, response);
instead of:
request.getRequestDispatcher("/WEB-INF/pages/concerts.jsp").forward(request, response);

Related

Difference between sendRedirect(test.jsp) and sendRedirect(/test.jsp)

I want to pay attention to / used in redirect.
Forward slash at the beginning means "relative to the root of this web
container - Head First JSP and Servlets
I thought I understand it, until I tried it out. I will put super simple code for demonstration:
Starts with index.html:
<html><body>
<form action="GenericServlet" method="POST">
Enter name: <input type="text" name="name">
<button>Submit name</button>
</form>
</body></html>
Then it goes to GenericServlet.class:
#WebServlet("/GenericServlet")
public class GenericServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("test.jsp");
}
}
, which redirects to test.jsp:
<html><body>
hellooooo
</body></html>
After I run it, I get hellooo message. But once I change redirect to /test.jsp instead of test.jsp, I get not found error.
I also noticed when I use redirect(test.jsp), I get this http://localhost:8080/testProject/index.html
.But, when I use redirect(/test.jsp), I get this: http://localhost:8080/test.jsp
If Head First told me that / stands for root, why am I not getting same URL as in first case? Root = testProject, right? Can anyone spot what am I saying wrongly?
Root = testProject? NO!
The root path is the doman part without any path,which is http://localhost:8080 in you context.
For example, suppose the current request url is http://localhost:8080/a/b, if you call resp.sendRedirect("c");, the next request url is http://localhost:8080/a/c. If you call resp.sendRedirect("/c");, the next request url will be http://localhost:8080/c.

Accessing JSP in subfolder within WEB-INF folder?

I just started working with JSPs and came across one problem.
As I understand, JSP pages under WEB-INF can be accessed via a browser with the URL in localhost:
localhost:8080/MyProject/MyJSP.jsp
However, if I create another sub-folder within the WEB-INF folder (i.e. 'MyFolder') and try to access the same JSP page through the URL:
localhost:8080/MyProject/MyFolder/MyJSP.jsp
it gives an Error 404 instead. Are JSP file navigation systems treated differently to, say, HTML file navigation system?
EDIT: I am using servlets to display my JSP page as such:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("MyJSP.jsp");
}
EDIT2: I've changed my redirect to a requestDispatcher as I've been advised to do:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/MyFolder/MyJSP.jsp");
dispatcher.forward(request, response);
}
If my #WebServlet is ("/myjsp"), can anyone still access my MyJSP.jsp page if they type localhost:8080/MyProject/myjsp?
As I understand, JSP pages under WEB-INF can be accessed via a browser with the URL in localhost
No. It's exactly the reverse. Everything under WEB-INF is not accessible by the browser.
It's a good practice to put them there precisely because you never want anyone to access a JSP from the browser directly. JSPs are views, and requests should go through a controller first, which then dispatches (i.e. forwards, not redirects, see RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()) to the right view.
'/WEB-INF/' is considered to be a protected/secured folder and it is not advisable to make it accessible unless really required. If you still want to make these files available, try adding the below servlet mapping in your web.xml. Hope it helps
<servlet>
<servlet-name>MyJSP</servlet-name>
<jsp-file>/WEB-INF/MyFolder/*</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>MyJSP</servlet-name>
<url-pattern>/ViewMyJsp.jsp</url-pattern>
</servlet-mapping>
You can specify the mapping explicitly by declaring it with a element in the deployment descriptor. Instead of a <servlet-class> element, you specify a <jsp-file> element with the path to the JSP file from the WAR root.

Java - NullPointerException for Enum.values() in WAR archive

I've got an Enum class that stores the name and some relevant numbers for 10 different materials.
In my HTML page I want to select one material via a drop down. Therefore I iterate over them via JSTL. I used to have a scriplet for that but I replaced it now. This is my code:
Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
if (session.getAttribute("materialArray") == null) {
session.setAttribute("materialArray", Material.values());
}
request.getRequestDispatcher("/jsp/input.jsp").forward(request, response);
}
JSP-Page:
{...}
<h2>
<fmt:message key="input.label.material" />
</h2>
<select name="s_material" id="s_material">
<c:set var="MaterialEnum" value="${materialArray}" />
<c:forEach items="${MaterialEnum}" var="material">
<option value="${material}"><c:out
value="${material.description}"></c:out></option>
</c:forEach>
</select>
{...}
Problem: When I click 'Run project on server' in eclipse and visit the URL in Chrome it works fine.
But when I export the project to a WAR file and deploy it on a server (same tomcat version, different machine) the drop down doesn't fill and I get a NullPointerException for Material.values(). Also when I look at it in the eclipse intern browser, the material drop down menu isn't filled. (I used System.out.println() in doGet() to check if it does anything, it only prints the materials when accessing the page via Chrome. In internal browser it simply prints nothing.)
Why? Is there a way to bypass these enum-methods .values() and .valueOf() (which I use later to process the selected value from the drop down)? Are there differences in when doGet() is called?
(The scriplet I used before worked in both environments.)

My url mapping is diverting my CSS pages

I am working on a Dynamic Web Application with simple Java, Eclipse, and Tomcat 7.
Until I made the below changes, everything worked perfectly.
I recently added a home page Servlet Home.java and home page jsp Home.jsp and mapped the servlet to the URL / in the web.xml like
<servlet>
<display-name>Home</display-name>
<servlet-name>Home</servlet-name>
<servlet-class>my_proj.servlets.Home</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Home</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
The Servlet Home.java looks like:
public class Home extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("Servlet \"Home\" doGet working");
System.out.println("PathInfo: " + request.getRequestURL());
//If logged in, go to home page
request.getRequestDispatcher("/resources/jsp/home.jsp").forward(request, response);
//If not, go to login/register page
// TODO
}
}
And the Home.jsp is quite long, but everything is working except the resources like CSS, images, etc. They are not being loaded by the page. I am referencing them with
<link href="/my_proj/resources/css/custom.css" rel="stylesheet">
The Cause
Because of the code I put in the doGet method above, I can see that the requests to find the CSS page are actually ending up at the Home servlet. For instance this is part of what I see in the console
Servlet "Home" doGet working
PathInfo: http://localhost:8080/my_proj/resources/css/custom.css
So my question is, how to I properly map my pages so as to not to cause this confusion? Or how do I separate my CSS from relying on this mapping system? I don't want web.xml to handle the mapping to these files.
Please give your directory structure, for example If your directory structure like :
Project Name\WebContent\css then just add following line to include css on your page :
<link href="css/fileName.css" rel="stylesheet">
That's it, No need to provide full path : like Project Name\WebContent\css\fileName.css
<link href="/css/fileName.css" rel="stylesheet">

sendRedirect() doens't work

I looked for a solution on this forum, but i didn't find anything that suits my problem.
I have a very simplce code
a jsp page
<html>
<body>
<jsp:include page="/servletName"/>
</body>
</html>
and a servlet
#WebServlet("/servletName")
public class reindirizzaController extends HttpServlet {
private static final long serialVersionUID = 1L;
public reindirizzaController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String redirectURL = "http://www.google.it";
response.sendRedirect(redirectURL);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
No redirect is done. I'm stuck in the jsp page and i get no error. I also tried to add return; after the response.
Since you are calling the servlet through Include, it does not make you redirect. It simply ignores.
From docs of include()
includes the content of a resource (servlet, JSP page, HTML file) in the response. In essence, this method enables programmatic server-side includes.
The ServletResponse object has its path elements and parameters remain unchanged from the caller's. The included servlet cannot change the response status code or set headers; any attempt to make a change is ignored.
First, it is bad practice to call a servlet from a jsp. As you are using #WebServlet("/servletName"), you can directly call it at http://host/context/servletName
If you really need to call it from a jsp, you must forward to the servlet instead of including it as Suresh Atta explained. So you should use :
<jsp:forward page="/servletName"/>
When you do a JSP include directive, you're essentially plopping the code you're including right on the page. In your example, you would be doing the sendRedirect in your JSP. Even if you got the redirect to work miraculously, you would get an error saying that your response has already been committed. This is because by the time your browser loads the JSP, it is already reading from the server's response. The server cannot send another response while it is already sending a response to your browser.
One way to approach this is instead of doing an include directive, create a form with your servlet path as the action. Something like:
<form name="someForm" action="/servletPath/servletName">
<!-- some stuff here if you want -->
</form>
And then in your body tag, have it submit the form on load:
<body onLoad="document.someForm.submit();">

Categories