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.
Related
Can I call a servlet from JSP file without using a HTML form?
For example, to show results from database in a HTML table during page load.
You can use the doGet() method of the servlet to preprocess a request and forward the request to the JSP. Then just point the servlet URL instead of JSP URL in links and browser address bar.
E.g.
#WebServlet("/products")
public class ProductsServlet extends HttpServlet {
#EJB
private ProductService productService;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Product> products = productService.list();
request.setAttribute("products", products);
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
}
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
Note that the JSP file is placed inside /WEB-INF folder to prevent users from accessing it directly without calling the servlet.
Also note that #WebServlet is only available since Servlet 3.0 (Tomcat 7, etc), see also #WebServlet annotation with Tomcat 7. If you can't upgrade, or when you for some reason need to use a web.xml which is not compatible with Servlet 3.0, then you'd need to manually register the servlet the old fashioned way in web.xml as below instead of using the annotation:
<servlet>
<servlet-name>productsServlet</servlet-name>
<servlet-class>com.example.ProductsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>productsServlet</servlet-name>
<url-pattern>/products</url-pattern>
</servlet-mapping>
Once having properly registered the servlet by annotation or XML, now you can open it by http://localhost:8080/context/products where /context is the webapp's deployed context path and /products is the servlet's URL pattern. If you happen to have any HTML <form> inside it, then just let it POST to the current URL like so <form method="post"> and add a doPost() to the very same servlet to perform the postprocessing job. Continue the below links for more concrete examples on that.
See also
Our Servlets wiki page
doGet and doPost in Servlets
How to avoid Java code in JSP
Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
You will need to use RequestDispatcher's Methods forward/include depending on your requirement to achieve same.
In JSP you need to use following tags:
jsp:include :
The element allows you
to include either a static or dynamic
file in a JSP file. The results of
including static and dynamic files are
quite different. If the file is
static, its content is included in the
calling JSP file. If the file is
dynamic, it acts on a request and
sends back a result that is included
in the JSP page. When the include
action is finished, the JSP container
continues processing the remainder of
the JSP file.
e.g.
<jsp:include page="/HandlerServlet" flush="true">
jsp:forward :
The element forwards the
request object containing the client
request information from one JSP file
to another file. The target file can
be an HTML file, another JSP file, or
a servlet, as long as it is in the
same application context as the
forwarding JSP file. The lines in the
source JSP file after the
element are not
processed.
e.g.
<jsp:forward page="/servlet/ServletCallingJsp" />
Check Advanced JSP Sample : JSP-Servlet Communication:
http://www.oracle.com/technology/sample_code/tech/java/jsps/ojsp/jspservlet.html
Sure you can, simply include it in your action in the form. But you have to write the correct doPost or doGet to handle the request!
If you want to call a particular servlet method than you also use Expression Language. For example, you can do something like:
Servlet
ForexTest forexObject = new ForexTest();
request.setAttribute("forex", forexObject);
JSP
<body bgcolor="#D2E9FF">
Current date : ${forex.rate}
</body>
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">
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();">
This question already has answers here:
Calling a servlet from JSP file on page load
(4 answers)
Closed 6 years ago.
I have below servlet. I would like to call the servlet on jsp page load. How can I do that?
servlet: SomeServlet.java
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>SomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
How can I write corresponding jsp to invoke the servlet on jsp page load. Also I need to get the result from servlet and display in the same jsp. Can I send result back to jsp?
Thanks!
You should do it the other way round. Call the servlet by its URL and let it present the JSP. That's also the normal MVC approach (servlet is the controller and JSP is the view).
First put the JSP file in /WEB-INF folder so that the enduser can never "accidently" open it by directly entering its URL in browser address bar without invoking the servlet. Then change the servlet's doGet() accordingly that it forwards the request to the JSP.
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
}
Open it by
http://localhost:8080/contextname/HelloServlet
Note that you can of course change the URL pattern in servlet mapping to something like /hello so that you can use a more representative URL:
http://localhost:8080/contextname/hello
See also:
Our Servlets tag info page
<jsp:include page="/HelloWorld"/>
Call a servlet instead get result in request attribute and forward the request to jsp
or make an ajax call to servlet on load and render the response using javascript
In JSP paage you can forward the request to the Servlet
response.sendRedirect(request.getContextPath()+"/SomeServlet");
In a JSF application, we have the directory hierarchy:
webapp
xhtml
login.xhtml
main.xhtml
search.xhtml
css
main.css
extra.css
js
jquery.js
etc. The servlet mapping is:
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
This works fine, but the URLs of our web app look like this:
http://localhost/myapp/xhtml/login.xhtml
http://localhost/myapp/xhtml/search.xhtml
We would like to have simpler URLs by dropping the /xhtml part, i.e.
http://localhost/myapp/login.xhtml
I could not find any way to accomplish this. Is there some way to do this in the <servlet-mapping>? Do I need some additional framework?
You could do it with a Filter. Either homegrown or a 3rd party one like URLRewriteFilter. Just map it on *.xhtml and then forward to /xhtml/*.
Something like:
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String ctx = request.getContextPath();
String uri = request.getRequestURI();
String viewId = uri.substring(ctx.length(), uri.length());
if (viewId.startsWith("/xhtml")) {
// Redirect to URL without /xhtml (changes URL in browser address bar).
response.setStatus(301);
response.setHeader("Location", ctx + viewId.substring("/xhtml".length());
// Don't use response.sendRedirect() as it does a temporary redirect (302).
} else {
// Forward to the real location (doesn't change URL in browser address bar).
request.getRequestDispatcher("/xhtml" + viewId).forward(request, response);
}
But simpler would be to just change the directory hierarchy to get rid of /xhtml subfolder. Those CSS/JS (and image) files should preferably be placed in a /resources subfolder so that you can utilize the powers of <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> in a proper way.
See also:
How to reference CSS / JS / image resource in Facelets template?
Structure for multiple JSF projects with shared code
Should I use URLs as links to images and other resources or should I use the EL #{resource...}