How to know from which jsp page the request has come to the controller in Spring MVC - spring

I am developing an app where LoginForm.jsp and UserRegistration.jsp will lead to UserAccount jsp page on specific action.In LoginForm when a user presses a 'Login' button ->UserAccount form is displayed.In UserRegistration Form when details are entered and submitted ->UserAccount form is displayed.
Below is the controller code when a request comes as UserAccount.html
#RequestMapping(value="/UserAccount.html", method = RequestMethod.POST)
public ModelAndView userAccountForm(#Valid #ModelAttribute("user") UserDetails user,BindingResult result) {
if(result.hasErrors())
{ System.out.println(result.getAllErrors());
ModelAndView model1=new ModelAndView("UserRegistration");
return model1;
}
// User validation
System.out.println(user.getAccountType());
userDAO.create(user);
ModelAndView model1 = new ModelAndView("UserAccount");
return model1;
}
LoginForm.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<body>
<h1
style="background-color: green; color: Yellow; padding: 10px; text-align: center;">Mybank
Online Login</h1>
<form:errors path="user.*" />
<form action="/MyBankProject/UserAccount.html" method="post">
<div
style="background-color: yellow; color: black; padding: 10px; text-align: center;"
align="center">
<p>
User ID <input type="text" name="userName" />
</p>
<p>
Password <input type="password" name="password" />
</p>
<input type="submit" value="Login" /> New User?
</div>
<input type="hidden" name="page" value="LoginForm"/>
</form>
</body>
</html>
UserRegistration.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<body>
<h1>${headerMessage}</h1>
<h3>USER REGISTRATION</h3>
<form:errors path="user.*" />
<form action="/MyBankProject/UserAccount.html" method="post">
<table border="1" style="width:100%" >
<tr>
<td>FirstName :</td>
<td><input type="text" name="firstName" /></td>
</tr>
<tr>
<td>LastName :</td>
<td><input type="text" name="lastName" /></td>
</tr>
<tr>
<td>User's EmailId :</td>
<td><input type="text" name="emailId" /></td>
</tr>
<tr>
<td>user's gender :</td>
<td><select name="gender" multiple>
<option value="M">Male</option>
<option value="F">Female</option>
</select></td>
</tr>
<tr>
<td>user's age :</td>
<td><input type="text" name="age" /></td>
</tr>
<tr>
<td>user's DOB :</td>
<td><input type="text" name="dOB" /></td>
</tr>
<tr>
<td>Account Type :</td>
<td><select name="accountType" multiple>
<option value="Savings">Savings</option>
<option value="Current">Current</option>
<option value="FixedDeposit">Fixed Deposit</option>
</select>
<td>
</tr>
<tr>
<td>Amount :</td>
<td><input type="text" name="amount" /></td>
</tr>
</table>
<table>
<tr>
<td>UserName</td>
<td><input type="text" name="userName" /></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password" /></td>
</tr>
</table>
<table>
<tr>
<td>User's Address :</td>
</tr>
<tr>
<td>country: <input type="text" name="address.country" /></td>
<td>city: <input type="text" name="address.city" /></td>
<td>street: <input type="text" name="address.street" /></td>
<td>pincode:<input type="text" name="address.pincode" /></td>
</tr>
<tr>
<td><button type="submit">Submit</button></td>
<td><input type="button" onclick="history.back();"
value="Cancel"></td>
</tr>
</table>
<input type="hidden" name="page" value="UserRegistration"/>
</form>
</body>
</html>
Now for me I need to know the jsp page from which the UserAccount invoked ,to perform different actions based on that.
I am new to Spring MVC and searched all over the internet for the solution.

HTTP is a stateless protocol. This means that you can not make assumptions about previous states.
I think you have two options to get information about the previous page anyways.
Add a hidden field to your form and send the name of the page with the request.
HTML:
<form>
<input type="hidden" name="page" value="[the name of the current page]"/>
</form>
Controller:
#RequestMapping(value="/UserAccount.html", method = RequestMethod.POST)
public ModelAndView userAccountForm(#RequestParam(value="page", required=false) String page) {
[...]
}
Now you can check the page value.
Use the session. Store the current page in the controller methods that render the form:
#RequestMapping("/login")
public String login(HttpServletRequest request) {
request.getSession().setAttribute("lastPage", "login");
return "redirect:/UserAccount.html";
}
#RequestMapping("/register")
public String register(HttpServletRequest request) {
request.getSession().setAttribute("lastPage", "register");
return "redirect:/UserAccount.html";
}
Check the lastPage value in userAccountForm():
#RequestMapping(value="/UserAccount.html", method = RequestMethod.POST)
public ModelAndView userAccountForm(HttpServletRequest request) {
HttpSession session = request.getSession();
String lastPage = (String) session.getAttribute("lastPage");
session.removeAttribute("lastPage");
[...]
}
Check the referer field of the request header.
#RequestMapping(value="/UserAccount.html", method = RequestMethod.POST)
public ModelAndView userAccountForm(#RequestHeader(value = "referer", required = false) String referer) {
[...]
}
This gives you the referer as a method argument if there is one. Be careful. It is possible that there was no referer or that the field was manipulated by the client.

Hope this will solve your need.
URL url = new URL(request.getHeader("referer"));
System.out.println("last page url"+ url.getPath());
if(url.getPath().equals("your last url"){
//code
}

Related

Thymeleaf - set attributes for objects in forms with hidden inputs

I got this peace of html:
<form action="#" th:action="#{${cartServiceBaseUrl}+'/addCatalogItemToCart'}" th:object="${cartCatalogItem}" method="post">
<input type="hidden" th:value="${cartId}" th:field="*{cartId}" />
<input type="hidden" th:value="${catalogItem.catalogItemId}" th:field="*{catalogItemId}" />
<input type="submit" value="add to cart" />
</form>
Unfortunately both values are null and I dont really understand why, because both values, cartId and catalogItem.catalogItemId are available on the page.
How can I properly pass them?
Java endpoint
#PostMapping(ADD_CATALOG_ITEM_TO_CART)
public void addCatalogItemToCart(#ModelAttribute CartCatalogItem cartCatalogItem, HttpServletResponse response) {
Full HTML:
<h1 th:text="${catalog.name}">...</h1>
<a th:href="#{${customerServiceBaseUrl}+'/home/'+__${cartId}__}">home</a>
<p th:text="'Catalog ID:'+${catalog.catalogId}"></p>
<p th:text="'Name: '+${catalog.name}"></p>
<table>
<th:block th:each="catalogItem : ${catalog.catalogItems}">
<tr>
<th>article id</th>
<th>catalogitem id</th>
<th>name</th>
<th>price</th>
</tr>
<tr>
<td th:text="${catalogItem.articleId}">...</td>
<td th:text="${catalogItem.catalogItemId}">...</td>
<td th:text="${catalogItem.name}">...</td>
<td th:text="${catalogItem.price}">...</td>
<td><form action="#" th:action="#{${cartServiceBaseUrl}+'/addCatalogItemToCart'}" th:object="${cartCatalogItem}" method="post">
<input type="hidden" th:value="${cartId}" th:field="*{cartId}" />
<input type="hidden" th:value="${catalogItem.catalogItemId}" th:field="*{catalogItemId}" />
<input type="submit" value="add to cart" />
</form></td>
</tr>
</th:block>
</table>
My goal: assign attributes to objects with hidden input fields and pass them for the controller methods.
You are not set your values from controller that's why there are both values null.
Use this code on your controller.
For example:
Model and View model=new Model and View ("Your thyme leaf template name");
model.put('your key name by which you an access on your thyme leaf
page',cart Id);
return model;
This will work.

Why Http status code 404 shows when I click on submit using war file deployed

Image 1. Successful GET request
Image 2. Failed POST when click on submit
Welcome page i.e. index.jsp aprears on localhost:8080/war_filename
but when we click on login in index page it shows http status code 404
Is anyone there, who's having the same issue?
I've copied the war file in apache\webapps
WebController.java
#Controller
public class indexController {
String errorMessage = "Invalid credentials";
#GetMapping("/login")
public String login() {
return "index.jsp";
}
/*********** Login using form ************/
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#RequestParam("firstname") String firstName,
#RequestParam("lastname") String lastName) {
System.out.println("inside login form");
Customer object = repository.findByFirstNameAndLastName(firstName,
lastName);
if (object != null) {
return "home.jsp";
}
return "index.jsp";
}
}
index.jsp
<h3>Do Login Here</h3>
<form method="POST" action="/login">
<table>
<tr>
<td>Employee ID</td>
<td><input type="text" name="firstname" placeholder="Username" required></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="lastname" placeholder="Password" required></td>
</tr>
<tr>
<td><input type="submit" value="Login" /></td>
</tr>
</table>
</form>
home.jsp
<body>
<h3>Operations</h3>
<form action="/selectusingform" method="get">
Select
</form>
<table>
<tr>
<td>Insert</td>
</tr>
<tr>
<td>Update</td>
</tr>
<tr>
<td>Delete</td>
</tr>
<tr>
<td>Find</td>
</tr>
</table>

Write handler methods for dynamically generated buttons and text boxes

I have this small data on JSP form. I use JSTL to iterate over data. In each row, I have two dynamically generated textboxes and a button. Question is: how do I write a generic handler method for this data, which handles dynamically generated textboxes and buttons. Here is my JSP
<c:forEach items="${menus}" var="menu" >
<tr>
<td align="left" >${menu.getMenuId()}</td>
<td align="right"><input type="text" name="menu_name" value="${menu.getMenuName()}"/></td>
<td align="right"><input type="text" name="menu_price" value="${menu.getMenuPrice()}"/></td>
<td align="right"><c:out value="${menu.getIsAvailable()}" /></td>
<td align="right"><input type="submit" value="Add Item ${menu.getMenuId()}"></td>
</tr>
</c:forEach>
<h4>Add Product</h4>
Name: <input type="text" name="chosen_menu_name" />
Price: <input type="text" name="chosen_menu_price" />
<input type="submit" value="Add to cart">
And here is my controller (though I dont know what to put it there - at the moment I am using two seperate textbox and a button for taking the input)
#RequestMapping(method = RequestMethod.POST)
public ModelAndView AddMenu(#RequestParam("chosen_menu_name") String mymenu, #RequestParam("chosen_menu_price") String menu_price, #ModelAttribute("cart") ArrayList<Menu> mycart, Model model)
{
Menu menu = new Menu();
menu.setMenuId(0);
menu.setMenuName(mymenu);
menu.setMenuPrice(Double.parseDouble(menu_price));
model.addAttribute("menus", GetMenus());
mycart.add(menu);
return new ModelAndView("edit_menu");
//return "show_menu";
}
As one can see from the JSP, I am using two seperate textboxes and a button for taking input and passing it to the controller. How do I write a generic handler method for this data, which handles dynamically generated textboxes and buttons?
I'm assuming that you don't want those other two field and button. You want to add items directly from table.
You have to make each and every row as one form like below :
<c:forEach items="${menus}" var="menu" >
<tr>
<form method="POST" action="controllerName">
<td align="left">
${menu.getMenuId()}
<input type="hidden" name="menu_id" value="${menu.getMenuId()}"/>
</td>
<td align="right">
<input type="text" name="menu_name" value="${menu.getMenuName()}"/>
</td>
<td align="right">
<input type="text" name="menu_price" value="${menu.getMenuPrice()}"/>
</td>
<td align="right">
<c:out value="${menu.getIsAvailable()}"/>
</td>
<td align="right">
<input type="submit" value="Add Item">
</td>
</form>
</tr>
</c:forEach>
And controller like below:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView AddMenu(#RequestParam("menu_id") String menuId, #RequestParam("menu_name") String mymenu, #RequestParam("menu_price") String menu_price, #ModelAttribute("cart") ArrayList<Menu> mycart, Model model)
{
Menu menu = new Menu();
menu.setMenuId(menuId);
menu.setMenuName(mymenu);
menu.setMenuPrice(Double.parseDouble(menu_price));
model.addAttribute("menus", GetMenus());
mycart.add(menu);
return new ModelAndView("edit_menu");
//return "show_menu";
}

Spring MVC - Submit Form 400 Error

I'm just begin writing an application using Spring MVC. I have 2 entities, District & City. A City has many districts, and each district belongs to a city.
In district.jsp I declare a form, allowing user input of the district name and a selection box to choose the City it belongs to.
The District entity looks like this:
<form:form action="${aAction}" commandName="district">
<table>
<c:if test="${!empty district.districtName}">
<tr>
<td>
<form:label path="id">
<spring:message text="ID"/>
</form:label>
</td>
<td>
<form:input path="id" readonly="true" size="8" disabled="true" />
<form:hidden path="id" />
</td>
</tr>
</c:if>
<tr>
<td>
<form:label path="districtName">
<spring:message text="District Name"/>
</form:label>
</td>
<td>
<form:input path="districtName" />
</td>
</tr>
<tr>
<td>
<form:label path="belongToCity">
<spring:message text="Belong to City"/>
</form:label>
</td>
<td>
<c:if test="${!empty listCities}">
<form:select path="belongToCity" items="${listCities}" itemLabel="cityName" itemValue="id"></form:select>
</c:if>
</td>
</tr>
<tr>
<td colspan="2">
<c:if test="${!empty district.districtName}">
<input type="submit"
value="<spring:message text="Edit District"/>" />
</c:if>
<c:if test="${empty district.districtName}">
<input type="submit"
value="<spring:message text="Add District"/>" />
</c:if>
</td>
</tr>
</table>
</form:form>
In my district controller I declare add action.
#RequestMapping(value = {"/district/add"}, method = RequestMethod.POST)
public String addDistrict(#ModelAttribute("district") District p,Model model, BindingResult result) {
if(result.hasErrors()) {
return "district";
}
this.districtService.addDistrict(p);
return "district";
}
When I run my project, however, it shows a 400 error and the error message: "The request sent by the client was syntactically incorrect."
I suspect my form is wrong somewhere, maybe it is not able to post to controller processing. Could someone help me identify the issue?
Your BindingResult parameter should be adjacent to modelAttribute. Below should be method signature.
#RequestMapping(value = {"/district/add"}, method = RequestMethod.POST)
public String addDistrict(#ModelAttribute("district") District p, BindingResult result, Model model) {
if(result.hasErrors()) {
return "district";
}
this.districtService.addDistrict(p);
return "district";
}

Safari, MVC3 ajax form submit

I have a form that submits just fine in FF, IE 8, IE 9, chrome.
In safari (windows), it submits but my model is empty. This behavior is only on my dev and prod site, not local development. Local development works normal. What am i doing wrong here?
Form:
<form action="/NetSite/Applications/ElectronicFileTransfer" id="TransfersSearchForm" method="post">
<table class="siteTable">
<tbody>
<tr>
<th style="width: 20%;">FICE</th>
<td style="width: 80%;"><input id="Criteria_Fice" maxlength="6" name="Criteria.Fice" size="6" type="text" value="" /></td>
</tr>
<tr>
<th>Source Email</th>
<td><input id="Criteria_SourceEmail" maxlength="40" name="Criteria.SourceEmail" size="25" type="text" value="" /></td>
</tr>
<tr>
<th>Target Email</th>
<td><input id="Criteria_TargetEmail" maxlength="100" name="Criteria.TargetEmail" size="25" type="text" value="" /></td>
</tr>
<tr>
<th>Upload From Date</th>
<td>
<input class="datePicker" data-val="true" data-val-date="Invalid date specified. Date should be like MM/DD/YYYY." id="Criteria_FromDate" maxlength="12" name="Criteria.FromDate" size="12" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Criteria.FromDate" data-valmsg-replace="true"></span>
</td>
</tr>
<tr>
<th>Upload To Date</th>
<td>
<input class="datePicker" data-val="true" data-val-date="Invalid date specified. Date should be like MM/DD/YYYY." id="Criteria_ToDate" maxlength="12" name="Criteria.ToDate" size="12" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Criteria.ToDate" data-valmsg-replace="true"></span>
</td>
</tr>
<tr>
<th class="empty"></th>
<td>
<button type="submit" title="Search" id="SubmitButton" class="gradientbutton gradientsmall gradientorange">Search</button>
<button type="button" title="Clear" id="ClearButton" class="gradientbutton gradientsmall gradientorange">Reset</button>
</td>
</tr>
</tbody>
</table>
</form>
JS submit method called by the event:
searchFormSubmit: function ($form, currentForm) {
if ($form.valid()) {
var $button = $("#" + FileTransferHome._enum.SubmitButton);
var $searchResults = $("#" + FileTransferHome._enum.SearchResultsDivId);
jMessage("Processing request...", $button, true, false);
$.ajax({
cache: false,
url: currentForm.action,
type: currentForm.method,
data: $form.serialize(),
error: function (xhr, ajaxOptions, thrownError) {
jMessageHide();
$searchResults.html(xhr.responseText).addClass(JSGlobalVars.MessageBoxError).fadeIn('slow');
},
success: function (result) {
jMessageHide();
$searchResults.removeClass(JSGlobalVars.MessageBoxError).html(result).fadeIn('slow');
location.hash = "SEARCHRESULTS";
}
});
}
}
Action:
I have an else block in there that i have put in just to test this case and it executes rather than the main block.
[HttpPost]
public ActionResult Index(ElectronicFileTransferHomeViewModel model)
{
... actions...
}
This in as internal app and behind windows login. Safari has a non issue with with windows authentication.
A work around that seems to be working for us (although not ideal) is to put Safari in Private browsing mode.

Resources