How can I use Servlets to access the HTML uses of having JSP without having to have all my client-facing pages called *.jsp?
I would rather do this than using all the response.write() stuff because I think it is easier to read and maintain when it is all clean "HTML".
Is this is fair assesment?
EDIT: What I'm going for is having the Servlets output things to the screen without having to redirect to a .jsp file.
In this way, I could write all the JSP stuff, but when it comes time to display it, the page the URL the user sees is essentially, "http://blah.com/posts/post-id" which is the address of the servlet and not "http://blah.com/posts.jsp?pos=post-id".
But I would still write all presentation logic in an external .jsp.
Just hide the JSP away in /WEB-INF folder so that noone can access it directly and create a servlet which forwards the request to this JSP file. Don't do a redirect, else you will see the new URL being reflected in the address bar. E.g.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String postId = request.getPathInfo();
// Do your business thing here. Any results can be placed in request scope. E.g.
request.setAttribute("post", post); // post is a bean containing information you'd like to display in JSP.
// Then forward request to JSP file.
request.getRequestDispatcher("/WEB-INF/posts.jsp").forward(request, response);
}
Map this servlet on an url-pattern of /posts/*.
In the /WEB-INF/posts.jsp make use of taglibs to control page flow and EL to access the data. E.g.
<h2>${post.title}</h2>
<p><fmt:formatDate value="${post.date}" type="date" /> - ${post.message}</p>
Finally just invoke the servlet by http://example.com/posts/postid. The /postid part will be available by HttpServletRequest#getPathInfo(). You need to parse the value yourself and do the business thing with it.
I'm not entirely sure what you're asking here. You can ge servlets themselves to write HTML, but that's not clean at all.
An alternative is to get your servlets to create HTML via a templating engine, such as Velocity or Freemarker. The syntax in the templates may be cleaner for your particular application, if less fully featured.
Back in ancient times (think '98...) this was called a "Model 2 architecture": a servlet received the request, processed it, and handed the request over to a JSP page that handled the view.
See this article for one example of how this is done, or simply search for "JSP Model 2".
Edit: for that, you can use RequestDispatcher.include() instead of forward() as described in the previous article. The rest should still be applicable.
If I understand correctly you want to hide *.jsp extension from user, right?
In that case when your Servlet redirects to a jsp page have it do this:
RequestDispatcher disp = request.getRequestDispatcher("hidden.jsp");
disp.forward(request,response);
By using Request Dispatcher instead of redirect you "hide" your .jsp extension behind the servlet name. However in case your JSP page redirects to another JSP page this won't work.
If you want the .jsp file to be visible use response.encodeURL or response.sendRedirect
I think you're looking for the Front Controller Pattern - this is the basis of "JSP Model 2" web apps (as #andri mentioned) and pretty much all the (hundreds?) of Java web frameworks.
Related
To make a request to Servlet, I need to use mapping inside XML file or add annotation for given Servlet. But why I am not required to do the same for JSP files as well? I will give examples.
How does this work?
index.html:
<html><body>
<form action="result.jsp">
<button>go</button>
</form>
</body></html>
result.jsp:
<html><body>
hello
</body></html>
Notice I didn't have to use any XML mappings nor annotations. It just "finds" it.
But how this doesn't work?
index.html:
<html><body>
<form action="com.example.MyServlet">
<button>go</button>
</form>
</body></html>
com.example.MyServlet:
public class MyServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw = resp.getWriter();
resp.setContentType("text/html");
pw.println("hello");
}
}
Here, I get error: The requested resource [/TestProject/com.example.MyServlet] is not available. How? How come I didn't need to use XML, nor annotations for JSP, but I had for Servlet? Shouldn't they work the same way, as JSP eventually turns to Servlet. So why is there different behavior? I know I am missing something, I just don't know what...
Why I need mapping or annotation for Servlet, but not for JSP?
As pointed out in the comment above from #SotiriosDelimanolis, that's not what actually happens. A JSP is eventually turned into a servlet and behaves like any other servlet you define on your own. And when you define a servlet you also need to add a URL mapping so that an URL path is resolved to a servlet that can respond to a request made for that URL.
The only difference is that for JSP files this mapping is done implicitly by the servlet container. For the servlets you define, you obviously need to define your own mapping because the server can't know what you want to do with the servlet in your own application.
The specifications says the following (emphasis mine):
A web component is either a servlet or a JSP page. The servlet element in a web.xml deployment descriptor is used to describe both types of web components. JSP page components are defined implicitly in the deployment descriptor through the use of an implicit .jsp extension mapping, or explicitly through the use of a jsp-group element.
and
[...] JSP page translated into an implementation class plus deployment information. The deployment information indicates support classes needed and the mapping between the original URL path to the JSP page and the URL for the JSP page implementation class for that page.
So basically, your JSP is translated into a servlet, and a mapping is created from your original JSP page location path to the servlet thus generated.
The JSP is not actually executed. What's executed is the servlet generated from the JSP. You have to realize that JSPs are provided for convenience. If you want to generate HTML from a servlet you have to do a whole bunch of out.write("<html>"); out.write("\r\n"); and so on, for your entire HTML page. It's not only very error prone, but you will go insane doing so. Thus, the option of providing an JSP combined with the things done behind the scene to make it all work.
I think the title above is a bit confusing.
What I'm trying to achieve:
I have a jps page(located in WEB-INF) with a hyperlink in it that will call another jsp (in WEB-INF) via servlet.
I understand that this can be achieved using the following:
Go to this page
But because there will be lots of hyperlinks, my idea was to have a general servlet(OpenPagesServlet) to handle all those pages.
Something like this:
JSP page:
<% request.setAttribute("page", "page1.jsp");%>
Page 1
OpenPagesServlet in doGet method:
String page = (String) request.getAttribute("page");
request.getRequestDispatcher("/WEB-INF/" + page).forward(request, response);
I tried the code above and I get:
HTTP Status 404 - Not Found
type Status report
messageNot Found
descriptionThe requested resource is not available.
But if I try with session.setAttribute / sesion.getAttribute the code works fine, but I don't want to have sessions on each time I click on hyperlinks.
The other approach I found was to use:
Page 1
and inside the servlet:
String page = (String)request.getParameter("value");
request.getRequestDispatcher("/WEB-INF/" + page).forward(request, response);
It worked, but this approach is not good because the page can then be accessed directly using the url:
http://localhost:8080/WebApp/OpenPagesServlet?value=page1
So...my question is why request.setAttribute/request.getAttribute is returning 404?
Is there a different approach to achieve what I'm trying to do?
An HttpServletRequest and its attributes only live for the duration of one HTTP request/response cycle. After yo've set the attribute in the JSP, the JSP is rendered and sent as part of the HTTP response body. The Servlet container considers the request handled and clears its attributes. The attribute is now gone.
It is therefore no longer available in the next request that arrives after the user clicks the link.
The session attribute or request parameter is fine. Consider looking into the Front Controller pattern.
Also, consider using the core tag library (in particular the url tag) instead of scriptlets for constructing your links.
I have a jsp page having a 'submit' option for input.On clicking it i want to update the value of a table called tbIndividual.What can be the best approach to do it?
On jsp page i have somthing like this :
User Name : <%=rs.getString(2)%>
First Name : <%=rs.getString(4)%>
Last Name : <%=rs.getString(5)%>
Email Id : <%=rs.getString(6)%>
Contact : <%=rs.getString(7)%>
<input type="submit" value="ADD"></input>
And now i want to update the value of status of that particular individual from 'NO' to 'WAIT' state.On click of this submit button.
Is making new servlet for this task a good option or doing the code in jsp a better one ?
If i need to make a new servlet then what will be the code for it on jsp page .?Please help.
If you are trying to learn servlet with this project then you should create a separate servlet where you will perform your business logic (e.g addition of element in Db) and jsp should be kept away from business logic because role of jsp is to render the output not to produce the output.
If this is a project for production purposes, then you should ( IMO you must ) opt some web framework. As framework will reduce your effort, headache and increase productivity.
First of all, there are certain things you need to understand while developing web applications in Java. I have a few recommendations and inputs
Please don't use Scriptlets. Scriptlets are deprecated and they make your code clumsy and the maintainance will be hard. Use JSTL
You need to create a form in your html to have a set of variables to push them to the server on clicking submit button. The form will have an action attribute which contains the URL where the request should be sent
Create a Servlet and map with the action URL and write the doPost method which can receive the form parameters and do the business logic whatever changing the status from NO to WAIT or anything else
Please take a note that you need to have Session variables in order to have the store the data in between requests from the same client. eg browser.
Is making new servlet for this task a good option or doing the code in jsp a better one ?
Writing a new servlet is a good option, than doing the business logic in jsp page. jsp is meant for presentation, just view. They shouldn't be used to perform business logic
If i need to make a new servlet then what will be the code for it on jsp page .?
JSP should just have all the necessary html elements and attributes like form, action attribute etc.. to post the parameters in the request to the action URL. Please note the method attribute of form. You should use HTTP POST method for posting form parameters to the server
Note : Finally, Writing Servlets are also NOT recommended. Instead, you should opt for webframeworks like Spring MVC , Struts etc. Please go through the link to understand about web frameworks answered by #BaluC
Hope this clarifies.
I have the following method in my Servlet.
private String process(HttpServletRequest arg0, HttpServletResponse arg1) {
return ("a key");
}
protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
process(arg0, arg1);
}
In web.xml the following code is added
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>iusa.ubicacel.actions.map.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
In inicio.jsp the following is added
<script type="text/javascript" src="<%=request.getContextPath()%>/MyServlet"></script>
In the src tag above I want to add google map api url(which I will retrieve from the database in the servlet) from the process method in the MyServlet.I understand from the comments that my approach is wrong.Can anyone please tell me how to do it correctly with only this jsp and servlet.
A best practice for writing servlets with JSP is to follow the MVC pattern: your servlet will be the controller, the JSP is the view, while the model will consist of your domain objects which are passed from the servlet to the JSP page via request attributes.
I don't think that what you have right now is entirely wrong. But it's only suited for a special scenario where you will need to generate all your javascript code from a servlet (and this is hardly ever a true requirement). Assuming though that this is a true requirement in your case (perhaps you read the whole javascript content from a database), it's OK to define a servlet that renders the JS content (and perhaps map it as /main.js or something, to make the dynamic generation transparent for the JSP page).
Most likely, you need only a bunch of small items to be dynamically generated at runtime (like your google maps url, API key or whatever you store in your database). If this is the case, then your JavaScript code can be statically defined in a .js file and allow initialization with some constructor arguments (or whatever).
In this setup, your servlet will read the url from the database, will pass it to the view by calling request.setAttribute("googleMapsUrl", url) and then call requestDispatcher.forward(...) to pass control to the JSP.
In the JSP, you'll now need to include your static script with src and then you can have another script tag to initialize your code based on dynamic values bound to your request:
<c:url value="/static.js" var="scriptUrl"/>
<script type="text/javascript" src="${scriptUrl}"></script>
<script type="text/javascript">
// let's assume your static script defines an object called `MyGoogleMapsDriver`...
var googleMapsDriver = new MyGoogleMapsDriver('${googleMapsUrl}');
</script>
I hope this helps.
You dont need that, you should access to data so :
Save data from Servlet -> request.setAttribute("MyObject", data);
After in JSP you load data that need -> request.getAttribute("MyObject");
Sorry my english,
good luck.
Note: I don't recommend to do this, but this is the direct answer to the question. For more information, take a look at the comments.
If you just 'want to add the string returned from the process method' you need to do the following:
Make your method public and static.
Then write the following scriptlet: <%= MyServletName.process(request, response); %>. This will output the result of the process method.
At the end you will have the following:
<script src="<%= MyServletName.process(request, response); %>"></script>
The variables request and response are available in this scope.
Important: The thing you are trying to achieve this way looks like a bad design. For various reason commented in this answer. Check the comments made by #LuiggiMendoza and #DaveNewton.
Here are some points to take in account:
Writing scriplet is easy but is not recommended by any mean. See: How to avoid Java code in JSP files?.
Invoking a Servlet method from JSP is bad design. Servlet methods are designed to handle HTTP methods. They were not designed to handle specific situation.
The thing you are trying to do is an anti-pattern, you are not separating concerns. A JSP page should be a view that structure and render information. That information should be pre-processed.
I'm working on a jsf project, and I have several xhtml pages which use the same template. The template contains the layout and the page header. I would like to know if it is possible to not reload the header when user navigates to another page, since it is always the same; and as it contains a couple of images it makes navigating unnecessarily slower.
One remark: I'm using a filter that adds the following headers to the response, for security reasons:
HttpServletResponse resp = (HttpServletResponse) response;
resp.setHeader("Cache-Control", "no-cache,no-store,must-revalidate"); // HTTP 1.1
resp.setHeader("Pragma", "no-cache"); // HTTP 1.0
resp.setDateHeader("Expires", 0); // Proxies.
Can it be done without removing those headers?
Thanks!
Damian
The template contains the layout and the page header. I would like to know if it is possible to not reload the header when user navigates to another page, since it is always the same;
This is only possible when using a HTML frame (not recommended) or when refreshing the page parts by Ajax requests instead of normal requests. However, the disadvantage is that you end up with unbookmarkable URLs.
and as it contains a couple of images it makes navigating unnecessarily slower.
If that is the real problem, then you need to instruct the browser to actually cache the images (and CSS and JS). So if you're setting those response headers on image/CSS/JS requests as well, then the browser is forced to reload them everytime. This is unnecessary and will indeed result in slow loading. You need to ensure that those headers are only set on JSF pages, so you need to ensure that the URL pattern of the filter matches JSF page requests only, e.g. *.jsf or *.xhtml and thus not /* or something.
See also:
Java EE Web application performance tips and tricks
Looking for a similar technique in my audio player to don't stop listenig during navigation. I just look at soundcloud site. U can refresh content in ajax and change url in javascript with window.history.pushState look here:
http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#dom-history-pushstate
It probably doesn't work with old browser...