Reputation: 959
I have a billing application that takes a request check in the db if the customer has already paid, if not paid it hits a billing API and then update the response in the database.
I am facing issues when the customer send request multiple time by clicking the "Bill me" button 3-4 times. All request are hitting the server with a difference in ms. As a result, the customer is getting charged multiple times because the result didn't get updated as the first request takes some time and in the meantime the second request read the status from the db and go again for charging. Below is the code. Please let me know what best practices I should follow to prevent the same. I have tried making the servlet SingleThreadModel
but it didn't help
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
String mobilenumber = request.getParameter("mobilenumber");
String param2 = request.getParameter("param2");
String checkifthecustomerischarged = checkifcharge(mobilenumber);
if (checkifthecustomerischarged.equals("NOTOK")) {
String status = hittocharge(mobilenumber, param2);
int i = updatestatus(mobilenumber, status);
if (i > 0) {
out.println("Status Updated ");
} else {
out.println("Status Not update Updated ");
}
} else {
out.println("Already Charged");
}
}
}
here I am checking in the table
private String checkifcharge(String mobilenumber) {
String st = "NOTOK" ;
try {
Connection conn = null ;
ResultSet rs = conn.createStatement.executeQuery("select sno from table where mobilenumber = "+mobilenumber);
if(rs.next()){
st = "OK";
}
} catch (Exception e) {
e.printStackTrace();
}
return st ;
}
here i am updating the status
private int updatestatus(String mobilenumber, String status) {
int st = 0 ;
try {
Connection conn = getConnection() ;
st = conn.createStatement.executeQuery("update table set status =1 where mobilenumber ="+mobilenumber);
releaseConnection(conn);
} catch (Exception e) {
e.printStackTrace();
}
return st ;
}
Upvotes: 3
Views: 66
Reputation: 2381
Normally, people don't just say "bill me" but "bill me for something specific" (e.g. "august 2015 payment for mobile number 123"). I would decide on an identifier for each billing (e.g. "08_2015_123") and include it in the billing request as well as the status table. Then you can use optimistic update, which is something in the lines of
st=statement.executeQuery("update table set status=1 where identifier='08_2015_123' and status<>1")
// if st==0 it probably means bill was previously payed, don't bill again
BTW even if you're absolutely sure you can't generate such an identifier, you could always generate some dummy random field in your form, so that at least you can identify multiple quick clicks on the same button (though it won't help for more complex situations, e.g. user that forgot that he payed a week ago). However with billing I would make an effort to find a proper identifier.
Upvotes: 2