I have been doing a basic application, which may contain all the issues I have had recently.
I tried to map the endpoints specified in the code under "/example/", "/example/add" and "/example/add2", but unfortunately I got 404 when I tried to submit the form.
My code works if I don't use subdomains, jut map everthing under "/".
Here's my relevant code:
//#RequestMapping("/example") --> also tried to put it here
public class AttractionController {
private AttractionService attractionService;
#Autowired
public AttractionController(AttractionService attractionService) {
this.attractionService = attractionService;
}
#RequestMapping("/example")
#GetMapping("/")
String main(Model model) {
model.addAttribute("attractions", attractionService.findAll());
return "main";
}
#PostMapping("/add")
String add(#ModelAttribute Attraction attraction) {
attractionService.save(attraction);
return "redirect:/";
}
#PostMapping("/add2")
String add2(#RequestParam String name, #RequestParam Double latitude,
#RequestParam String city, Model model) {
attractionService.save(new Attraction(name, latitude, city));
return "redirect:/";
//also tried to use return "redirect:/example"
}
HTML:
<form th:method="POST" th:action="#{add}">
<input type="text" name="name">
<input type="text" name="latitude">
<input type="text" name="city">
<input type="submit">
</form>
<form th:method="POST" th:action="#{add2}">
<input type="text" name="name">
<input type="text" name="latitude">
<input type="text" name="city">
<input type="submit">
</form>
How could I solve this issue?
Related
I want to create my own registration page with spring boot, instead of sending a JSON POST request from Postman.
I currently have an HTML page with a form which submits the registration data, a registration controller, and registration service. However, it is not working properly.
My code:
RegistrationRequest
#Getter
#AllArgsConstructor
#EqualsAndHashCode
#ToString
public class RegistrationRequest {
private final String firstName;
private final String lastName;
private final String email;
private final String password;
}
Registration Controller
#RestController
#RequestMapping(path = "api/v1/registration")
#AllArgsConstructor
public class RegistrationController {
private final RegistrationService registrationService;
#PostMapping
public String register(#RequestBody RegistrationRequest request) {
return registrationService.register(request);
}
#GetMapping(path = "confirm")
public String confirm(#RequestParam("token") String token) {
return registrationService.confirmToken(token);
}
HTML form
<form class="form-signin" method="post" action="api/v1/registration">
<h2 class="form-signin-heading">Please Log in to tour agency account</h2>
<p>
<label for="firstName" class="sr-only">First name</label>
<input type="text" id="firstName" name="firstName" class="form-control" placeholder="First name" required="" autofocus="">
</p>
<p>
<label for="lastName" class="sr-only">Last name</label>
<input type="text" id="lastName" name="lastName" class="form-control" placeholder="Last name" required="" autofocus="">
</p>
<p>
<label for="email" class="sr-only">Email</label>
<input type="text" id="email" name="email" class="form-control" placeholder="Email" required="" autofocus="">
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required="">
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>
Template controller
#Controller
#RequestMapping("/")
public class TemplateController {#PostMapping("register") // I know that "register is not linked with path = api/v1/registeration
public String postRegister() {
return "register";
}
}
You need either need a template engine, or you could use Javascript and submit an AJAX request for that. If you want to use a template engine, I recommend using Thymeleaf, however there are many template engines that are available for use.
Using Thymeleaf, you'd have to modify your template to include th:action, which describes your endpoint, and th:object, which is your model. Then we name it as register.html:
<form action="#" th:action="#{/api/v1/registration}" th:object="${registrationRequest}" method="post">
<!-- Form inputs... -->
<button type="submit">Register</button>
</form>
Then in the controller, we need to tell Spring about our HTML page and the model:
#GetMapping("/register")
public String registerationForm(Model model) {
model.addAttribute("registrationRequest", new RegistrationRequest());
return "register";
}
So now when we open /register, our HTML page is loaded.
Finally, modify your POST endpoint to get our form's submitted model:
#PostMapping
public String register(#ModelAttribute RegistrationRequest registrationRequest) {
return registrationService.register(request);
}
This returns the result from registration service, you could also return a string which represents a page name, e.g. return "result", here result is an HTML page result.html.
Below is code from a controller that I'm aiming to make sure it's receiving two input parameters (name and code) from a front-end interface.
It's a page that takes two parameters within a submit form, "name" and "code".
#RequestMapping(method = RequestMethod.POST)
public String transfer(#RequestParam(name = "name") String name,
#RequestParam(name = "code") String code,
Errors errors, RedirectAttributes redirectAttributes) {
if (errors.hasErrors()) {
return "htmlPageOne";
}
try {
User userToBeTransferred = usersRepository.findByName(name);
userToBeTransferred.setTransferred(true);
Region regionOfTransference = regionsRepository.findByCode(code);
regionOfTransference.setPopulationNumber(regionOfTransference.getPopulationNumber() + 1);
userToBeTransferred.setRegion(regionOfTransference);
usersRepository.save(userToBeTransferred);
regionsRepository.save(regionOfTransference);
return "redirect:/section/users/new";
} catch (IllegalArgumentException e) {
return "htmlPageOne";
}
}
The front-page form :
<form class="form-horizontal" method="POST" action="/section/users/new" th:object="${user}">
<input type="hidden" th:field="*{id}"/>
<div class="form-group row">
<label for="name" class="col-form-label">User name</label>
<input type="text" class="form-control" id="name" th:field="*{name}" name="name"/></div>
<div class="form-group row">
<label for="code" class="col-form-label">Code</label>
<input type="text" class="form-control" id="code" th:field="*{region.code}" name="code"/></div>
<button type="submit" class="btn btn-primary col-sm-6 ">Save</button>
</form>
For some reason, I'm getting the following error after I click to submit the form :
There was an unexpected error (type=Internal Server Error, status=500).
An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the #RequestBody or the #RequestPart arguments to which they apply: public java.lang.String
I'm not sure if I'm using the requestparams correctly, so maybe it's got something to do with this? I don't know, I've been stuck on this for a few hours now, so would appreciate if someone could help me.
Im trying to create 2 instances of an object and then parse them to the controller via an input type="submit".
Here's what I have:
#RequestMapping (value = "/webdata")
public String vorsorgestammdaten(Model model) {
model.addAttribute("Data", new DataOp());
model.addAttribute("Data2", new DataOp());
return "/webdata";
}
// Here I want to parse both objects
#RequestMapping(value = "/formdata", method = RequestMethod.POST)
public String formdata(HttpServletRequest req, #AuthenticationPrincipal User currentUser,
DataOp Data, DataOp Data2, Model model) {
// Do stuff for example
Data.getName();
Data2.getName();
}
Here is part of my forms:
<form method="post" th:action="#{/formdata}" th:object="${regData}">
<div class="col-sm-4">
<input th:field="${Data2.gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="${Data2.gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="${Data2.firstname}" placeholder="Max" disabled="disabled" />
</div>
<div class="col-sm-4">
<input th:field="*{Data.gender}" type="radio" value="MALE" name="gender" disabled="disabled" /><span>Mr</span>
<input th:field="*{Data.gender}" type="radio" value="FEMALE" name="gender" disabled="disabled"/><span>Frau</span>
<p>Firstname:</p>
<input required="required" type="text" th:field="*{Data.firstname}" placeholder="Max" disabled="disabled" />
<button type="submit">Speichern</button>
</div>
</form>
Try removing this th:object="${regData}".
Then you can use #ModelAttribute annotation.
For example,
public String formdata(HttpServletRequest req,#AuthenticationPrincipal User currentUser, #ModelAttribute DataOp Data,#ModelAttribute DataOp Data2, Model model) {
//Some code
}
You might as well switch *{Data.gender} to ${Data.gender}.
add RequestAttribute annotation to each of those params, adding the "name" attribute to differentiate them.
here you have some info.
i am working with Spring where my form fields are same with attribute fields so when i submit form it directly maps to database fields and save the data it works perfectly, but what if i want to save multiple objects with one form,
HTML:
<form>
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
</form>
POJO:
public class ProjectPayment
{
private Double payment;
private Date paymentDate;
// setters and getters
}
Controller:
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPayment projectPayment) {
projectPaymentService.saveProjectPayment( projectPayment);
}
this works perfectly,
but now in my some scenario i need multiple objects dynamically then how to save in database, how controller should look like
for example:
Now my Form is
<form>
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
Payment:<br>
<input type="text" name="payment"><br>
Date:<br>
<input type="date" name="paymentDate">
</form>
Now this form have multiple objects of ProjectPayment class but it saves only one object
please tell me how my controller should like, i have done like this but it occurs exception
Controller:
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPayment[] projectPayment) {
for(ProjectPayment propay : projectPayment)
{
projectPaymentService.saveProjectPayment( propay );
}
}
I can understand that you want to post data from a grid/table, however it's too ambiguous to determine which field map to which object.
Example:
field1
field2
field3 ==>Map to object at index 1 or 2?
filed1
So you think field3 should map to array index=1 or index=2?
So I suggest you should submit one by one to solve this issue.
Simple way to solve this problem is create a ViewModel.
e.g.
public class ProjectPaymentViewModel
{
private List<ProjectPayment> listProjectPayment;
// setters and getters
}
Use this view model on web page and controller
<form>
Payment:<br>
<input type="text" name="listProjectPayment[0].payment"><br>
Date:<br>
<input type="date" name="listProjectPayment[0].paymentDate">
Payment:<br>
<input type="text" name="listProjectPayment[1].payment"><br>
Date:<br>
<input type="date" name="listProjectPayment[1].paymentDate">
Payment:<br>
</form>
On controller
#RequestMapping(value = "/addnewproject", method = RequestMethod.POST)
public #ResponseBody String SaveProject(ProjectPaymentViewModel projectPaymentViewModel) {
for(ProjectPayment propay : projectPaymentViewModel.getListProjectPayment())
{
projectPaymentService.saveProjectPayment( propay );
}
}
So my Spring MVC project home page has two input fields within a form.
The user can enter the roll number or name.
Jsp
<form action="search" method="GET" >
<div style="text-align: center;">
<input type="text" id="regNo" name="regNo" size="30" maxLength="50" "></input> or
<input id="studentName" type="text" size="30" maxLength="50" "></input>
</form>
In my controller, I have two methods mapped to two input fields.
#RequestMapping(value ="/search", method = RequestMethod.GET)
public String getStudent(String regNo, ModelMap model){
return "A";
}
#RequestMapping(value="/search", method = RequestMethod.GET)
public String searchStudentByName(String studentName, ModelMap model){
return "B";
}
Since both the input fields are String, I don't know how can I map them to two different methods in controller?
Did you want something like this :
#RequestMapping(method= RequestMethod.GET,value = "/search/r/regNo={regNo}")
public String getStudent(#PathVariable String regNo){
}
for studentName :
#RequestMapping(method= RequestMethod.GET,value = "/search/s/studentName={studentName}")
public String getStudent(#PathVariable String studentName){
}
then you need to add both request in different form tag, & in action tag provide :
if regNo send :
/search/r/
for studentName :
/search/s/
Jsp :
<form action="search/r" method="GET" >
<div style="text-align: center;">
<input type="text" id="regNo" name="regNo" size="30" maxLength="50" "></input>
<input type="submit" name="approve" value="RegNo" />
</form>
<form action="search/s" method="GET" >
<div style="text-align: center;">
<input id="studentName" type="text" size="30" maxLength="50" "></input>
<input type="submit" name="approve" value="StudentName" />
</form>
OR Second way to do so :
<form action="search" method="GET" >
<input type="text" id="regNo" name="regNo" size="30" maxLength="50" "></input>
<input id="studentName" type="text" size="30" maxLength="50" "></input>
<input type="submit" name="regno" value="regno" />
<input type="submit" name="studentName" value="studentName" />
</form>
controller :
#RequestMapping(value = "/search", method = RequestMethod.GET, params = { "regno" })
public String getRegno(#RequestParam String regno) {
}
#RequestMapping(value = "/search", method = RequestMethod.GET, params = { "studentName" })
public String getStudent(#RequestParam String studentName) {
}
Post me.