I'm new to JEE programming, I know that the way I present you my problem is not optimal but I have to do it using only JPSs first.
So, I created a form that included checkboxes. I would like to delete all members that have been checked. My tag action form redirects to dispaly.jsp where I perform delete query before redirecting to my main page, members.jsp.
The problem is that my server crash and does not redirect me. I have to restart it, But my rows have been deleted in my database.
Here's my code :
<form method="post" action="display.jsp"><table id="members_table">
<tr>
<th>Sel</th><th>FIRSTNAME</th><th>NAME</th><th>EMAIL</th>
</tr>
<%
while (resultset.next()) {
%>
<tr>
<td><input type="checkbox" name="selected" value="<%=resultset.getString(1)%>"/></td>
<td><%= resultset.getString(2)%></td>
<td><%= resultset.getString(3)%></td>
<td><%= resultset.getString(4)%></td>
</tr>
<%}%>
</table>
<input type="submit" value="Details" name="details" id="details_members">
<input type="submit" value="Delete" name="delete" id="delete_members">
</form>
display.jsp page :
RequestDispatcher requestDisp = request.getRequestDispatcher("/members.jsp");
if(request.getParameter("delete") != null)
{
if(request.getParameter("selected")!=null)
{
String[] a = request.getParameterValues("selected");
str = "DELETE FROM MEMBERS WHERE ID = ";
for(int it=0;it<a.length;++it)
{
if(it==a.length-1)
str+=a[it];
else
str+=a[it]+" OR ID = ";
}
statement.executeUpdate(str);
requestDisp.forward(request, response);
}
requestDisp.forward(request, response);
}
When I run my code, I get this error after a long time waiting :
javax.servlet.ServletException: java.sql.SQLTransactionRollbackException: Unable to get a lock within the requested timeout
root cause
java.sql.SQLTransactionRollbackException: Unable to get a lock within the requested timeout
I don't understand why my server crash, I tried to execute this delete query directly in my database and it works. I also debug my code to see if my variable "str" contains right query ...
Please help.
Related
I would like to create a form for a patient database system. Then I will give some input data to each textbox of the form and the data will be stored in a MySQL database.
I wrote a JSP file as follows
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page import="java.sql.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table>
<tr><td>Pid</td><td><input type="text" name="pid" required /></td></tr>
<tr><td>Name</td><td><input type="text" name="patientname" required /></td></tr>
<tr><td>Address</td><td><input type="text" name="patientaddress" ></td></tr>
<tr><td>Phone number</td><td><input type="number" name="Ph" required /></td></tr>
<tr><td>Email</td><td><input type="email" name="email" required /></td></tr>
<tr><td>Type</td><td><input type="text" name="patienttype" ></td></tr>
<tr><td></td><td><input type="submit" name="submit" value="register"></td></tr>
</table>
<%
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/hospitalm","root","1234");
out.println ("database successfully opened.");
String sql = "INSERT INTO patient (pid, pname, address, phone, email_id,ptype) values (?, ?, ?,?,?,?)";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1, Pid);
statement.setString(2, Name);
statement.setString(3, "Forrest");
statement.setDouble(4, 664208158);
statement.setString(5, "ava#gmail.com");
statement.setString(6,"G");
int row = statement.executeUpdate();
if (row > 0) {
System.out.println("One row inserted.");
}
}
catch(SQLException e) {
out.println("SQLException caught: " +e.getMessage());
}
%>
</body>
</html>
This two lines throw error
statement.setString(1, Pid);
statement.setString(2, Name);
If I input some values like 'p101' for Pid and 'John' for Name then I can easily entered a record on the database hospitalM.
But if I try Pid and Name which are the variable names for table,
<tr><td>Pid</td><td><input type="text" name="pid" required /></td></tr>
<tr><td>Name</td><td><input type="text" name="patientname" required /></td></tr>
I got error.
How could I solve this?
JSP does not automagically bind request parameters in to Java variables, which is what you're trying to do here.
In order to get the parameters, you need to query the request object directly. Something akin to:
statement.setString(1, request.getParameter("Pid"));
statement.setString(2, request.getParameter("Name"));
Addenda:
Regarding double (or other non-strings), there's two things you can do.
One, you can convert them on the fly:
statement.setDouble(4, Double.parseDouble(requests.getParameter("phone")));
Second, you can rely on the SQL driver to do it for you.
statement.setString(4, requests.getParameter("phone"));
The "setXXX" in JDBC is based on the value that you're setting, NOT the data type of the column in the database. Inevitably, most of the time, whatever you set in the JDBC statement is going to be turned in to a string before being shipped up to the DB anyway. So, you can just use setString and be done with it and let the driver/db figure it out.
Either way, if you send in badly formatted data (i.e. "Tom" for the phone number), you're going to get an exception, either from the Double.parseDouble or when the DB tries to convert it during the insert. But that's a separate issue from simply setting parameters.
I like to create a registration form where user can register his or her data and the given data will be saved on a database. I created a database HospitalM using mysql workbench 8.0. I ran the project, the jsp file for form creation on Tomcat server. The pid is a primary key in the table called patient in the database HospitalM.
When I run the form on server a form generated but the form did not wait for input data and throw a message SQLException caught: Column 'pid' cannot be null.
I will share my code and the form in the below. Can any one give me some hints why it did not work?
JSP code: (name of the jsp file insert.jsp)
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page import="java.sql.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table>
<tr><td>Pid</td><td><input type="text" name="pid" required /></td></tr>
<tr><td>Name</td><td><input type="text" name="patientname" required /></td></tr>
<tr><td>Address</td><td><input type="text" name="patientaddress" ></td></tr>
<tr><td>Phone number</td><td><input type="number" name="Ph" required /></td></tr>
<tr><td>Email</td><td><input type="email" name="email" required /></td></tr>
<tr><td>Type</td><td><input type="text" name="patienttype" ></td></tr>
<tr><td></td><td><input type="submit" name="submit" value="register"></td></tr>
</table>
<%
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/hospitalm","root","1234");
out.println ("database successfully opened.");
String sql = "INSERT INTO patient (pid, pname, address, phone, email_id,ptype) values (?, ?, ?,?,?,?)";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1, request.getParameter("pid"));
statement.setString(2, request.getParameter("pname"));
statement.setString(3, request.getParameter("address"));
statement.setString(4, request.getParameter("phone"));
statement.setString(5, request.getParameter("email_id"));
statement.setString(6,request.getParameter("ptype"));
int row = statement.executeUpdate();
if (row > 0) {
System.out.println("One row inserted.");
}
}
catch(SQLException e) {
out.println("SQLException caught: " +e.getMessage());
}
%>
</body>
</html>
The sql query for patient table:
create table patient(pid varchar(10),
pname varchar(40) not null,
address varchar(10),
phone numeric(10,0) not null,
email_id varchar(20) not null,
ptype varchar(2),
primary key(pid),
check(email_id like '%_#__%.__%'));
The output that I got
The problem here is that when you first access the page, all of that code gets executed, but there was no request to process.
So, during the first access, all of those request parameters are null.
As suggested by Piotr, you could use the request method to get for whether it's a GET or a POST, and only execute the code on the POST.
The proper answer to that goes much deeper into how these kinds of things are architected along with the page workflow, but that's a much deeper topic that to go in to here.
For now, the simple issue is that on the first access, there are no parameters, so you're essentially trying to do:
statement.setString(1, null);
Which is illegal (to set a column to an explicit SQL NULL value in JDBC, you use the statement.setNull(1) method).
i encountered the following problem. I have made a table in mysql named 'users' and i want to add users using JSP. The primary key is the Email and i want to check before adding another user if the email already exists. If the email already exists the users will not be added to the database and a message "email already exists" will appear.
I created ResultSet rs object and extracted the "Email" column into a String email using a while loop.Now, here comes the problem. Suppose i have a user with the "denis#yahoo.com" email. If i try to add an user with the exact same email an error will occur which means my if statement was ignored. I looked up in the debug mode for the variables email and Email and they had the exact same "denis#yahoo.com" and still the if statement was ignored.
<!-- file name: addUser.jsp -->
<%
String Email=request.getParameter("Email");
String Name = request.getParameter("Name");
String Adress = request.getParameter("Adress");
String Phone = request.getParameter("Phone");
if (Email != null)
{
jb.connect(); // connect to the database using JavaBean class
ResultSet rs;
rs=jb.seeTable("users");// rs gets first row of table
String email;
int a=1;
while(rs.next())
{
email=rs.getString("Email");
if(Email==email)
{
a=0;
jb.disconnect();
%>
<p> The email already exists</p>
<%
break;
}
}
if(a==1){
jb.addUser(Email,Name, Adress, Phone);
jb.disconnect();
%>
<p>Data has been added.</p>
<%
}
} else {
%>
<form action="addUser.jsp" >
Email: <input type="text" name="Email"><br>
Name: <input type="text" name="Name"><br>
Adress: <input type="text" name="Adress"><br>
Phone: <input type="text" name="Phone"><br>
<button type="submit" >Add User</button><br>
</form>
<%
}
%>
I use NetBeans IDE 8.2, and something that i think is odd appeared in the debug mode. One of the email i try to test appeared with bold characters meanwhile the other was not bold.
Why is my if statement ignored if i add an user with the exact same email of another? Please help me out!
I have written a code where the admin has the access to change the general users from active to inactive and vice-versa. So I want to update the database if the radio button is changed from active to inactive.
Here is the code:
<%
while (rs.next()) {
String firstname = rs.getString("firstname");
String lastname = rs.getString("lastname");
String email = rs.getString("email");
String password = rs.getString("password");
String age = rs.getString("age");
String sex = rs.getString("sex");
String haddress = rs.getString("haddress");
String oaddress = rs.getString("oaddress");
String phonenumber = rs.getString("phonenumber");
String flag = rs.getString("flag");
Statement stmt1 = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
%>
<tr>
<td>
Name: <% out.println(firstname); %> <% out.println(lastname); %>
</td>
<td>
<% if (flag.equals("A")){ %>
Active: <input type="radio" value="A" name="<% out.println(email); %>" onclick="<% stmt1.executeUpdate("update assignment set flag='A' where email='"+email+"'");
System.err.println("A"+email); %>
alert('changed to active');" checked>
Inactive: <input type="radio" value="I" name="<% out.println(email); %>" onclick="<% stmt1.executeUpdate("update assignment set flag='I' where email='"+email+"'");
System.err.println("I"+email); %>
alert('changed to inactive');">
<%
}else if(flag.equals("I")){%>
Active: <input type="radio" value="A" name="<% out.println(email); %>" onclick="<% stmt1.executeUpdate("update assignment set flag='A' where email='"+email+"'");
System.err.println("A"+email); %>
alert('changed to active');">
Inactive: <input type="radio" value="I" name="<% out.println(email); %>" onclick="<% stmt1.executeUpdate("update assignment set flag='I' where email='"+email+"'");
System.err.println("I"+email); %>
alert('changed to inactive');" checked>
But in output, when I change one radio button, all the queries run automatically, updating the database to I for all the data in the DB.
Using onclick, you need to invoke a ajax call and update the response . You should not use like onclick="<%SOME SQL Query%>". That is why it's updating all the rows.
Step 1:
" onclick="updatestatus(this.value, '<% out.println(email); %>')"/>
Step 2 :
Add Jquery lib and add a JS function
function updatestatus(statuschg, email) {
/*ajax call to some update-status.jsp with email and current value needs to be passed */
//ajax code goes here ...
$.ajax({
type: "post",
url: "update-status.jsp", //this is my servlet
data: "email=" +email"&status="+statuschg,
success: function(msg){
alert(msg);
}
});
}
Ref: How to invoke ajax call How to pass parameters in GET requests with jQuery
step 3:
i) In update-status.jsp,Establish db connection
ii) receive parameters of the email address and current status.
iii) Execute the Query
stmt1.executeUpdate("update assignment set flag='+status+' where email='"+email+"'")
iv) out.println("Updated");
You are mixing two different codes. The key is to realize, where and when each code is executed - JSP on the server when the page is requested and rendered (i.e. before the response is send to the browser) and Javascript in the browser, after the browser receives the already generated response.
I.e. in your
onclick="<% stmt1.executeUpdate("update assignment set flag='I' where email='"+email+"'"); System.err.println("I"+email); %> alert('changed to inactive');"
the <% stmt1.executeUpdate("update assignment set flag='I' where email='"+email+"'"); System.err.println("I"+email); %> part is executed on the server when the page is generated, and only the alert('changed to inactive'); waits in browser until the input field is clicked.
What you need is AJAX.
Side note: Do not put Java code into JSP, use MVC pattern, or at least put the code into an "util" class and call the class from JSP.
I have a Thymeleaf template in a simple Spring Boot application. The template contains a list in a table as follows:
<p>There are <span th:text="${#lists.size(persons)}"></span> people:</p>
<table th:if="${not #lists.isEmpty(persons)}" border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Address</th>
<th>Telephone</th>
<th>Email</th>
<th>Actions</th>
</tr>
<tr th:each="person : ${persons}">
<td th:text="${person.personId}"></td>
<td th:text="${person.name}"></td>
<td th:text="${person.address}"></td>
<td th:text="${person.telephone}"></td>
<td th:text="${person.email}"></td>
<td>
Edit |
Delete
</td>
</tr>
</table>
I want to enable edit and delete functionality as per the last cell in the table. But at the moment both requests are for HTTP GET. That is fine for edit where a person's details are fetched from the server for editing, but delete should trigger a POST request because of the data changes on the server.
Does anyone know if Thymeleaf allow a POST request per row of a table? Or do I have to write a simple HTML form per row?
The GET form is currently:
<td>
Edit
<!--a href="#" data-th-href="#{/delete(personId=${person.personId})}">Delete</a></td-->
<form method="get" th:action="#{/edit(personId=${person.personId})}">
<button type="submit" name="submit" value="value">Edit</button>
</form>
</td>
Where I have a link and a form for testing.
The controller method to be called is:
// Gets a Person.
#RequestMapping(value="/edit", method=RequestMethod.GET)
public String getEditPerson(#RequestParam("personId") String personId, Model model) {
logger.info(PersonController.class.getName() + ".getEditPerson() method called.");
Person person = personDAO.get(Integer.parseInt(personId));
model.addAttribute("person", person);
// Set view.
return "/edit";
}
The error when the button version of GET is called is:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Jul 24 00:26:16 BST 2016
There was an unexpected error (type=Bad Request, status=400).
Required String parameter 'personId' is not present`
I am using GET to trigger editing because no data is sent to the server here other than the personId. No database action is taken so it should be a GET.
you are using Links and I don't think that is possible, you would need to use a form where you can specify the method POST to be used.
In the example below im using a <button> instead of a <a> element, but it will work, the only thing you need to do is to style your button with CSS to look like your links
<form method="POST" th:action="#{/edit(personId=${person.personId})}">
<button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
</form>
now in your code should look like this
<tr th:each="person : ${persons}">
<td th:text="${person.personId}"></td>
<td th:text="${person.name}"></td>
<td th:text="${person.address}"></td>
<td th:text="${person.telephone}"></td>
<td th:text="${person.email}"></td>
<td>
<form method="POST" th:action="#{/edit(personId=${person.personId})}">
<button type="submit" name="submit" value="value" class="link-button">EDIT</button>
</form> |
<form method="POST" th:action="#{/delete(personId=${person.personId})}">
<button type="submit" name="submit" value="value" class="link-button">DELETE</button>
</form>
</td>
</tr>
EDIT
As you just shared you Java code, in the controller you are expecting the personId not as a PathVariable, but as a RequestParam,
in that case your form should have that value...
edit your form and add the person id as follows.
<form method="POST" th:action="#{/edit}">
<input type="hidden" name="personid" id="personId" th:value="${person.personId}" />
<button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
</form>
Notice also I changed the action of the form to be just /edit, as its what your controller looks like
Does anyone know if Thymeleaf allow a POST request per row of a table? Or do I have to write a simple HTML form per row?
HTML doesn't support POST request with links and you have to use forms (as Rayweb_on explained). But Thymeleaf allows you to define custom tags which helps a lot :
<a th:href="#{/edit(personId=${person.personId})}" custom:linkMethod="post">Edit</a>
... which would generate following HTML (assuming jQuery is available) :
Edit
Custom tag definition (without error checking to keep it simple) :
/**
* Custom attribute processor that allows to specify which method (get or post) is used on a standard link.
*/
public class LinkMethodAttrProcessor extends AbstractAttributeTagProcessor {
private static final String ATTR_NAME = "linkMethod";
private static final int PRECEDENCE = 10000;
public LinkMethodAttrProcessor(final String dialectPrefix) {
super(
TemplateMode.HTML, // This processor will apply only to HTML mode
dialectPrefix, // Prefix to be applied to name for matching
null, // No tag name: match any tag name
false, // No prefix to be applied to tag name
ATTR_NAME, // Name of the attribute that will be matched
true, // Apply dialect prefix to attribute name
PRECEDENCE, // Precedence (inside dialect's own precedence)
true); // Remove the matched attribute afterwards
}
#Override
protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag,
final AttributeName attributeName, final String attributeValue,
final IElementTagStructureHandler structureHandler) {
// get the method name (tag parameter)
final IEngineConfiguration configuration = context.getConfiguration();
final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);
final IStandardExpression expression = parser.parseExpression(context, attributeValue);
final String method = (String) expression.execute(context);
// add custom javascript to change link method
final String link = tag.getAttribute("href").getValue();
final String action = "$('<form action="" + link + "" method="" + method + ""></form>').appendTo('body').submit(); return false;";
structureHandler.setAttribute("onclick", action);
structureHandler.setAttribute("href", "#");
}
}
See the Thymelead documentation for example of how this custom attribute needs to be registered.