I am trying to get a value from thymeleaf input into my java class.
Simple script from thymeleaf
<h1>Form</h1>
<form action="#" th:action="#{index}" th:object="${emails}" method="post">
<p>Emails: <input id="emailbox" type="text" th:field="*{email}"
placeholder="Enter e-mails: eg; Foo#gmail.com, Bar#yahoo.com"/></p>
<p><input type="submit" value="Submit"/> <input type="reset" value="Reset"/></p>
</form>
How would I be able to retrieve the inputted text into my java class?
Controller
#Controller
public class IndexController {
#RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView getdata() throws IOException {
ModelAndView model = new ModelAndView("index");
model.addObject("emails", new MailModel());
return model;
}
#PostMapping("/index")
public String emailSubmit(#ModelAttribute MailModel emails) {
System.out.println(emails.getEmail());
return "index";
}
I am able to run my application and see thymeleaf view. When I enter some text into the text box and hit submit. I receive an error.
Error Message
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'emails' available as request attribute
My Application is created with Springboot, Java, and Thymeleaf. What am I doing wrong? Is it possible that ModelandView does not work with PostMapping? I also followed https://spring.io/guides/gs/handling-form-submission/ and I got that sample working, but when I tried to follow the logic and implement into my project. It did not work.
In your HTML, change th:action="#{index}" to th:action="#{/index}". This will allow Thymeleaf to resolve it properly.
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 have currently built a controller for my index page which is also a login page.
With the controller, I'm mapping the jsp if the login credentials of the user matches and if it doesn't I want to redirect to the index page with message "Sorry Username, Password error."
Here's the code:
Controller
if(uname.equals(inf.getUsername())&&pwd.equals(inf.getPassword())&&dept.equals(inf.getDept()))
{
req.getSession().setAttribute("uname",inf.getName());
return new ModelAndView("employeeLoginResult", "message", message1);
}
else if(uname.equals(inf2.getUsername())&&pwd.equals(inf2.getPassword())&&dept.equals(inf2.getDept()))
{
req.getSession().setAttribute("uname",inf2.getName());
return new ModelAndView("adminLoginResult", "message", message2);
}
else
{
return new ModelAndView("redirect:/index.jsp","message","Sorry");
}
The index page
<b><span class="heading">LOGIN USER</span></b>
<div class="container">
<form action="login.html" method="Post">
<div class="form_style">
<input type="text" name="username" placeholder="Enter Username"/>
<input type="password" name="pwd" placeholder="Enter password"/>
<select name="dept">
<option>IT</option>
<option>Admin</option>
<option>HR</option>
<option>Marketing</option>
</select>
<input type="Submit" value="submit">
<span class='disp'>${message}</span>
</div>
</form>
</div>
The redirect works but the message get appended in the Url like this:
I just want to print "Sorry username password error" on the index file with ${message}
My question:
Is it possible to use ModelAndView with RedirectView or if it isn't are there any other solution to send redirect to my index page with using ModelAndView?
Any suggestions or opinions are appreciated.
Thanks for the same.
"The redirect works but the message get appended in the Url " this is the expected behaviour of normal redirection attributes.
You can use flash attributes to redirect by not revealing the URL in the browser.
For example refer below code :
#RequestMapping(value = "/accounts", method = RequestMethod.POST)
public String handle(Account account, BindingResult result, RedirectAttributes redirectAttrs) {
if (result.hasErrors()) {
return "accounts/new";
}
// Save account ...
redirectAttrs.addAttribute("id", account.getId()).addFlashAttribute("message", "Account created!");
return "redirect:/accounts/{id}";
}
Refer this : https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html
Can you add a class like MyConfig
#EnableWebMvc
#Configuration
public class MyConfig {
#Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
#PostConstruct
public void init() {
requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
}
}
I have a table for adding one object to another and deleting one object from another.
This is my controller:
#Controller
#RequestMapping("/proj/{pid}/coupling/{r1}")
public class CouplingController {
#RequestMapping(method = RequestMethod.GET)
public String getAllCouplings( ){
return "riskCoupling";
}
#RequestMapping(value = "/{r1}", method = RequestMethod.POST)
public String saveCoupling( ){
return "/projects";
}
#RequestMapping(value = "/{r2}", method = RequestMethod.DELETE)
public String removeCoupling(){
return "/projects";
}
}
This is my Thymeleaf view
<td>
<form action = "#" th:action="#{/proj/{pid}/coupling/{r1}/{r2} (pid=${projectID},r1=${r1ID},r2=${r2.id})}" method = "post">
<input type="submit" name="Couple" value="Couple" class="btn btn-info" />
</form>
</td>
<td">
<form action = "#" th:action="#{/proj/{pid}/coupling/{r1}/{r2} (pid=${projectID},r1=${r1ID},r2=${r2.id})}" method = "delete">
<input type="submit" name="RemoveCoupling" value="RemoveCoupling" class="btn btn-info" />
</form>
</td>
When I go to the url /proj/{pid}/coupling/{r1} I get the overview so the GET works.
When I press the Couple button it works. So the POST works.
When I press the RemoveCoupling button I get the error:
Request method "Get" not supported.
I really don't know why I get this error.
Since browsers unfortunately do not support any other verbs than POST and GET in HTML forms, they will just send POST/GET requests instead. This might be the reason why only that one does not work.
See more:
http://martinfowler.com/articles/richardsonMaturityModel.html
http://amundsen.com/examples/put-delete-forms/
http://www.quora.com/HTTP/Why-are-PUT-and-DELETE-no-longer-supported-in-HTML5-forms
I fixed this with Thymeleaf - Button click to call http delete method.
Basically putting a hidden field in my form.
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 am super new to front end development. I have a simple webapp where you can submit a form, and I want to be able to get the form data in a REST endpoint. I am using Spring boot which contains Spring MVC.
The HTML:
<div class="modal-header modal-header-info">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h4 class="modal-title">Add Entity</h4>
</div>
<div class="modal-body">
<form role="form" method="post" action="/createEntity">
<div class="form-group">
<label for="name">Name:</label> <input type="text"
class="form-control" id="name">
</div>
<button type="submit" class="btn btn-info">Submit</button>
</form>
</div>
The Java:
#RequestMapping(value = "/createEntity", method = RequestMethod.POST)
public void createEntity(#RequestBody String payload) {
System.out.println("Hello world!");
System.out.println(payload);
}
I get this error back:
Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing: public void main.java.info.spring.data.neo4j.controllers.CreateEntityController.createEntity(java.lang.String)
How do I get the "name" value from the form? The "hello world" attribute prints out if I take out the #RequestBody part.
Edit: my configuration per request:
#EnableTransactionManagement
#Import(RepositoryRestMvcConfiguration.class)
#EnableScheduling
#EnableAutoConfiguration
#ComponentScan(basePackages = { "main.java.info.spring.data.neo4j.services",
"main.java.info.spring.data.neo4j.controllers" })
#Configuration
#EnableNeo4jRepositories(basePackages = "main.java.info.spring.data.neo4j.repositories")
public class MyNeo4jConfiguration extends Neo4jConfiguration {
public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL")
: "http://localhost:7474";
#Override
public Neo4jServer neo4jServer() {
return new RemoteServer(URL, "neo4j", "LOL my pass");
}
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory("main.java.info.spring.data.neo4j.domain");
}
}
Problem 1: HTML form controls are missing the name attribute
HTML forms are submitted in name-value pairs. Form controls that do not have a name attribute cannot be submitted because their names are not known. The id attribute is only for referencing controls on the client-side.
<input type="text" class="form-control" id="name">
is missing the name attribute. It should be:
<input type="text" class="form-control" id="name" name="name"/>
This will submit the control as a form parameter in the HTTP request body, something like:
name: [the value you specify for the control]
Problem 2: #RequestBody as a controller method argument will give you the entire HTTP request body
public void createEntity(#RequestBody String payload)
means that you want the entire HTTP request body to be passed as a String to the controller method createEntity. If your HTML form is indeed what you have posted, you will get the following value for payload (after you have addressed problem 1):
name: [the value you specify for the control]
If this is what you want, keep the #RequestBody annotation, but I suspect that you are only interested in the value of the name request parameter. If that is the case, you need to change your method declaration to (after you have addressed problem 1):
public void createEntity(#RequestParam String name)
This will map the HTTP request parameter name to the controller method argument name.
Problem 3: Having void as the return type for a controller method will force Spring MVC to look for a view with the same name as the method name
Since you have the controller method declared as:
public void createEntity(#RequestBody String payload)
Spring MVC will look for a view named createEntity after this method exits. If you have a view with that name, well and good. Otherwise, once you have fixed problems 1 and 2, you will get a 404 - Resource not found error.