I have a java class which performs some operations on files. Since the java code is huge I don't want to write this code in jsp. I want to call the methods in jsp whenever required.
Please tell me the path where I need to keep this file. Also some example code how to use it would be helpful.
In the servlet (which runs before the JSP):
Person p = new Person(); // instantiate business object
p.init(...); // init it or something
request.setAttribute("person", p); // make it available to the template as 'person'
In the template you can use this:
your age is: ${person.age} <%-- calls person.getAge() --%>
I think the question is, how do you make Java code available to a JSP? You would make it available like any other Java code, which means it needs to be compiled into a .class file and put on the classpath.
In web applications, this means the class file must exist under WEB-INF/classes in the application's .war file or directory, in the usual directory structure matching its package. So, compile and deploy this code along with all of your other application Java code, and it should be in the right place.
Note you will need to import your class in the JSP, or use the fully-qualified class name, but otherwise you can write whatever Java code you like using the <% %> syntax.
You could also declare a method in some other utility JSP, using <%! %> syntax (note the !), import the JSP, and then call the method declared in such a block. This is bad style though.
Depending on the kind of action you'd like to call, there you normally use taglibs, EL functions or servlets for. Java code really, really doesn't belong in JSP files, but in Java classes.
If you want to preprocess a request, use the Servlet doGet() method. E.g.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Preprocess request here.
doYourThingHere();
// And forward to JSP to display data.
request.getRequestDispatcher("page.jsp").forward(request, response);
}
If you want to postprocess a request after some form submit, use the Servlet doPost() method instead.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Postprocess request here.
doYourThingHere();
// And forward to JSP to display results.
request.getRequestDispatcher("page.jsp").forward(request, response);
}
If you want to control the page flow and/or HTML output, use a taglib like JSTL core taglib or create custom tags.
If you want to execute static/helper functions, use EL functions like JSTL fn taglib or create custom functions.
Although I'll not advice you to do any java calls in JSP, you can do this inside your JSP:
<%
//Your java code here (like you do in normal java class file.
%>
<!-- HTML/JSP tags here -->
In case you're wondering, the <% ... %> section is called scriptlet :-)
Actually, jsp is not the right place to 'performs some operations on files'. Did you hear about MVC pattern?
If you still interested in calling java method from jsp you can do it, for example:
1. <% MyUtils.performOperation("delete") %> (scriptlet)
2. <my-utils:perform operation="delete"/> (custom tag)
Anyway I recomend you to google about scriptlets, jsp custom tags and MVC pattern.
Best Regards, Gedevan
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 need to call in a JSP a method that is defined in another JSP that should be included dynamically (include page ) not statically (include file), but I get a jsp compilation error "method is undefined". It works fine when I use <%#include file=""%>.
The reason I need this is that our JSP ends up getting too big and we get this error: "The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit" (whence the need to include other jsps dynamically), therefore we're splitting some of its funcionality into smaller JSPs.
Foo.jsp
<%#page language="java"%>
<%!
public String getSomeID(String param) throws Exception {
return "someId";
}
%>
Bar.jsp
<jsp:include page="Foo.jsp"></jsp:include>
String id = getSomeID(param);
I'm aware that the better option here is to use a preprocessing servlet. We'll probably do that. But, for now, I merely wish to know if it is possible to call methods from another jsp while including it dynamically.
You can't reference the code from your Foo.jsp in Bar.jsp
if you are doing that with jsp:include.
Both pages in that cases are compiled into independent servlets behind the scene. Let's call them Foo_Servlet and Bar_Servlet.
What actually happens in that case is the following: Bar_Servlet while handling the request passes control and original request to Foo_Servlet.
Once Foo_Servlet completes the response of execution of Foo_Servlet (and not original jsp code) is combined with a response of Bar_Servlet.
I'm used to rails and the very handy yield functionality in erbs. I would like to be able to inject css/js script tags to the head when I'm running through many child jsp templates in the body tag. I know this is possible with Rails using yield, but I cant see a way of injecting a string higher than whats already outputted... here is my example
<head>
<!--- i want to inject script tags into here -->
</head>
<body>
<!-- running multiple child templates here -->
<!-- when the template needs a script tag, find a way of injecting it into the head -->
</body>
can I render into the head tag from further down the page, is this possible in jsp using string writers or some other way?
There are several ways to accomplish text juggling. As ERB, ruby on rails, also has a bit of Model-View-Controller separation, let's keep the same practice here:
A servlet (the controller) builds one or more data models and puts them in request attributes. Then it forwards to a JSP (the view).
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException {
List<Content> contents = new ArrayList<>();
...
request.setAttribute("contents", contents);
request.getRequestDispatcher("/contentsview.jsp")
.forward(request, response);
}
As I guess intended to do a loop on data emitting HTML and building a parallel list collected in a StringWriter, this already should solve the problem.
Now for doing (too much) work in the JSP: you can use the JspWriter also in methods, so order of evaluation is just as free.
<%!
private void printSomething() {
%><p>...</p><%
}
%>
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.
In Expression Language, I can access my model like so: ${model.member}
How do I achieve the same thing when I want to use <%=some_method(${model.member}); %>
The reason is because I have some HTML helper methods I created to separate logic from UI, and I need to pass a member of the model to create the user control.
The JSP's main method has the following signature:
_jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, java.io.IOException
Based on this, you can access the request and response objects programattically from a scriptlet. For example:
<%= request.getParameter("foo").toString() %>
or
<%= request.getAttribute("bar").toString() %>
If you want to do something more complication, you could precede these with scriptlets to declare / initialize local (Java) variables; e.g.
<% String foo = request.getParameter("foo") == null ?
"no foo" : request.getParameter("foo").toString(); %>
<%= foo %>
You can use this to lookup your model in the request or response object (I think it will be an attribute of the request with name "model"), cast it to the appropriate type, and call its getter methods.
The reason is because I have some HTML helper methods I created to separate logic from UI, and I need to pass a member of the model to create the user control.
A better idea would be to turn those helper methods into custom JSP tags so that you can use them without resorting to scriptlets. JSPs with embedded scriptlets are generally thought to be hard to read and hard to maintain. One small mistake (or one change to the model API) and the JSP generates bad Java on your deployment platform and you get a broken page.
Take a look at JSTL custom functions. It allows a way for you to call static functions from your code in a JSTL standard way. You just need to set then up in your tld file.