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.
Related
I'm unable to fetch the values from Controller(Home.java) to View (home_view.jsp) in Spring Boot.
home.jsp
<body>
<div class="container mt-10">
<form action="processHome" method="post">
<div class="form-group">
<label for="emp_Id">Enter Employee Id</label>
<input type="number" placeholder="Enter Id" name="id">
</div>
<div class="form-group">
<label for="Name">Enter Employee Name</label>
<input type="text" placeholder="Enter Name" name="name">
</div>
<div class="form-group">
<label for="Password">Enter Employee Password</label>
<input type="text" placeholder="Enter Password" name="password">
</div>
<button type="submit">Submit</button>
</form>
Home.java
#Controller
public class Home {
#RequestMapping("home")
public String index() {
return "home";
}
#RequestMapping(path="processHome",method=RequestMethod.POST)
public String homeForm(#ModelAttribute Employee emp, Model model) {
System.out.println(emp); // Here in 'emp' I'm getting the values in my console
return "home_view";
}
}
Employee.java
public class Employee {
private int id;
private String name;
private String password;
//getters & setters
//toString()
}
home_view.jsp
<body>
Model : ${emp.id} ${emp.name} ${emp.password}
</body>
OUTPUT
I am successfully redirected to the home_view.jsp but unable to fetch data. As in my console, I'm getting the values from the View and when I am using ModelAndView then also I am getting those values but when I'm using #ModelAttribute then only data isn't fetching into the view.
I've got the data on views but really not sure that Model object name is creating such differences
public String homeForm(#ModelAttribute Employee employee, Model model)
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?
I'm creating a simple CRUD in Spring Boot+Thymeleaf and all other CRUD on application work well but this one. When I submit the form, the object comes with empty attributes to controller.
In the following, the code:
Artist.java
#Entity
public class Artist {
#Id
#GeneratedValue
private Long id;
#Column(nullable=false, length = 80)
private String artistName;
<getters and setters>
ArtistController.java
#Controller
public class ArtistController {
#Autowired
ArtistRepository artistRepository;
#GetMapping("/artist/add")
public String addArtist(Model model) {
model.addAttribute("artist", new Artist());
return "artist/form_artist";
}
#PostMapping("/artist/save")
public String artistSave(#ModelAttribute(name="artist") Artist artist) {
artistRepository.save(artist);
return "redirect:/artist";
}
}
And now, the form:
<form action="#" th:action="#{/artist/save}" th:object="${artist}" method="post" class="form-horizontal">
<div class="form-group">
<label for="id" >HobbyOn id:</label>
<input type="text" id="id" th:field="*{id}" readonly="readonly" class="form-control" placeholder="hobbyOn ID" />
</div>
<div class="form-group">
<label for="artistName" >Artist Name:</label>
<input type="text" th:field="*{artistName}" class="form-control" required="required" />
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
</form>
I can't see any difference from examples in internet and in my own code. Any help will be very welcomed.
I am building an application which has same functionalities both from AWS and Google Cloud. For example Creating an instance , Launching instance from Machine ID, Creating snapshot, Liting all Instances,etc. Which I called using REST calls.
For example:
<form method="post" action="rest/create/new" class="form-inline">
<label for="user">User Name</label> <input type="text" id="user"
name="user" class="form-control" size="50"
placeholder="Enter Username">
<button type="submit" class="btn btn-info">Start New Machine</button>
</form>
<form method="post" action="rest/launch/start" class="form-inline">
<label for="AMId">Launch Existing Machine</label><br> <input
type="text" id="AMId" name="AMId" class="form-control" size="50"
placeholder="Enter Instance ID">
<button type="submit" class="btn btn-info">Launch</button>
<br>
</form>
<br> <br>
<form method="get" action="rest/create/listAll" class="form-inline">
<label>Show All EC2 Instances</label><br>
<button type="submit" class="btn btn-info btn-lg">Show All</button>
</form>
<br> <br>
<form method="post" **action="rest/create/listRunning"**>
<label>Show All Running EC2 Instances</label><br>
<button type="submit" class="btn btn-info">Show All Running</button>
</form>
<br> <br>
<form method="post" action="rest/create/terminate" class="form-inline">
<label for="terminateID">Enter Instance ID</label><br> <input
type="text" id="terminateID" name="terminateID" class="form-control"
size="50" placeholder="Enter Machine ID">
<button type="submit" class="btn btn-info">Terminate</button>
</form>
<br> <br>
And I am catching these rest calls in classes.
For example,
#GET
#Path("/listAll")
public Response getAllAvailableImages(#Context ServletContext context)
Now what I want is how can I use both AWS and google cloud features, using these same calls or some other method,depending on requirement or choice?
How about:
GET /{provider}/images
POST /{provider}/images/{imageID}/start
where the variables in braces are placeholders for path parameters:
{provider} may resolve to AWS, Google or another provider
{imageID} references a unique image ID
Examples:
GET /AWS/images (gets all AWS images)
POST /GoogleCloud/images (creates new Google Cloud image)
POST /OpenStack/images/gfhdh45ff4/terminate (terminates a specific image)
If you are using Spring MVC for REST, the controller could look like:
#RestController
public class ImageController {
#Autowired
private ImageService imageService;
#RequestMapping(value = "/{provider}", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
public List<Image> getImages(#PathVariable String provider) {
return imageService.getImagesByProvider(provider);
}
#RequestMapping(value = "/{provider}", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public Image createNewImage(#PathVariable String provider, #RequestBody Image image) {
return imageService.createImageForProvider(provider, image);
}
#RequestMapping(value = "/{provider}/images/{imageId}/start", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void startImageAtProvider(#PathVariable String provider, #PathVariable String imageId) {
return imageService.startImageAtProvider(provider, imageId);
}
}
The HTTP method for starting the image could be POST - and should be if starting an image is not idempotent. But I am assuming hat attempting to start an image which is already running will just be ignored.
Extra edit:
If the image IDs are unique across ALL providers, you could shorten the REST URLs regarding images:
POST /images/gfhdh45ff4/terminate (terminates a specific image)
I have fiollowing controller method:
#RequestMapping(value = "/admin/addNewAdmin")
public String adminUsers(#ModelAttribute #Valid TerminalAdmin newAdmin, BindingResult bindingResult, ModelMap model, Principal principal, HttpSession session) {
if (bindingResult.hasErrors()) {
...
model.addAttribute("newAdmin",newAdmin);
return "admin/adminUsers";
}
....
}
and following model:
Entity
#Table(name = "terminal_admin")
public class TerminalAdmin {
.....
#Column(name = "email", nullable = false)
#Size(max = 255)
#NotEmpty
private String email;
}
jsp:
<form:form modelAttribute="newAdmin" action="/admin/addNewAdmin">
<div class="line">
<label for="">email</label>
<form:input path="email" type="text" name="emal" value=""/>
!!!<form:errors path="email" cssClass="error"/>!!!
<div class="clear"></div>
</div>
</form:form>
I input empty email into form
In debug in controller method I see that bindingResult has errors that email shouldn't be empty.
jsp renders as:
<form id="newAdmin" action="/admin/addNewAdmin" method="post">
<div class="line">
<label for="">email</label>
<input id="email" name="email" type="text" value="">
!!!!!!
<div class="clear"></div>
</div>
</form>
Working after replace
newAdmin
with
terminalAdmin
thx second point of this https://stackoverflow.com/a/2912049/2674303