Creating a new User Account Spring data rest framework - spring-mvc

I have been trying to create a new user for my webApp. I am using spring-data-rest. At the front end, a prospective user submits his information and then the app is supposed to create back-end information. The codes are as below.
User.java
public class User {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String name;
private String email;
private String password;
private String address;
//getters and setters
}
UserRepository.java
#RepositoryRestResource(collectionResourceRel = "user", path = "user")
public interface UserRepository extends PagingAndSortingRepository<User, Long>{
}
Is it okay to have view as below? Do I need to worry about id? It is supposed to be generated by backend, so it does not make any sense to put id field in view.
registration.html
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
</head>
<body>
<h3>Welcome, Enter The User Details</h3>
<form:form action="#" th:action="#{/user}" th:object="${user}" method="post">
<div><label> User Name : <input type="text" th:field="*{username}"> </label></div>
<div><label> Password: <input type="password" th:field="*{password}"/> </label></div>
<div><label> Email: <input type="email" th:field="*{email}"/> </label></div>
<div><label> Address: <input type="text" th:field="*{address}"/> </label></div>
<div><input type="submit" value="Submit"/></div>
</form:form>
</body>
</html>

I don't know about thymeleaf, but answer for your question is it is ok.
You don't need to worry about id in view, it is automatically created by your dao framework. By #GeneratedValue(strategy= GenerationType.AUTO)
You can use this kind of thing since it's a Spring MVC
<form:hidden path="id"/>

Related

Saving record in a proper way

I have a problem with saving records to DB with Spring-Mvc and Thymeleaf.
When I click "Update" button on record, to enter the update form (included beneath), all values are in place correctly, but, when I want to subbmit, an error occur. There is no any stacktrace in console, only error in web page, that I am not able to solve.
This is my code:
Controller:
#GetMapping("/{maltId}")
public ModelAndView showMalt(#PathVariable("maltId") Long maltId) {
ModelAndView mav = new ModelAndView("malt/malt-show");
mav.addObject(maltService.findById(maltId));
return mav;
}
#GetMapping("/{maltId}/edit")
public String initUpdateMaltForm(#PathVariable("maltId") Long maltId, Model model) {
model.addAttribute("malt", maltService.findById(maltId));
return VIEWS_MALT_CREATE_OR_UPDATE_FORM;
}
#PostMapping("/{maltId}/edit")
public String processUpdateMaltForm(#Valid Malt malt, BindingResult result, #PathVariable("maltId") Long maltId) {
if (result.hasErrors()) {
return VIEWS_MALT_CREATE_OR_UPDATE_FORM;
} else {
malt.setId(maltId);
Malt savedMalt = maltService.save(malt);
return "redirect:/malt/" + savedMalt.getId();
}
}
Model:
#Column(name="malt_name")
private String maltName;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="producer_id")
private Producer producer;
#Column(name="malt_filling")
private int maltFilling;
#Column(name="malt_ebc")
private int maltEbc;
#Column(name="malt_usage")
private String maltUsage;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="country_id")
private Country country;
#ManyToMany(mappedBy="malts")
private Set<Batch> batches;
This is the view:
<body>
<form th:object="${malt}" th:action="#{/malt/}" method="post">
<input type="hidden" th:field="*{id}" />
<label>Malt name:</label>
<input type="text" class="form-control" th:field="*{maltName}" />
<label>Producer:</label>
<input type="text" class="form-control"
th:field="*{producer.producerName}" />
<label>Country:</label>
<select class="form-control" th:field="*{country.id}">
<option value="0">Select country</option>
<option th:each="country : ${countries}"
th:value="${country?.id}"
th:text="${country?.countryName}">
</option>
</select>
<label>Malt filling:</label>
<input type="text" class="form-control"
th:field="*{maltFilling}" />
<label>Malt usage:</label>
<input type="text" class="form-control"
th:field="*{maltUsage}" />
<label>Malt EBC:</label>
<input type="number" class="form-control"
th:field="*{maltEbc}" />
<button class="submit-button" type="submit">Submit</button>
</form>
</body>
When I hit Submit button, I get this error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed May 15 22:46:22 CEST 2019
There was an unexpected error (type=Not Found, status=404).
No message available
I have tried couple of different approaches, but nothing helps, and since there is no stacktrace in console, I have no idea what is wrong here.
Link to repo: https://github.com/fangirsan/maruszka-new
No stack trace 404 normally indicates that there is no mapping. Since you have, potentially, provided only a part of your Controller I assume that the causation for this is the code in your view right here:
<form th:object="${malt}" th:action="#{/malt/}" method="post">
The action takes to ("/malt/"), however, your controller has not got mapping for this?!
I expect that this should fix it:
<form th:object="${malt}" th:action="#{${'/' + malt.id + '/edit'}}" method="post">
Update
Had a look at your controller and you have the following annotations on your class
#Controller
#RequestMapping("/malt")
public class MaltController{..
#RequestMapping("/malt") will now make your path to save ../malt/{id}/edit'. The code below now should work:
<form th:object="${malt}" th:action="#{${'/malt/' + malt.id + '/edit'}}" method="post">
On using "#{${...}}"
#{} is a link variable, contents within this tag will be appended to the applications root context, e.g., at Stack Overflow #{'/posts'} would result with https://stackoverflow.com/posts
The ${} is a variable expression which will return a String or the object's .toString() value.
If we want to pass a variable within #{} link variable we must include the ${} variable within it, thus resulting in :
#{${'/hope/this/helps' + yourVariable}}

How to use input radio button with thymeleaf and Spring MVC

I would like to get a destination address from a input radio button list. The DestinationAddress class is the following:
public class DestinationAddress {
private Integer destinationAddressId;
private String name;
private Location location;
private User owner;
public DestinationAddress(String name, Location location, User owner) {
this.name = name;
this.location = location;
this.owner = owner;
}
public DestinationAddress() {
}
// getter and setter
}
The controller who handles the get and post is the following:
#PreAuthorize("hasRole('USER')")
#GetMapping(value = "/select-address")
public String selectAddress(Principal principal, Model model) {
List<DestinationAddress> addresses = destinationAddressService.getAllByUsername(principal.getName());
model.addAttribute("destinationAddresses", addresses);
model.addAttribute("destinationAddress", new DestinationAddress());
return "purchase/select-address";
}
#PreAuthorize("hasRole('USER')")
#PostMapping(value = "/select-address")
public String selectAddress(#ModelAttribute DestinationAddress destinationAddress, Principal principal) {
Purchase purchase = purchaseService.addPurchase(principal.getName(), destinationAddress);
return "redirect:/purchases/pay/" + purchase.getPurchaseId();
}
And the html page is the following:
<form th:object="${destinationAddress}" method="post">
<fieldset>
<legend>Your addresses</legend>
<ul>
<li th:each="destinationAddress : ${destinationAddresses}">
<input type="radio" th:field="*{destinationAddressId}" th:value="${destinationAddress.destinationAddressId}" />
<label th:for="${#ids.prev('destinationAddress.destinationAddressId')}" th:text="${destinationAddress}"></label>
</li>
</ul>
</fieldset>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
The error message is the following:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'destinationAddressId' available as request attribute
I don't know what's the problem here. I don't know which type will the form return to the controller. So I don't know which variable pass to the model and which one to get from the post controller method. Integer or DestinationAddress? I cannot find anything googling it, just small pieces of code without any explanations. Any suggestions?
I found a solution to my problem. I changed the html page, now it looks like this:
<form th:object="${address}" method="post">
<fieldset>
<legend>Your addresses</legend>
<ul>
<li th:each="destinationAddress : ${destinationAddresses}">
<input type="radio" th:field="${address.destinationAddressId}" th:value="${destinationAddress.destinationAddressId}" />
<label th:for="${destinationAddress.destinationAddressId}" th:text="${destinationAddress}"></label>
</li>
</ul>
</fieldset>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
I changed the name of the object inside the model because it was the same as the name of the temp destinationAddress of the loop. I also replaced '{#ids.prev(' because it was giving me an error:
Cannot obtain previous ID count for ID ...
Now it works fine.

Thymeleaf Set Binding for Neo4j insert

I have been working on an Spring MVC application with a Thymeleaf UI. For Neo4j handling entities, I use Set that contains NeoImages that Belong to the class posts:
#Data
#NodeEntity
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class NeoPost {
#Id
#GeneratedValue
Long postId;
#NotNull
#NotBlank
#Size(min = 1, max = 600)
String question;
/**
* Images that are involved in that post
*/
#NotEmpty
#Size(min = 2)
#Relationship(type = "STARES", direction = Relationship.OUTGOING)
Set<Neoimage> neoimageSet = new HashSet<>();
/**
* User that made this post
*/
#Relationship(type = "OWNS", direction = Relationship.INCOMING)
NeoUser user;
/**
* Users that somehow in a way possible described in Userinteractiontype enum
* with this current post.
*/
#Relationship(type = "INTERACTED_WITH", direction = Relationship.INCOMING)
Set<NeoInteraction> incomingInteractions = new HashSet<>();
}
Here the class of the NeoImage type:
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
#NodeEntity
public class Neoimage {
#Id
#GeneratedValue
Long imageId;
//For testing purposes use this type of information
#ImageUrlValidator
String imageFull;
}
Do not get me wrong I know that I want to use a Set to store the Neoimages in the Neopost class. The Problem is not the persistence or anything, but I want to delivery input results from a thymeleaf form.
<form autocomplete="off" action="#" th:action="#{/postQuestion}"
th:object="${neoPost}" method="post" role="form">
<div class="form-group">
<div class="col-sm-12">
<label th:if="${#fields.hasErrors('question')}" th:errors="*{question}"
class="validation-message"></label>
<input type="text" th:field="*{question}" placeholder="Question"
class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="text" th:field="*{neoimageSet[0].imageFull}"
placeholder="Image 1" class="form-control" /> <label
th:if="${#fields.hasErrors('neoimageSet[0].imageFull')}" th:errors="*{neoimageSet[0].imageFull}"
class="validation-message"></label>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="text" th:field="*{neoimageSet[1].imageFull}"
placeholder="Image 1" class="form-control" /> <label
th:if="${#fields.hasErrors('neoimageSet[1].imageFull')}" th:errors="*{neoimageSet[1].imageFull}"
class="validation-message"></label>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-outline-secondary my-2 my-lg-0 loginButton">Upload Post</button>
</div>
</div>
<span th:utext="${successMessage}"></span>
</form>
When I then access the post request, the question is filled in the model as expected, but the neoimageset does not hold the two strings from the two input fields. I have heard that databinding is somehow not possible to a set with thymeleaf. I can fully understand if you need any further elaborations, thank you for helping.
I have solved this issue using a wrapper method within:
/**
* Wrapper method since set elements cannot be accessed by index which is needed in thymeleaf
*/
#Transient
AutoPopulatingList<Neoimage> neoImageWrapperList = new AutoPopulatingList(Neoimage.class);
public AutoPopulatingList<Neoimage> getNeoImageWrapperList() {
//Copy content to neoimageset
this.neoImageWrapperList.forEach(neoimage -> neoimageSet.add(neoimage));
return this.neoImageWrapperList;
}
Now I just call the neoImageWrapperList instead of the actual set.

Java spring post form one to many relationship

I'm trying to get POST form data on controller of the object have one to many relationship. Like below code
My Notification Model
private long id;
#NotBlank(message = ERROR.NOT_EMPTY)
private String title;
#NotBlank(message = ERROR.NOT_EMPTY)
private String content;
// One Notification has many User
private List<NotificationUser> listNotificationUser;;
// Getter and setter method
My controller
#RequestMapping(value = "notification/add", method = RequestMethod.GET)
public String create(ModelMap model) {
ArrayList<User> listUser = userService.getAllUsername();
model.put("user", listUser);
model.addAttribute("notification", new Notification());
return "notification/add";
}
#RequestMapping(value = "notification/add", method = RequestMethod.POST)
public String create(ModelMap model, HttpServletRequest request,
#Valid #ModelAttribute(value = "notification") Notification notification, BindingResult bindingResult) {
....
}
My .jsp
<form:form method="POST" action="add" name="addForm" commandName="notification">
<!-- Other input -->
<form:select path="listNotificationUser" multiple="multiple" id="name" name="itemValue">
<form:options />
<form:options items="${user}" itemValue="id" itemLabel="name" />
</form:select>
<!-- Other input -->
</form:form>
When I submit POST form to controller, the field notification.listNotificationUser always is null (other field is fine).
I was search and try some solution but it not working.
I guess your problem its you have a typo in your form:select. You are defining 2 options blocks, and I guess you want to define just an empty option. So should be like this
<form:select path="listNotificationUser" multiple="multiple" id="name" name="itemValue">
<!-- Some value you can identify as empty option-->
<form:option value="0" label="--Options--"/>
<form:options items="${user}" itemValue="id" itemLabel="name" />
</form:select>

ASP.NET WEB API Not able to retrieve Post Parameters

I trying to retrieve post parameters in web API but I do get null values everytime.
My html
<form method="POST" action="http://localhost:16192/update" name="myform">
<input name="title" type="text"/>
<input name="isbn" type="text"/>
<input name="author" type="text"/>
<input type="submit" value="Submit"/>
</form>
And My WebAPI
[HttpPost]
[Route("UPDATE/")]
public String updateRecord([FromBody]String title,String isbn="", String author="")
{
return "Updated";
}
The updateRecord method is being called but I always get null values. Any help would be greatly appreciated.
[HttpPost]
[Route("UPDATE/")]
public String updateRecord([FromBody]dynamic values)
{
var title = values.title.Value;
....
return "Updated";
}
or you can create a DTO object (paragraph 2):
http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

Resources