Ive checked many similar questions but none of them has a working solution in my case.
I'm trying to make a dropdown selection for my user registration form using spring form:select tag. In my bean, country is set as ManyToOne so I pass a map for selecting the value.
Im bouncing between: Neither BindingResult nor plain target object for bean name 'register' available as request attribute. And: commandName not found blabla...
Help me understand what is going on and how to fix it.
It migth be interesting to know that I'm mounting my views through a MergedOutputModel (uses two redirects to mount the view), hence the Session variables.
Code below(simplified to where the problem is appearing).
Controller class:
#Transactional
#Controller
public class RegisterController {
#Autowired
public CountryDao cDao;
#RequestMapping("register")
public String register(Model model, #ModelAttribute("user") User user, BindingResult result, HttpSession session) {
session.setAttribute("user", user);
session.setAttribute("countryList", cDao.getCountryMap());
return "login/registerForm";
}}
View:
<body>
<h1>
<spring:message code="register.message" />
</h1>
[...]
<form:form action="addUser" commandName="register" method="post">
[...]
<spring:message code="register.country" />
<form:select path="country" items="${countryList}" />
[...]
<input type="submit" value="<spring:message code='register.submit'/>" />
</form:form>
</body>
This may get you closer to what you need. Your flow could be slightly different, so you can adjust the page names as needed.
#Controller
#SessionAttributes("countryList") //add whatever session attributes as needed
public class RegisterController {
#RequestMapping("/registerForm", method = RequestMethod.GET)
public String registerGet(Model model) {
model.addAttribute("user", myUserService.createUser());
model.addAttribute("countryList", countryDao.getCountryMap());
return "login/registerForm";
}
#RequestMapping("/registerVerify", method = RequestMethod.POST)
public String registerPost(#ModelAttribute("user") User user,
Errors result) {
if (result.hasErrors()) {
FormValidationLogger.log(log, result);
return "login/registerForm";
}
//persist, send emails, or do whatever
return "registerVerify"; //or whatever page
}
#Autowired
private CountryDao countryDao; //put these at the bottom so we don't have to scroll as much to get to the meat of the code
}
I don't readily see the need for #Transactional in the code you posted. I would expect that in your service or DAO layer.
<body>
<h1>
<spring:message code="register.message" />
</h1>
[...]
<form:form modelAttribute="user" action="/registerVerify" method="post">
[...]
<spring:message code="register.country" />
<form:select path="country" items="${countryList}" />
[...]
<input type="submit" value="<spring:message code='register.submit'/>" />
</form:form>
</body>
This assumes that country is a property of user. You also may want to change the method name to something like getCountries() instead of getCountryMap().
Related
I'm using Thymeleaf and Spring Boot to try and send data to a server, but I can't even load the page because any instance of th:field results in that error.
HTML form template is here:
<form action="#" method="post" th:action="#{/flow}" th:object="${flow}" id="myForm">
<input type="text" name="mouseX" th:field="*{xpos}"id="mouseX" value="0">
<input type="text" name="mouseY" th:field="*{ypos}" id="mouseY" value="0">
<button type="submit">submit</button>
</form>
Controller is here:
public class MainController {
#GetMapping("flow")
public String generateImg(Model model, BindingResult br) {
model.addAttribute("Flow", new Flow());
return "flow";
}
#PostMapping("flow")
public String imgGen( #ModelAttribute("flow") Flow flow, Model model, BindingResult br) {
return "flow";
}
}
I've tried a couple different things, adding and removing parameters, renaming my object, changing form action, and none seem to have any effect.
I'm creating a web shop in JSP for a school project.
On each product page, there's a button to add it to the cart.
Originally, there is only one item added to the cart when we press the "Add" button.
I send the productId to add to the controller by adding it as parameter in the url as you can see here :
<div class="product-page">
<div class="product">
<h1>${product.title}</h1>
<img src="${product.imageUrl}"/>
<div class="price"><p>${product.price}€</p></div>
</div>
<c:url var="addLineToCart" value="/product/addLineCart">
<c:param name="productId" value="${product.id}" />
</c:url>
<a id="addToCart" type="submit" href="${addLineToCart}"><spring:message code="addCart"/></a>
What I'd like to do, is to add an input field to specify the amount of items to add in the cart. I did it here :
<div class="product-page">
<div class="product">
<h1>${product.title}</h1>
<img src="${product.imageUrl}"/>
<div class="price"><p>${product.price}€</p></div>
</div>
<input type="number" name="quantity" value="1"/>
<c:url var="addLineToCart" value="/product/addLineCart">
<c:param name="productId" value="${product.id}" />
</c:url>
<a id="addToCart" type="submit" href="${addLineToCart}"><spring:message code="addCart"/></a>
My problem is that I don't know how to pass the value from the input field in the <c:param/> property in order to add it in the URL too.
Here is how my controller looks like assuming I get the quantity to add via the URL :
#Controller
#RequestMapping(value="/product")
#SessionAttributes({Constants.CURRENT_CART})
public class ProductController {
private ProductDAO productDAO;
#Autowired
public ProductController(ProductDAO productDAO){
this.productDAO = productDAO;
}
#ModelAttribute(Constants.CURRENT_CART)
public Cart cart()
{
return new Cart();
}
#RequestMapping (method = RequestMethod.GET)
public String home(ModelMap model, #RequestParam("product") int productId, #ModelAttribute(value=Constants.CURRENT_CART) Cart cart){
Product product = productDAO.getById(productId);
model.addAttribute("product", product);
model.addAttribute("title", "Produit");
model.addAttribute("cart", cart);
return "integrated:product";
}
#GetMapping("/addLineCart")
public String addLineCart(#ModelAttribute(value=Constants.CURRENT_CART) Cart cart, #RequestParam("productId") int productId, #RequestParam("quantity") int quantity, ProductService productService)
{
Product product = productService.searchProduct(productId,productDAO);
cart.addProduct(product, quantity);
return "redirect:/product?product=" + productId;
}
}
Thanks for your help.
The easiest way is to wrap the fields in a HTML <form> tag and submit the data to your controller. You should also replace GET with a POST since your browser might decide to cache the response to some combinations of productId and quantity and your application might exhibit some unwanted behavior as result of that (don't forget to change your #GetMapping in your controller with a #PostMapping also).
There is also the option of submiting this to the server with JavaScript as an Ajax request, or to change the value of the URL in your existing link to include the quantity when you click it and before making the request to the server, but using a form with a POST action is the easiest and cleanest solution.
Finally, <c:url> and <c:param> are server side tags. They get evaluated at the server to produce your final HTML that gets sent to the client browser. You can't get your input value from the browser into your <c:param> because you are running client code at this point, no longer server code.
Searched all over the Internet and tryed different solutions, but somehow no one worked in my case.
I have following html template for a view where you should register yourself:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" type="text/css" th:href="#{/css/style.css}" />
<!-- Page title -->
<title> Register</title>
</head>
<body>
<form action="#" th:action="#{/registeruser}" th:object="${user}" method="post">
<input type="text" th:field="*{username}" />
<input type="text" th:field="*{email}" />
<input type="text" th:field="*{password}" />
<input type="submit" />
</form>
</body>
</html>
also here is the controller:
#Controller
public class RegisterController {
#Autowired
private UserService userservice;
#Autowired
private RoleService roleService;
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String regUser(Model model) {
User u = new User();
u.setUsername("username");
u.setPassword("password");
u.setEmail("email");
Set<Role> userRoles = new HashSet<>();
userRoles.add(roleService.findRoleByName("ROLE_USER"));
u.setRoles(userRoles);
System.out.println("test");
model.addAttribute("user", u);
return "register";
// return new ModelAndView("register", "command", new User());
}
#RequestMapping(value = "/registeruser", method = RequestMethod.POST)
public String addUser(#ModelAttribute(value = "user")User user,
ModelMap model) {
model.addAttribute("username", user.getUsername());
model.addAttribute("password", user.getPassword());
model.addAttribute("email", user.getEmail());
System.out.println("user " + user.getUsername() + "got registered, here a list of all users: " );
return "login";
}
}
The console print test works in the regUser() method but somehow the console print in the addUser() method does not work, so I guess it does not get triggered?
Also the View works perfect and I get redirected after submitting to the login page, but this is also the defaultSuccesFulUrl so it probably means nothing.
Kinda frustrated on this one, so it would be really nice if you could help.
Thanks in advance.
Try removing action="#" in your form. This may be stepping on the one that's generated through Thymeleaf.
Aside:
You can use #GetMapping and #PostMapping as shorthand for your
mappings.
You'll want to change it to input type="password"
You can use Model instead of ModelMap
Use #Slf4j and a logging system of your choice
Change your POST method to
#RequestMapping(value = "/registeruser", method = RequestMethod.POST)
public String addUser(User user) {
...
Also is better if in your submit, says is a button
<button type="submit">Submit</button>
And as said bphlilipnyc remove the action="#"
I am still relatively new to springMVC, I currently have some code, that will take an input from a <form:input> on a jsp page, and create different lists depending on the input(providing I enter the correct String). I would like to transition this into a button instead, so I could have four buttons that will return a different String, for example "one", "two", "three" and "four". That way there is no typing needed from the user.
I see that there is a <form:button> available but I do not know how I could return the String value from this. Also I have looked into angularJS and seen that you can call a function onClick. But again, I don't know what the implementation would have to be to tie it into my Controller. I am just not really sure how I can implement this. Any help would be appreciated.
This is what I have being implemented at the moment :
<form:form commandName="input">
<label>Enter Value</label>
<form:input path="listType" class="inputbox" />
<br>
<input type="submit" class="button" value="Enter" />
</form:form>
This takes the input and stores it in an object :
#Controller
#SessionAttributes("input")
public class EventController {
#RequestMapping(value = "/event", method= RequestMethod.GET)
public String displayEvent (Model model) {
AccessInput userInput = new AccessInput();
model.addAttribute("input", userInput);
System.out.println("finished get method");
return "event";
}
#RequestMapping(value = "/event", method= RequestMethod.POST)
public String processEvent(#ModelAttribute("input")AccessInput userInput) {
System.out.println(userInput.getListType()); //just so I know what value it has
return "redirect:results.html";
}
This is the controller that creates my list based on the string that I pass through to the object
#RestController
#SessionAttributes("input")
public class ReportController {
#RequestMapping(value="/events")
public List<Appliance> getEvents(#ModelAttribute("input")AccessInput userInput) {
List<Appliance> events = new ArrayList<>();
events = ProcessChoice.ofList(userInput.getListType());
System.out.println(userInput.getListType());
return events;
}
}
Edit:
Just to note I have resolved this, I followed the example given by Vipin Dubey, I had to change my controller. I removed the POST method and added in a #RequestParam as a parameter, and redirected the buttons on the event.jsp to "results.html?input=one" then took this value and added it to my model to store it in the session.
#Controller
#SessionAttributes("URLparam")
public class ResultController {
#RequestMapping(value = "/results.html", method = RequestMethod.GET)
public String buttonSelect(Model model, #RequestParam("input")String input) {
model.addAttribute("URLparam", input);
System.out.println(input);
return "result";
}
}
You have two options :
1. Short and recommended way :
Use a link and style it as a button and you can directly call your controller
<a class="btn" href="/events?input=one">One</a>
<a class="btn" href="/events?input=two">two</a>
<a class="btn" href="/events?input=three">three</a>
<a class="btn" href="/events?input=four">four</a>
2. Use jQuery or JavaScript to submit the form based on clicked button using a hidden input field in your form
<!-- Buttons with classes -->
<div id="target">
<button class="one">One</button>
<button class="two">two</button>
<button class="three">three</button>
<button class="four">four</button>
</div>
<!-- Your form -->
<form:form commandName="input" id="myForm">
<input type="hidden" name="inputbox" id="inputbox" value=""/>
</form:form>
// You will have to do this for each of the button which is not a recommended way
$( ".one" ).click(function() {
$('input[name="inputbox"]').val("one");
//var a = $('input[name="inputbox"]').val();
//alert(a);
$( "#myForm" ).submit();
});
I have a problem in my form action in Spring MVC.
My code:
<form method="POST" action="j_acegi_security_check" name="frmLogin">
<input type='hidden' autocomplete="off" name='_schema' id="_schema"/>
<input type='hidden' id='j_username' name='j_username' autocomplete="off" />
<input type='hidden' id='j_password' name='j_password' autocomplete="off" />
</form>
I can't understand what kind of action is j_acegi_security_check perfoming.
For Form Action, you need to land your request to the controller you created for. Specify your request name for example
This is HTML part <form:form method = "POST"action="/addUser">...</form:form>
For your controller class
#Controller
public class UserController {
#RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String addStudent(#ModelAttribute("SpringWeb")User user,
ModelMap model) {
}
Your request will be landed to this controller where you can perform any desired action.
Hope this will help.