I use jsp+servlets and have a form. How can I send the form data to a servlet (to the doPost() method) without leaving the actual page, that contains the form?
I want to press the button "submit", the data should be sent and I want to still remain on the page with the form. I would rather not use javascript.
I have on http://localhost/myproject/
<form action="http://localhost/myproject/anotherpage" method="POST">
First Name: <input type="text" name="first_name">
<br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>
when clicking the submit button i get forwarded to the following page: http://localhost/myproject/anotherpage
but I want to stay on
http://localhost/myproject/
edit: right now I am going to write
request.getRequestDispatcher("/index.jsp").forward(request, response);
in the doPost() method
You should have a form with method="POST" in your JSP
<form method="post">
<input type="number" name="number1" id="number1" />
+
<input type="number" name="number2" id="number2" />
<input type="submit" />
</form>
Then in your servlets, in the doPost method, you have to get the parameters of your form with getParameter("name"), do what you want on it, then resend it to your JSP (setAttribute).
Don't forget to link with your jsp (last line of my example)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String textNumber1 = request.getParameter("number1");
String textNumber2 = request.getParameter("number2");
int number1 = (!textNumber1.isEmpty() ? Integer.parseInt(textNumber1) : 0);
int number2 = (!textNumber2.isEmpty() ? Integer.parseInt(textNumber2) : 0);
int result = number1 + number2;
request.setAttribute("result", Integer.toString(result));
request.setAttribute("number1", Integer.toString(number1));
request.setAttribute("number2", Integer.toString(number2));
this.getServletContext().getRequestDispatcher("/WEB-INF/calc.jsp").forward(request, response);
}
Finally on your JSP, get the attribute from your servlet you want to display on the same page with getAttribute
<%
String number1 = (String) request.getAttribute("number1");
String number2 = (String) request.getAttribute("number2");
String result = (String) request.getAttribute("result");
if (number1 != null && number2 != null && result != null) {
out.print(String.format("<p>Result of %s + %s = <strong>%s</strong></p>", number1, number2, result));
}
%>
This example is a little calculator that show you the result of number1 + number 2 on the same page of the form ;)
I would advise you not to forward to initial page from the second one, but instead to redirect to it in order to follow the Post-Redirect-Get pattern.
If you do not, the user will see in his URL bar the address of the page where he posted data, and if he clicks the back button he will get the ugly message of duplicate post submissions.
So in you doPost() method just to :
response.sendRedirect("/back/to/your/page");
As as alternative, you could hide the JSP page behind the servlet, and have the servlet to directly forward to the JSP page for a GET request, and do its work for a POST and then either forward to the JSP or redirect to itself. In that case, you would not set any action in the <form> tag to have the data posted to same URL.
As it would keep same URL, you could eventually simply do a forward, but I still recommend a redirect to avoid the back button problem.
On you servlet, define the jsp you want to return.
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/path/to/your/jsp");
requestDispatcher.forward(req, res);
If you mean to send data without refreshing current page, you might want to look at sending ajax request.
This doesn't let you stay on the form page, but redirects you back to it right away. And you can of course use the values you just entered.
JSP form
<form method="post" action="yourServlet">
Servlet (in doPost())
getServletContext().getRequestDispatcher("/back/to/your.jsp").forward(request, response);
You can use javascript and ajax (XMLHttpRequest), or specify a target to your form, that references a hidden iframe.
Related
I'm studying JSP and Servlets by reading a book and following some online tutorials. I'm totally new with web programming using JSP and Servlets.
I came across an example which I am trying to understand.
index.html
<form action="emailList" method="post">
<input type="hidden" name="action" value="add" />
<label>Email: </label>
<input type="email" name="email" required /> <br />
<label>First Name:</label>
<input type="text" name="firstName" required /> <br/>
<label>Last Name:</label>
<input type="text" name="lastName" required /> <br />
<label> </label>
<input type="submit" value="Join Now" id="submit" />
</form>
EmailServlet.java
public class EmailListServlet extends HttpServlet{
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = "/index.html";
//get the current action
String action = req.getParameter("action");
if(action == null){
action = "join"; //default action
}
//perform action and set URL to appropriate page
if(action.equals("join")){
url = "/index.html"; //the join page
}
else if(action.equals("add")){
//get parameters from the request
String firstName = req.getParameter("firstName");
String lastName = req.getParameter("lastName");
String email = req.getParameter("email");
//store data in User object and save User object in database
User user = new User(firstName, lastName, email);
UserDB.insert(user);
//set User object in request object and set URL
req.setAttribute("user", user);
url = "/thanks.jsp"; //the thanks page
}
//forward request and response objects to specified url
getServletContext().getRequestDispatcher(url).forward(req, resp);
}
The thing I don't understand is the IF-ELSE part.
I read somewhere that the main purpose of using hidden <input> is to determine the state of a form. The way I understand it is that of, a way to check if form fields (or parameters) are null or not.
If that's the case, then what is the purpose of the value="add" attribute?
Because on else if(action.equals("add")) , add was used.
What could the req.getParameter() return ?
//get the current action
String action = req.getParameter("action");
I'm asking because in the past I did some CRUD project on PHP where it used the ff to check if form has no null parameters.
if(isset($_POST['btnSave'])){
}
<form method ="POST" action="index.php">
<label>First Name<input type="text" name="firstname" required></label>
<br /><br />
<label>Last Name<input type="text" name="lastname" required></label>
<br /><br />
<input type = "submit" name="btnSave" value="Save" />
<input type = "submit" name="btnSearch" value="Search" />
</form>
Instead, in the last form example it used the btnSave (form button) instead of a hidden input.
I just don't see the point of using a value="add" and what req.getParameter("action") could return. Because it was used on the IF-ELSE
I'd appreciate any explanation.
Thank you.
Covering your questions in reverse order:
What could the req.getParameter() return ?
It could return anything. The <form> you posted will generate a request to the server that looks like this:
POST /emailList HTTP/1.1
Host: example.com
Cache-Control: no-cache
action=add&email=MyEmail&firstName=MyFirstName&lastName=MyLastName&submit=Join Now
Now, consider the case where someone submits the following request instead:
POST /emailList HTTP/1.1
Host: example.com
Cache-Control: no-cache
action=edit&id=1&email=NewEmail&firstName=TypoFreeName&lastName=TypoFreeLastName&submit=Update Details
Since you don't have an "edit" case in your servlet, but you do have that if check, your servlet will just redirect to /index.html instead of changing a user's details or inserting a new user.
A logical next step for code like this would be to add new sections to your servlet:
if(action.equals("join")){
url = "/index.html"; //the join page
}
else if (action.equals("delete") {
//Call UserDB.delete()
}
else if (action.equals("edit") {
//Call UserDB.update()
}
else if(action.equals("add")){
...
}
what is the purpose of the value="add" attribute?
It's partly to control the flow of your servlet and partly to act as an error prevention measure; if the request includes action=add, you proceed with the assumption that you'll have the other form elements (better practice would be to check to make sure that firstName, lastName, and email are set in the request before calling UserDB).
The code is frankly a bit odd. It appears to be designed to handle the case where a different form (without an action field) is POSTed to the servlet, and to handle it by presenting the index.html page. Perhaps there's another form somewhere else in the chapter that does that?
If the form in the question is posted to the server, the servlet will receive an action parameter. (Well, unless JavaScript code actively removes the input from the form first.) So getParameter("action") will not return null. It might (if JavaScript code changed the input's value) get a different string, even a "" string, but not null.
It's probably worth noting that it doesn't handle the possibility that a different form with an action=add field is posted to the server, and happily uses the other parameters without checking them server-side, which is poor practice. Validation must be done server-side.
In my Liferay 6 app I'm able to pass parameter from java to jsp via:
final PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("view");
request.setAttribute("description", "some description");
rd.include(request, response);
Then I want user to change the description and pass it back to back-end:
<form method="POST" action="${addItem}">
<input name="description"
type="text"
value="${description}"/>
<button type="submit">UPDATE</button>
</form>
Nevertheless when I call then System.out.println("request.getAttribute("description")); , I'm getting null. What am I doing wrong?
Youre passing in the parameter but checking the request attribute (assuming that the outer quotes are a question typo). Based on the information you provided, the initial request attribute was only available in the JSP but not any subsequent servlet. Try
System.out.println(request.getParameter("description"));
I should be using getRemoteUser functionality to get the logged in user. Until the authentication part get created I am trying to hard code the user in the jsp page and pass that in the my servlet. But when I try to print out the value its null:
<input type="hidden" name="userId" id="userId" value="123456789" />
Here is how I tried to get the user:
String fakeUser = request.getParameter("userId");
PrintWriter out = response.getWriter();
out.println(fakeUser);
System.out.println(fakeUser)
I also tried the solution mentioned following Stackoverflow post but that didn't work either.
passing value from jsp to servlet
As you are trying to use hidden-form field I assume that you are trying to do some sort of state management.
try something like this
<form action="urlOfYourServlet" method="post">
Enter your name : <input type ="text" name = "name">
<input type="hidden" name="hidden" value="Welcome">
<input type="submit" value="submit">
</form>
In servlet
String getHiddenValue=request.getParameter("hidden");
String name=request.getParameter("name");
System.out.println(name+" Hidden field Value is :"+getHiddenValue);
Disadvantage :
Only textual information can be persisted between request.
This method works only when the request is submitted through input form
Instead try url-redirecting or HttpSession
In my JSP I do the following :
<!-- Bank manager's permissions -->
<!--more stuff goes here -->
<fieldset>
<legend>To open a new account</legend>
<form action="blablabla">
<input type="hidden" name="hdField" value="myValue" /> // note I pass a "myValue" as string
Press here to continue
</form>
</fieldset>
And in my Servlet I grab the hidden input :
#WebServlet("/employeeTransaction1")
public class Employee1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String getHiddenValue=request.getParameter("hdField");
System.out.println("Hidden field Value :"+getHiddenValue);
// forwards to the page employeeOpenNewAccount.jsp
request.getRequestDispatcher("/WEB-INF/results/employeeOpenNewAccount.jsp").forward(request, response);
}
}
And System.out.println produces : null at the Console
Why do I get a null of not the actual value is I pass ?
Regards
EDIT:
After changing to :
<fieldset>
<legend>To open a new account</legend>
<form action="/employeeTransaction1" method="GET">
<input type="hidden" name="hdField" value="myValue"/>
Press here to continue
</form>
</fieldset>
A null is still presented at the console .
What you are trying to do is to send a form to the server. But, in fact, you don't do that. You just issue a GET request (when the user clicks your link: Press here to continue)
If you want to send the form make sure you set the attributes of the form tag properly and add a submit button to the form:
<form action="/employeeTransaction1" method="GET">
...
<input type="submit" value="Submit" />
...
</form>
Depending on your preferred way of sending the form, you can change the method="GET" paramater to method="POST" and make sure that in the servlet you handle the form in the doPost() method
Alternatively, if your purpose is not to send the from to the server but just to pass the value of the hidden input, you should add its value as a prameter encoded in the GET request. Something like:
/employeeTransaction1?hdField=myValue
To achieve this, you need some client processing, i.e. when the user clicks the link, the hidden input should be added to the get and then the request should be issued.
Using an href tag does not submit your form, i.e. it does not pass the parameters defined in the form to the request. You should use input type="submit" or button tags instead. Also make sure the form action matches your #WebServlet definition.
<fieldset>
<legend>To open a new account</legend>
<form action="/employeeTransaction1">
<input type="hidden" name="hdField" value="myValue" /> // note I pass a "myValue" as string
<input type="submit" value="Submit" />
</form>
</fieldset>
Since this not really answers my question, I'm gonna clarify.
3 .jsp pages, index.jsp, calculator.jsp and error.jsp.
index.jsp contains (withoug html and body tags):
<p><b>Enter the Number you want to know the square root of:</b></p>
<form action="calculator.jsp" method="post">
<div><input type="text" name="number_textfield" size="40" /> <input type="submit" value="Send" /></div>
</form>
error.jsp contains (without html body tags):
<%#page isErrorPage="true" import="java.io.*" %>
<%
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
String exceptionstack = sw.toString();
%>
<p>Path to File causing this error:
<span class="errortext"><%= request.getAttribute("javax.servlet.error.request_uri") %></span><br />
Error Message: <span class="errortext"><%= exception %></span><br />
The Error is: <span class="errortext"><%= exception.getMessage() %></span><br /></p>
<hr />
<p>Exception stack:</p>
<pre class="errortext"><%= exceptionstack %></pre>
<p>Index Page</p>
Now in calculator.jsp....
1) If I leave the textfield empty in index.jsp, I'm gettin displayed the error according to error.jsp.
2) If I enter a number smaller than 0, nothing happens. Now I've tried various methods from there. None of them works.
The calculator.jsp (without body and html tag):
<%# page errorPage="../WEB-INF/sqrterror.jsp" %>
<%
String number_string = request.getParameter("number_textfield");
double number = Double.parseDouble(number_string);
if (number < 0){
//THAT'S WHAT I'M MISSING HERE :(
%>
<%
}
else{
double sqrt = Math.sqrt(number);
%>
<p>Square Root of <%= number %> is <%= sqrt %> .</p>
<p>Back to Index Page</p>
<%
}
%>
You've one big problem here: if you throw an Exception halfway a JSP file, then the chance is big that it will never reach the error.jsp, simply because the response is already committed. The response headers are already set, the response writer is already obtained, the response content is already sent to the client (even if only partly), all only because of the fact that the JSP does that by nature as being a pure view technology. This is a point of no return. The enduser may end up with a blank page and you may end up with an IllegalStateException in the server logs.
If you are very, very lucky, everything is still in the buffer which is not flushed yet, then the webcontainer can still manage to reset it all and forward the request to error.jsp. But I wouldn't rely on that. Writing raw Java code in JSP files is considered bad practice.
Better use a Servlet class. I'll give you a kickoff example. Change your index.jsp as follows:
<h4>Enter the Number you want to know the square root of:</h4>
<form action="calculator" method="post">
<input type="text" name="number" size="40" />
<input type="submit" value="Send" />
${error}
</form>
The ${error} should display the error message, if any. The servlet can set it as a request attribute.
Change your result.jsp as follows:
<p>Square Root of ${param.number} is ${result}.</p>
The ${param.number} should display the "number" request parameter. The ${result} should display the result, if any. The servlet can set it as a request attribute.
Create a Servlet class CalculatorServlet:
public class CalculatorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String number = request.getParameter("number");
// Check if number is set and if it is valid, with little help of regex.
// Those are valid: "12" and "12.34", but those not: "-1" or "" or null.
if (number != null && number.matches("^\\d+(\\.\\d+)?$")) {
request.setAttribute("result", Math.sqrt(Double.parseDouble(number)));
request.getRequestDispatcher("result.jsp").forward(request, response);
} else {
request.setAttribute("error", "Please enter valid number.");
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
}
Note that I don't throw exceptions, but just validate the values and set an user-friendly error message for the case that the input is wrong. You should expect that the user can enter wrong values. Never trust user input, always validate it in a proper manner. Your application should not look like to "drastically break" on wrong user input. Exceptions are only affordable if for example the backend DB is down and more of those kind of unrecoverable matters.
Now map this servlet in web.xml as follows (oh, ensure that you're using Servlet 2.4 or newer to get EL (Expression Language, the ${} things) to work in template text):
<servlet>
<servlet-name>calculator</servlet-name>
<servlet-class>com.example.CalculatorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>calculator</servlet-name>
<url-pattern>/calculator</url-pattern>
</servlet-mapping>
The url-pattern should cover the action url as you're going to use in the <form action>.
That should be it. Much nicer separation of business logic and the presentation logic. That's a good start of the MVC way.
Just add
throw new IllegalArgumentException("Number must be non-negative");