java spring - post request with additional value - java

I have implemented a registration process where you can send user data to the controller via post request.
The post request works fine, however now I want to pass another value (role, Long) from the form to the controller that is not an attribute of the user model.
That part is not working.
Does anyone know why?
HTML:
<form action="add_user" method="post" class="form-horizontal" th:object="${user}">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<input th:field="*{username}" class="form-control" placeholder="Person ID" type="text" name="id" id="id"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<input th:field="*{firstName}" class="form-control" placeholder="First Name" type="text" name="firstname" id="firstname"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<input th:field="*{lastName}" class="form-control" placeholder="Last Name" type="text" name="lastname" id="lastname"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<input th:field="*{password}" class="form-control" placeholder="Password" type="password" name="password" id="password"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<select th:field="${role}" class="form-control" id="role">
<option value="1">Admin</option>
<option value="2" >User</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<button type="submit" class="btn btn-success" value="Submit">Save</button>
</div>
</div>
</form>
Controller:
#RequestMapping(value = "/users", method = RequestMethod.GET)
public String showUsers(Model model)
model.addAttribute("user", new User());
model.addAttribute("role", new Long(2));
return "users";
}
And:
#RequestMapping(value = "/add_user", method = RequestMethod.POST)
public String handleNewUser(#ModelAttribute("user") User user, BindingResult bindingResult, Model model, long role) {
if (user != null) {
System.out.println(role);
userService.save(user);
}
return "redirect:/users";
}

th:field="${role}" means name of field in the model object, not its value. You probably want to write th:value="${role}" instead of this.

Related

405 - request GET and POST

Hello i have problem with update object, i dont know how always aftre update data i have message: Request method 'GET' not supported. But date after refresh object is update.
Controller with GET and POST method to update object
#Controller
#RequestMapping("/packet")
public class PacketController {
#GetMapping("/modify/{id}")
public String modifyPacketGet(Model model, #PathVariable Long id)
{
model.addAttribute("channels", channelService.getAllChannels());
model.addAttribute("packet", packetService.getById(id));
return "packet/modify";
}
#PostMapping("/modify")
public String modifyPacketPost(Model model, #ModelAttribute PacketDto packetDto)
{
packetService.updatePacket(packetDto);
return "redirect:/packet/modify";
}
HTML form
<form th:action="#{/packet/modify}" method="post" th:object="${packet}" enctype="multipart/form-data">
<input type="text" hidden="hidden" readonly="readonly" th:field="*{id}" />
<input type="text" hidden="hidden" readonly="readonly" th:field="*{filename}" />
<div class="form-group">
<label for="name" class="h3 text-success">Name:</label>
<input id="name" type="text" th:field="*{name}" class="form-control">
</div>
<div class="form-group">
<label for="price" class="h3 text-success">Price:</label>
<input id="price" type="text" th:field="*{price}" class="form-control">
</div>
<div class="form-group">
<label for="description" class="h3 text-success">Description:</label>
<textarea class="form-control" rows="5" th:field="*{description}" id="description"></textarea>
</div>
<div class="form-group">
<label for="image" class="h3 text-success">Image:</label>
<input id="image" type="file" th:field="*{multipartFile}" accept="image/**" class="form-control">
</div>
<div class="form-group">
<label for="channel" class="h2 text-secondary">Channels:</label>
<ul class="list-inline">
<li class="list-inline-item" th:each="c : ${channels}">
<input id="channel" type="checkbox" th:field="*{channelIds}" th:value="${c.id}">
<label th:text="${c.name}"></label>
</li>
</ul>
</div>
<button type="submit" class="btn btn-success btn-lg mr-2">Add</button>
</form>
The http request GET /packet/modify is not being handled in your controller and you are redirecting your POST method to that http request:
return "redirect:/packet/modify";
To solve this you need to do one of the following:
Change the redirect request in your POST to an endpoint that is being handled:
return "redirect:/packet/modify/" + packetDto.getPacketId();
Or, handle that GET endpoint:
#GetMapping("/modify/")
public String retrievePacket(...) { ... }
Hope this helps.

400 bad request when submitting form

I can't seem to figure out why I keep getting a 400 bad request. Before I got 400 bad request, the form had "id" instead of "name". When the form had "id" I got 200 but didn't update my database. Now, I get the error and nothing seems to be working.
Here's my controller:
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(MemberVO vo, Model model) {
System.out.println(vo);
logger.info("regist post...");
logger.info(vo.toString());
try {
mservice.insertMember(vo);
} catch (Exception e) {
e.printStackTrace();
}
return "/register_success";
}
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public void registrationGet(MemberVO vo, Model model) {
}
Here's my form:
<form role = "form" method ="post">
<div class="form-group">
<input type="email" class="form-control" name = "username" placeholder="Email" required/>
<span><i class="fa fa-envelope"></i></span>
</div>
<div class="form-group">
<input type="password" class="form-control" name = "password" placeholder="Password" required/>
<span><i class="fa fa-lock"></i></span>
</div>
<div class="form-group">
<input type="text" class="form-control" name = "firstname" placeholder="firstname" required/>
<span><i class="fa fa-user"></i></span>
</div>
<div class="form-group">
<input type="text" class="form-control" name = "lastname" placeholder="lastname" required/>
<span><i class="fa fa-user"></i></span>
</div>
<div class="form-group">
<input type="text" class="form-control" name = "phonenum" placeholder="Phone Number" required/>
<span><i class="fa fa-user"></i></span>
</div>
<div class="form-group">
<input type="text" class="form-control" name = "birthday" placeholder="Birthday, ex) 1986-06-08" required/>
<span><i class="fa fa-user"></i></span>
</div>
<div class="form-group">
<input type="text" class="form-control" name = "destination" placeholder="where would you like to go?" required/>
<span><i class="fa fa-user"></i></span>
</div>
<button type = "submit" class="btn btn-orange btn-block">Sign Up</button>
</form>
We can not tell you the exact problem as you have not attached your modal class MemberVO but you can check below.
1.There is no action attribute in your form.
2.Ensure that all the fields present in Modal class should also be present in the form with the same name.

Required request part 'photo' is not present

I encountered this issue on uploading image file. It say's that there is something part is missing and I have no idea. I have searched so many things already but still I couldn't find a solution. I'm trying to insert it in database and store the file in my project directory. It's seems I have missed something.
here is my html:
<form autocomplete="off" th:action="#{/AddCriminal}"
enctype="multipart/form-data" method="post" class="m-t" role="form"
th:object="${criminalRec}" data-toggle="validator">
<h1 class="text-white">Add Criminal</h1>
<div th:if="${info}" class="alert alert-success" role="alert"
th:text=${info}></div>
<div th:if="${infoError}" class="alert alert-danger" role="alert"
th:text="${infoError}"></div>
<div class="row text-center">
<div class="col-md-5">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"
class="validation-message alert alert-danger" role="alert"></div>
<div th:if="${#fields.hasErrors('seq_number')}"
th:errors="*{seq_number}"
class="validation-message alert alert-danger" role="alert"></div>
<div th:if="${#fields.hasErrors('comments')}"
th:errors="*{comments}"
class="validation-message alert alert-danger" role="alert"></div>
<div class="form-group">
<label class="text-white">Full Name: </label> <input type="text"
th:field="*{name}" placeholder="Wanted Full name"
class="form-control" required /> <small id="firstnameHelp"
class="form-text text-muted text-white">Full name of the
person</small>
</div>
<div class="form-group">
<label class="text-white">Sequence Number: </label> <input
type="text" th:field="*{seq_number}"
placeholder="Sequence Number" class="form-control" required /> <small
id="firstnameHelp" class="form-text text-muted text-white">Sequence
of the records the Ascending order</small>
</div>
<div class="form-group">
<label class="text-white">Photo: </label> <!-- <input type="file"
th:field="*{photo}" placeholder="Add Photo" class="form-control"
accept="image/*" required /> -->
<input type="file" name="photo" accept="image/*" class="form-control" />
<small id="firstnameHelp" class="form-text text-muted text-white">Upload
Photo</small>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<textarea class="form-control" th:field="*{comments}"
placeholder="Facts" rows="3" required></textarea>
<small id="firstnameHelp" class="form-text text-muted text-white">Facts
about this criminal</small>
</div>
</div>
<div class="col-md-5">
<button type="submit" class="btn btn-primary block full-width m-b">Add
Criminal</button>
</div>
</div>
</form>
my controller:
#RequestMapping(value = "/AddCriminal", method = RequestMethod.POST, consumes = "multipart/form-data")
public ModelAndView processCriminal(ModelAndView modelAndView,
#Valid #ModelAttribute("criminalRec") Criminals criminalRec, #RequestParam("photo") MultipartFile file,
BindingResult bindingResult, HttpServletRequest request)
throws SerialException, SQLException, IOException {
if (bindingResult.hasErrors()) {
modelAndView.setViewName("/admin/addwantedperson");
} else {
storageService.store(file);
System.out.println("FILENAME: " + storageService.getFName());
byte [] byteArr=file.getBytes();
Blob blob = new SerialBlob(byteArr);
criminalRec.setPhoto(blob);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.now();
criminalRec.setDate_added(formatter.format(localDate));
criminalService.saveCriminal(criminalRec);
modelAndView.addObject("info", "Criminal Record Successfully Added!");
modelAndView.addObject("criminalRec", new Criminals());
modelAndView.setViewName("/admin/addwantedperson");
}
return modelAndView;
}
In your Application Properties add spring.http.multipart.enabled=true

Spring Web Mvc jQuery AJAX call with post not bidinding from with #ModelAttribute

I am trying to send an AJAX call with jquery to a spring web mvc application. I have a modal which contains a form:
<div id="editTileModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog modal-lg">
<form id="frmEditTileModal" modelAttribute="editTile" class="floating-labels " action="/DESSOApplicationPortalAdmin/rest/tile/002" method="POST">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myLargeModalLabel">Edit Tile</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6" >
<div class="form-group m-b-40 margin-top-20">
<input type="text" class="form-control" id="editTileId" name="id" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileId">Id</label>
</div>
<div class="form-group m-b-40">
<input type="text" class="form-control" id="editTileDescription" name="description" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileDescription">Description</label>
</div>
<div class="form-group m-b-40">
<input type="text" class="form-control" id="editTileRole" name="role" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileRole">Role</label>
</div>
</div>
<div class="col-md-6" >
<div class="form-group m-b-40 margin-top-20">
<input type="text" class="form-control" id="editTileTarget" name="target" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileTarget">Target</label>
</div>
<div class="form-group m-b-40">
<input type="text" class="form-control" id="editTileIndex" name="index" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileIndex">Index</label>
</div>
<div class="form-group m-b-40">
<input type="text" class="form-control" id="editTileTileimagename" name="tileImageName" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileTileimagename">Tile Image Name</label>
</div>
</div>
<div class="col-md-12">
<div class="form-group m-b-40">
<input type="text" class="form-control" id="editTileUrl" name="url" required><span class="highlight"></span> <span class="bar"></span>
<label for="editTileUrl">Url</label>
</div>
</div>
<div class="col-md-12">
<div class="form-group m-b-40 form-check">
<label class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Disable Tile</span>
</label>
</div>
</div>
<div class="row>">
<div class="col-sm-6 col-md-6 col-xs-12">
<div class="white-box">
<h3 class="box-title">Tile Image Normal</h3>
<label for="img-tile-normal">You can add a default value</label>
<input type="file" id="img-tile-normal" class="dropify" data-default-file="resources/vendor/plugins/bower_components/dropify/src/images/test-image-1.jpg" />
</div>
</div>
<div class="col-sm-6 col-md-6 col-xs-12">
<div class="white-box">
<h3 class="box-title">Tile Image on Hover</h3>
<label for="img-tile-on-hover">You can add a default value</label>
<input type="file" id="img-tile-on-hover" class="dropify" data-default-file="resources/vendor/plugins/bower_components/dropify/src/images/test-image-1.jpg" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default waves-effect" data-dismiss="modal">Close</button>
<button id="btnSaveEditTile" type="submit" class="btn btn-danger waves-effect waves-light">Save changes</button>
</div>
</div>
</form>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
This is the jQuery
$('#frmEditTileModal').submit(function (e) {
e.preventDefault();
alert("save edit start!");
var editSuccesFunc = function () {
alert('Success Edit!');
};
var editErrorFunc = function () {
alert('Error Edit!');
};
var tileId = $('#editTileId').val();
alert("data to send: " + $('#editTileId').val());
var formData = new FormData();
formData.append("id", $('#editTileId').val());
formData.append("description", $('#editTileDescription').val());
formData.append("role", $('#editTileRole').val());
$.ajax({
type: "POST",
url: "/DESSOApplicationPortalAdmin/rest/tile/" + tileId,
data: $('#frmEditTileModal').serialize(),
contentType: "application/json",
dataType: "json",
success: editSuccesFunc,
error: editErrorFunc
});
});
and this is the java controller:
#RestController
#RequestMapping(value = "rest/tile")
public class TileRestController {
#Autowired
TileService tileService;
#RequestMapping(value = "/{tileId}", method = RequestMethod.GET)
public Tile getProductById(#PathVariable(value = "tileId") String tileId) {
System.out.println("------------->" + this.getClass().getSimpleName() + ": getProductById called. Searching for Tile Id " + tileId);
return tileService.getTileById(tileId);
}
#RequestMapping(value = "/{tileId}", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
#ResponseBody
public Tile update( #ModelAttribute("editTile") Tile tile, #PathVariable(value = "tileId") String tileId) {
Tile updatedTile = new Tile();
//updatedTile.setId("099");
//updatedTile.setDescription("ExampleTile");
System.out.println("------------->" + this.getClass().getSimpleName() + " update method: print object fields: "+tile.toString());
return updatedTile;
//return tileService.updateTile(tile);
}
}
When I try a doing a normal submit (no ajax or jquery) the controller correctly reads the field to the object.
However when, I try doing the same as an ajax call, it correctly sends the data but the controllers does not map it to an object via modelAttribute("editTile"). Here is a print of the class:
------------->TileRestController update method: print object fields: Tile{ tileImageName=null, description=null, role=null, url=null, target=null, index=0, id=null, disabled=false}
Am I missing something?
EDIT:
I tried a suggestion made in the answers, but it did not seem to work. Here is what I did:
I change the code of the update method in order to use the #RequestBody annotation
#RequestMapping(value = "/{tileId}", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
#ResponseBody
public Tile update( #RequestBody Tile tile, #PathVariable(value = "tileId") String tileId) {
Tile updatedTile = new Tile();
//updatedTile.setId("099");
//updatedTile.setDescription("ExampleTile");
System.out.println("------------->" + this.getClass().getSimpleName() + " update method: print object fields: "+tile.toString());
return updatedTile;
//return tileService.updateTile(tile);
}
plus, I changed my content type as well for the ajax call:
$.ajax({
type: "POST",
url: "/DESSOApplicationPortalAdmin/rest/tile/" + tileId,
data: $('#frmEditTileModal').serialize(),
contentType: "application/www-form-url-encoded",
dataType: "json",
success: editSuccesFunc,
error: editErrorFunc
});
however, now I get an ajax error, it it does not even make the call:
You seem to be Posting a JSON (content-type: application/json) from ajax.
Try using #RequestBody instead of #ModelAttribute for the Tile.
A FORM post normally gets post'ed as content-type: application/www-form-url-encoded.

org.hibernate.PropertyAccessException: Null value was assigned to a property of boolean type

I'm working on java web app, which uses Spring Boot, Hibernate and thymeleaf. At the moment I'm trying to implement registration process for my application and I'm stuck on a problem with my entity class.
Part of User #Entity clas
#Column(name = "aktywny")
private boolean enabled;
#Column(name = "token")
private String confirmationToken;
public boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean value) {
this.enabled = value;
}
Request method
#RequestMapping(value = "/register", method = RequestMethod.POST)
public ModelAndView processRegistrationForm(Model model, ModelAndView modelAndView, #Valid User user, BindingResult bindingResult, #RequestParam Map requestParams, RedirectAttributes redir, HttpServletRequest httpServletRequest){
//Lookup user in db by email
User userExist = userService.findByEmail(user.getEmail());
System.out.println(userExist);
if( userExist != null){
model.addAttribute("alreadyRegisteredMessage", "Użytkownik o podanym adresie e-mail już istnieje");
bindingResult.reject("email");
}
if(bindingResult.hasErrors()){
modelAndView.setViewName("home");
}else {
//set disabled until confirmation link clicked
user.setEnabled(false);
//generate string token
user.setConfirmationToken(UUID.randomUUID().toString());
Zxcvbn passwordCheck = new Zxcvbn();
Strength strength = passwordCheck.measure(requestParams.get("password").toString());
if(strength.getScore() < 3) {
bindingResult.reject("password");
redir.addFlashAttribute("errorMessage", "Twoje hasło jest zbyt słabe, wybierz silniejsze");
modelAndView.setViewName("redirect: confirm?token=" + requestParams.get("token"));
System.out.println(requestParams.get("token"));
// Set new password
user.setPassword(bCryptPasswordEncoder.encode(requestParams.get("password").toString()));
}
userService.saveUser(user);
String appUrl = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName();
SimpleMailMessage registrationEmail = new SimpleMailMessage();
registrationEmail.setTo(user.getEmail());
registrationEmail.setSubject("Potwierdzenie rejestracji");
registrationEmail.setText("Aby dokończyć rejestrację, kliknij w poniższy link: "
+ appUrl + "/confirm?token=" + user.getConfirmationToken());
registrationEmail.setFrom("hotelwaltertorun#gmail.com");
emailService.sendEmail(registrationEmail);
if (user == null) { // No token found in DB
modelAndView.addObject("invalidToken", "Oops! This is an invalid confirmation link.");
} else { // Token found
modelAndView.addObject("confirmationToken", user.getConfirmationToken());
}
model.addAttribute("confirmationMessage", "E-mail potwierdzający został wysłany na adres " + user.getEmail());
modelAndView.setViewName("home");
}
return modelAndView;
}
HTML form code
<form th:autocomplete="on" id="register_form" class="form-horizontal" action="#"
th:action="#{/register}" th:object="${user}" method="post" role="form"
data-toggle="validator">
<input type="hidden" name="token" th:value="${confirmationToken}">
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" th:field="*{firstname}"
placeholder="Imię" class="form-control" required/>
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" th:field="*{lastname}"
placeholder="Nazwisko" class="form-control" required/> </div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" th:field="*{username}"
placeholder="Login" class="form-control" required/>
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input name="password" type="password" id="password"
placeholder="Hasło" class="form-control" required />
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type="password" class="form-control" id="signup-password-confirm" placeholder="Potwierdź hasło" name="ConfirmPassword" data-fv-notempty="true"
data-fv-notempty-message="Please confirm password"
data-fv-identical="true"
data-fv-identical-field="password"
data-fv-identical-message="Both passwords must be identical" />
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
<input type="email" th:field="*{email}"
placeholder="Adres e-mail" class="form-control"
data-error="This email address is invalid" required />
</div>
</div>
<div class="col-md-6 form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-phone"></i></span>
<input type="tel" th:field="*{phone}"
placeholder="Telefon" class="form-control"
data-error="This email address is invalid" required />
</div>
</div>
<div class="col-md-6 form-group">
<button id="register" class="btn btn-success" name="register" style="width:100%;">Zarejestruj <span class="glyphicon glyphicon-send"></span></button>
</div>
</form>
and error description from browser
There was an unexpected error (type=Internal Server Error, status=500).
org.hibernate.PropertyAccessException: Null value was assigned to a property [class com.kaceper.model.User.enabled] of primitive type setter of com.kaceper.model.User.enabled
Thanks for help
Thymeleaf is trying to execute something like this:
user.setEnabled(null)
Which causes a NullPointerException since enabled is a primitive type and can only be true or false.
Change the enabled field to Boolean instead of boolean and update the getter and setter accordingly.

Categories