Cannot load the image from database to thymleaf - spring

This is my editprofile.html:
<form th:action="#{/updateProfile}" method="post" class="signin-form" th:object="${editprofile}" enctype="multipart/form-data">
<div class="title-main text-center mx-auto mb-md-5 mb-4" style="max-width:500px;">
<h5 class="footer-title-29">Personal Details</h5>
<div class="col-sm-6 profile_Pic">
<img id="thumbnail" th:src="*{'data:image/jpg;base64,'+profile_pic}" width="200" />
</div>
</div>
<br><br>
<div class="input-grids">
<label class="control-label" for="name">Name:</label>
<input type="text" th:field="*{name}" id="name" class="contact-input" />
<div class="row">
<div class="col-sm-6">
<label class="control-label" for="mobileNumber">Mobile Number:</label>
<input type="text" th:field="*{mobileNumber}" id="mobileNumber" class="contact-input" />
</div>
<div class="col-sm-6">
<label class="control-label" for="email">Email:</label>
<input type="text" th:field="*{email}" id="email"
class="contact-input" />
</div>
</div>
</div>
<div class="title-main text-center mx-auto mb-md-5 mb-4" style="max-width:500px;">
<h5 class="footer-title-29">Address Details</h5>
</div>
<div class="input-grids">
<label class="control-label" for="address1">Address Line 1:</label>
<input type="text" th:field="*{address1}" id="address1" class="contact-input" />
<label for="address2">Address Line 2:</label>
<input type="text" th:field="*{address2}" id="address2" class="contact-input" />
<label class="control-label" for="city">City:</label>
<input type="text" th:field="*{city}" id="city" class="contact-input" />
<div class="row">
<div class="col-sm-6">
<label class="control-label" for="state">State:</label>
<input type="text" th:field="*{state}" id="state"
class="contact-input" />
</div>
<div class="col-sm-6">
<label class="control-label" for="zipCode">Zip Code:</label>
<input type="text" th:field="*{zipCode}" id="zipCode"
class="contact-input" />
</div>
<div class="col-sm-6">
<label class="control-label" for="fileImage">Upload image</label>
<input type="file" name="fileImage" accept="image/*" id="fileImage" />
</div>
</div>
</div>
<div class="col-md-8 login-center text-start">
<button class="btn btn-style btn-style-3 text-left" >Update</button>
<a th:href="#{/dashboard}" class="new-user text-right">
<button class="btn btn-style btn-style-3 text-left" th:formaction="#{/displayProfile}">BACK</button></a>
</div>
</form>
I did a compress and decompress when adding and retrieving the data from db
Code: ImageUtil.java
public static byte[] compressImage(byte[] data) {
Deflater deflater = new Deflater();
deflater.setLevel(Deflater.BEST_COMPRESSION);
deflater.setInput(data);
deflater.finish();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] tmp = new byte[1024];
while (!deflater.finished()) {
int size = deflater.deflate(tmp);
outputStream.write(tmp, 0, size);
}
try {
outputStream.close();
} catch (Exception e) {
}
return outputStream.toByteArray();
}
public static byte[] decompressImage(byte[] data) {
Inflater inflater = new Inflater();
inflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] tmp = new byte[1024];
try {
while (!inflater.finished()) {
int count = inflater.inflate(tmp);
outputStream.write(tmp, 0, count);
}
outputStream.close();
} catch (Exception exception) {
}
return outputStream.toByteArray();
}
I upload the image like:
person.getAddress().setProfile_pic(ImageUtil.compressImage(file.getBytes()));
personRepository.save(person);
And the image is saved to db successfully
The problem is image cannot be displayed.I did this when retrieving the data from db:
byte[] decomImage = ImageUtil.decompressImage(person.getAddress().getProfile_pic());
byte[] encodeBase64 = Base64.getEncoder().encode(decomImage);
String base64Encoded = new String(encodeBase64, "UTF-8");
pojoprofile.setEncoded_image(base64Encoded);
I cannot retrieve the image and display it. I tried decompress the image and converted it into Base64 to display it in the thymleaf.
This is my controller class to upload image to database:
#RequestMapping(value = "/EditProfile")
public ModelAndView EditProfile(Model model, HttpSession httpSession){
PersonPojo person=(PersonPojo) httpSession.getAttribute("loggedInPerson");
Profile pojoprofile1=new Profile();
pojoprofile1.setName(person.getName());
pojoprofile1.setEmail(person.getEmail());
pojoprofile1.setMobileNumber(person.getMobileNumber());
if(person.getAddress()!=null&&person.getAddress().getAddressId()>0){
pojoprofile1.setAddress1(person.getAddress().getAddress1());
pojoprofile1.setAddress2(person.getAddress().getAddress2());
pojoprofile1.setCity(person.getAddress().getCity());
pojoprofile1.setState(person.getAddress().getState());
pojoprofile1.setZipCode(person.getAddress().getZip_code());
pojoprofile1.setProfile_pic(Base64.getEncoder().encode(person.getAddress().getProfile_pic()));
// pojoprofile1.setProfile_pic(person.getAddress().getProfile_pic());
}
ModelAndView editprofile=new ModelAndView("EditProfile.html");
editprofile.addObject("editprofile",pojoprofile1);
return editprofile;
}
#RequestMapping(value = "/updateProfile")
public String updateProfile(#RequestParam("fileImage") MultipartFile file, #Valid #ModelAttribute("editprofile") Profile profile, Errors errors,
HttpSession httpSession) throws IOException {
if(errors.hasErrors()){
return "EditProfile.html";
}
PersonPojo person=(PersonPojo) httpSession.getAttribute("loggedInPerson");
person.setName(profile.getName());
person.setEmail(profile.getEmail());
person.setMobileNumber(profile.getMobileNumber());
if(person.getAddress() == null || !(person.getAddress().getAddressId()>0)){
person.setAddress(new AddressPoJO());
}
person.getAddress().setAddress1(profile.getAddress1());
person.getAddress().setAddress2(profile.getAddress2());
person.getAddress().setCity(profile.getCity());
person.getAddress().setState(profile.getState());
person.getAddress().setZip_code(profile.getZipCode());
person.getAddress().setProfile_pic(ImageUtil.compressImage(file.getBytes()));
personRepository.save(person);
httpSession.setAttribute("loggedInPerson", person);
return "redirect:/dashboard";
}
Controller to display the content in Profile page:
#RequestMapping("/displayProfile")
public ModelAndView Myprofile(HttpSession httpSession) throws UnsupportedEncodingException {
Profile pojoprofile=new Profile();
PersonPojo person=(PersonPojo) httpSession.getAttribute("loggedInPerson");
pojoprofile.setName(person.getName());
pojoprofile.setEmail(person.getEmail());
pojoprofile.setMobileNumber(person.getMobileNumber());
if(person.getAddress()!=null&&person.getAddress().getAddressId()>0){
log.info("Inside the if"+new MyProfile().getClass().toString());
pojoprofile.setAddress1(person.getAddress().getAddress1());
pojoprofile.setAddress2(person.getAddress().getAddress2());
pojoprofile.setCity(person.getAddress().getCity());
pojoprofile.setState(person.getAddress().getState());
pojoprofile.setZipCode(person.getAddress().getZip_code());
byte[] encodeBase64 = Base64.getEncoder().encode(ImageUtil.decompressImage(person.getAddress().getProfile_pic()));
pojoprofile.setProfile_pic(encodeBase64);
}else {
pojoprofile.setAddress1(" Not available ");
pojoprofile.setAddress2(" Not Available");
pojoprofile.setZipCode(" Not Available");
pojoprofile.setState(" Not Available");
pojoprofile.setCity(" Not Available");
}
return new ModelAndView("profile.html").addObject("profile",pojoprofile);
}

You should return a String representation of an image, rather than a byte array. So change your code to
String encodeBase64 = Base64.getEncoder().encodeToString(person.getAddress().getProfilePic());
pojoprofile.setProfilePic(encodeBase64);
This means that Profile.profilePic is also a String. ( person.getAddress().getProfilePic()should return a valid byte array)
EDIT:
If you just want to make sure that this works without changing much of your code, I suggest adding a String field to Profile.java and setting that field with a hardcoded base64 image in your controller.
private String testImg; //in Profile.java
//in your controller
String picbase64 = "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";
pojoprofile.setTestImg(picbase64);
You will have adjust profile.html as well to include this new field. (anyway I tested this and it's working as expected)
The fastest way to test your current code would be to call setProfilePic with a base64 hardcoded image
pojoprofile.setProfilePic( "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" );
The Profile class should be changed as well, since we're now using a String instead of a byte[]
class Profile {
//base64 encoded image
private String profilePic;//private byte[] profilePic;
....
}

Related

In springboot,How to store image of my customer in local system and store the image path in the database?

This is my customer entity
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String relative;
private String address;
private Long aadhar;
private Long contact;
private String townname;
private String imagePath;
this is my controller function to add new customer, i dont know whether i did this corrrectly, i meant to store the imagepath in customer table and images in the custimages folder in static folder,this savCustomer saves the other fields from the form since the form input name and column name are same
#PostMapping("/customer/addnew")
public String addNew(Customer customer, RedirectAttributes redirectAttributes,#RequestParam("image") MultipartFile snapshot) throws IOException {
if (!snapshot.isEmpty()) {
try {
// Generate a random file name
String fileName = UUID.randomUUID().toString() + ".jpg";
// Create a File object to save the image
File file = new File("src/main/resources/static/custimages/" + fileName);
// Save the snapshot to the file
snapshot.transferTo(file);
// Set the imagePath field in the Customer entity
customer.setImagePath(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
customerService.saveCustomer(customer);
redirectAttributes.addFlashAttribute("addcustomermessage", "added successfully");
return "redirect:/customer";
}
this is my html form
<form class="row g-3" th:action="#{/customer/addnew}"
method="post" enctype="multipart/form-data">
<div class="col-md-12">
<label for="image">Upload Image</label> <input type="file"
id="image" name="image" accept="image/*">
<div class="row">
<div class="col-md-5">
<canvas id="snapshot" width="280" height="200"
style="transform: scaleX(-1)"></canvas>
</div>
<div class="col-md-2">
<button type="button" id="capture" class="btn btn-info">Capture</button>
</div>
<div class="col-md-5">
<video id="camera-stream" autoplay width="280" height="200"
style="transform: scaleX(-1);"></video>
</div>
</div>
</div>
<div class="col-md-4">
<label for="aadhar" class="form-label">ஆதார் எண்</label> <input
type="number" min="0" max="999999999999" class="form-control"
id="aadhar" name="aadhar" required>
</div>
<div class="col-md-8">
<label for="customername" class="form-label">பெயர்</label> <input
type="text" class="form-control" id="name" name="name"
onKeyup="this.value = this.value.toUpperCase()" required>
</div>
<div class="col-md-6">
<label for="relative" class="form-label">S/o,D/o,W/o,C/o</label>
<input type="text" class="form-control" id="relative"
name="relative" onKeyup="this.value = this.value.toUpperCase()"
required>
</div>
<div class="col-md-6">
<label for="contact" class="form-label">தொலைபேசி எண்</label> <input
type="number" min="10" max="9999999999" class="form-control"
id="contact" name="contact" required>
</div>
<div class="col-12">
<label for="inputAddress5" class="form-label">முகவரி</label> <input
type="text" class="form-control" id="address" name="address"
onKeyup="this.value = this.value.toUpperCase()"
placeholder="1234 Main St" required>
</div>
<div class="col-md-4">
<label for="inputTown" class="form-label" id="selecttown">ஊர்</label>
<select class="form-control" id="selecttown" name="townname"
required>
<option selected></option>
<option th:each="town:${towns}" th:value="${town.townname}"
th:text="${town.townname}">...</option>
</select>
</div>
<script>
const constraints = {
video: true
};
const cameraStream = document.getElementById('camera-stream');
const snapshotCanvas = document.getElementById('snapshot');
const context = snapshotCanvas.getContext('2d');
const form = document.querySelector('form');
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
cameraStream.srcObject = stream;
});
document.getElementById("capture").addEventListener("click", function() {
var canvas = document.getElementById('snapshot');
var video = document.getElementById('camera-stream');
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, 280, 200);
canvas.toBlob(function(blob) {
var file = new File([blob], generateFileName(), { type: 'image/jpeg' });
// Add the file to the form data
var formData = new FormData();
formData.append('image', file);
}, 'image/jpeg', 1);
function generateFileName() {
var prefix = "customer_";
var randomNumber = Math.floor(Math.random() * 1000000);
var fileName = prefix + randomNumber + ".jpg";
return fileName;
}
});
</script>
<div class="text-center" style="margin-bottom: 10px">
<button type="submit" class="btn btn-primary mx-1 my-1">Submit</button>
<button type="reset" class="btn btn-secondary mx-1 my-1">Reset</button>
</div>
</form>
this form has the fields for customer data as well as the first field streams the video inside the form and when i hit the caputre button it took a snapshot and post it as a thumbnail within the form itself , i have a inline code to do these functions, and also it appends the captured snapshot to append it to the image input and once i hit submit my controller function will save the image and the path to the customer table, but the other fields are updated properly in the table, but the image was not uploaded to the custimages folder as well as the imagepath is also null. I am just learning am i doing anything wrong here or am i complicating the code here, instead of easy way.
This might not be the exact answer you're looking for.
But on of the options / solution to store images, you can transform them a base64 image (string format) and store it as a string in your database.
Don't worry about ready the image in your html code because <img src ="${imgUrl}" > will understand the base64 format and display it correctly.
I hope this unlocks you

Upload file with Boostrap Modal on Asp.net core 2.1

I want to upload a file and send to email. But I don't see how to do this with Bootsrap Modal.
If you want any other information, tell me.
I would like to send the attached file by email then also integrate it in my database and be able to download it.
/[...]/ ==> Code that I didn't add, not useful.
Edit : Otherwise how to do with Ajax ?
My View :
<form name="contact" method="post" asp-action="Validation">
#if (ViewBag.Alert != null && ViewBag.Alert != "")
{
<div class="alert role="alert">
#ViewBag.Alert
</div>
}
<div class="details">
<h3 class="title">Demande</h3>
<label for="card">Type *</label>
<select required onchange="contact()" class=" form-control" disabled="true" name="type" value="#ViewBag.Form.Type">
<option value="1">Choose 1</option>
<option value="2">Choose 2</option>
</select>
<label for="card">Origine *</label>
<select required class="form-control" name="origine" value="#ViewBag.Form.Origine">
<option value="1">Origine 1</option>
<option value="2">Origine 2</option>
<option value="3">Origine 3</option>
</select>
/*[...]*/
<input type="hidden" name="Id" value="#ViewBag.Form.Id" />
<input type="hidden" name="Price" value="#ViewBag.Form.Price" />
/*[...]*/
<textarea class="form-control" name="Response" placeholder="Response..."></textarea>
<button required class="btn" onclick="modal_response()" data-whatever="getbootstrap" data-toggle="modal" data-target="#modal_contact" type="button">Response</button>
<label for="card" class="right">Response send</label><br />
<button required class="btn_second" onclick="modal_save()" data-whatever="getbootstrap" data-toggle="modal" data-target="#modal_contact_save" type="button">Save</button>
<label for="card-holder" class="right">Save Ok!</label>
/*[...]*/
<div class="form-row">
<button class="btn-primary" onclick="form_confirmation()" type="submit">Save All</button>
<button class="btn-secondary" type="reset" onclick="location.href = '#Url.Action("List", "Control", new { id = ViewBag.Id })';">Close</button>
</div>
</div>
</form>
/* When I click on "Response" a new window open */
<div class="modal fade" id="modal_contact" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<h5 class="modal-title" id="modal_label">Send email to : #ViewBag.Form.Name</h5>
<button type="button" class="close" data-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="modal_contact_form" enctype = "multipart/form-data" method="post" action="#Url.Action("Modal_contact", "Control")">
<div class="form-group">
<input type="file" name="file" accept="application/pdf" /><br /><br />
<textarea class="form-control" name="Description" required placeholder="Content">#ViewBag.Response</textarea>
</div>
<input type="hidden" name="Id" value="ID" hidden />
<input type="hidden" name="Price" value="#ViewBag.Form.Price" hidden />
<input type="hidden" name="Type" value="#ViewBag.Form.Type" hidden />
/*[...]*/
<input type="submit" hidden />
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" data-dismiss="modal" onclick="$('#modal_contact_form').submit();" class="btn-primary">Send Email</button>
</div>
</div>
My Controller :
public class MyController : BaseEntity
{
[Required]
public string Id { get; set; }
public string Price { get; set; }
public string Type { get; set; }
/*[...]*/
/* For File I don't know if it's good?? */
public IformFile File { get; set; }
}
My Model :
public ActionResult Modal_contact(MyController model)
{
/* How to retrieve file ?? */
bool ok = false;
OtherController OC = new OtherController();
/*[...]*/
if (ModelState.IsValid)
{
OC = othercontrollerRepository.Find(model.Id);
OC.Email = this.Session_get("Email");
OC.Description = "";
model.Email = this.Session_get("Email");
model.Status = "1";
model.View = "response";
/*[...]*/
if (mycontrollerRepository.Add(model) && othercontrollerRepository.Update(OC))
{
/* How to send file to email and save file to folder in my project to add in my database ? */
MailManager mail = new MailManager();
Modele modele = new Modele();
modele= modeleRepository.Find("response");
ok = mail.send(modele.Objet, model.Description, OC.Email);
}
return Json(new { Json_result = ok, Redirect = "" });
}
return Json(new { Json_result = false, Redirect = "" });
}
I found my error :
Form before <div>
I tried your code and reproduced your issue. I noticed that you named the IFormFile object as File.
public IFormFile File { get; set; }
But input file you are getting is named file.
<input type="file" name="file" accept="application/pdf"/><br /><br />
Asp.net core model binding will bind the property according to the input name. This is the reason why you couldn't get the IFormFile value in controller.
To solve this issue, you should change the name of the input to File so that they could match each other.
Like below:
<input type="file" name="File" accept="application/pdf"/><br /><br />
Result:

Spring Required request part 'file' is not present

I'm trying to upload an image with a form, it's going to be the profile picture, but I get the error:
Required request part 'file' is not present
I'm really new with spring, so I don't know what's wrong here's part of the code:
This is the form
<form th:action="#{/form}" th:object="${cliente}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label>Nombre</label>
<input class="form-control" type="text" th:field="*{nombre}" placeholder="Nombre"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('nombre')}" th:errors="*{nombre}"></small>
</div>
<div class="form-group">
<label>Apellido</label>
<input class="form-control" type="text" th:field="*{apellido}" placeholder="Apellido"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('apellido')}" th:errors="*{apellido}"></small>
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="text" th:field="*{email}" placeholder="correo#ejemplo.com"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></small>
</div>
<div class="form-group">
<label>Fecha</label>
<input class="form-control" type="text" th:field="*{createAt}" placeholder="DD/MM/YYYY"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('createAt')}" th:errors="*{createAt}"></small>
</div>
<div class="form-group">
<label>Imagen</label>
<input type="file" name="file" class="form-control" th:field="*{foto}">
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Guardar Cambios" />
</div>
<input type="hidden" th:field="*{id}" />
</form>
This is the controller function
#RequestMapping(value="/form", method=RequestMethod.POST)
public String guardar(#Valid Cliente cliente, BindingResult result,
#RequestParam("file") MultipartFile foto, RedirectAttributes flash) {
String mensaje;
if(result.hasErrors()) {
return "form";
}
if(!foto.isEmpty()) {
Path directorioRecursos = Paths.get("src//main//resources//static/uploads");
String pathRoot = directorioRecursos.toFile().getAbsolutePath();
try {
byte[] bytes = foto.getBytes();
Path rutaCompleta = Paths.get(pathRoot + "//" + foto.getOriginalFilename());
Files.write(rutaCompleta, bytes);
flash.addFlashAttribute("info", "Foto subida correctamente");
cliente.setFoto(foto.getOriginalFilename());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(cliente.getId() != null) {
mensaje = "Cliente actualizado correctamente";
}
else {
mensaje = "Cliente creado correctamente";
}
clienteservice.save(cliente);
flash.addFlashAttribute("success", mensaje);
return "redirect:listar";
}
This is my application properties
spring.http.multipart.file-size=10MB
spring.http.multipart.max-request-size=10MB
spring.http.multipart.enabled=true
Can you see what's wrong?
you're attaching a file to a string field with the th:field="*{foto}" ,
remove the th:field part in the input , should be like this:
<input type="file" name="file" class="form-control" />

How tell the view an error has occured from controller? (Spring MVC)

How can I say trigger error/validation messages in the view from the controller in a better way? Currently, I do this by sending boolean attributes. For example, in creating a product, I have two possible errors. Invalid format of UPC of a product, or duplicate upc. I also have a validati
#RequestMapping("/createProduct")
public String createProduct(Model model, #RequestParam(value = "name") String name,
#RequestParam(value = "upc") String upc, #RequestParam(value = "category") String categoryName,
#RequestParam(value = "description") String description, #RequestParam(value = "price") BigDecimal price,
#RequestParam(value = "stock") int stock){
model.addAttribute("activeTab", 3);
if(Validator.invalidUpcFormat(upc)){
model.addAttribute("invalidFormat", true); //trigger for invalid format
return "management";
}
Category category = productService.getCategory(categoryName);
Product product = new Product(upc, category, name, description, price);
InventoryProduct inventoryProduct = new InventoryProduct(product, stock);
try {
managerService.add(inventoryProduct);
model.addAttribute("productCreated", true);
} catch (DuplicateProductException e) {
model.addAttribute("upc", upc);
model.addAttribute("duplicateProduct", true); // trigger for duplicate product
}
return "management";
}
And here is my view:
<div id="menu3"
class="tab-pane fade <c:if test="${activeTab == 3}">in active</c:if>">
<div class="container-fluid" style="padding: 2%;">
<div class="row">
<div class="col-md-12"
style="padding-left: 15%; padding-right: 15%;">
<c:if test="${productCreated}">
<div class="alert alert-success fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Success!</strong>
Product has been created!
</div>
</c:if>
<c:if test="${duplicateProduct}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oh no!</strong>
Product with the UPC ${upc} already exists!
</div>
</c:if>
<c:if test="${invalidFormat}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oops!</strong>
Invalid UPC format!
</div>
</c:if>
<form
action="${pageContext.request.contextPath}/manager/createProduct"
method="post">
<div class="form-group">
<label for="Name">Name </label> <input type="text" name="name"
class="form-control" required />
</div>
<div class="form-group">
<label for="UPC">UPC </label> <input type="number" name="upc"
class="form-control" required />
</div>
<div class="form-group">
<div class="form-group">
<label for="category">Category</label> <select
class="form-control" name="category" required>
<option selected disabled value="">SELECT CATEGORY</option>
<c:forEach items="${categories}" var="item">
<option>${item.getName()}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" rows="5" name="description"></textarea>
</div>
<div class="form-group">
<label for="price">Price </label> <input type="number"
name="price" class="form-control" required />
</div>
<div class="form-group">
<label for="stock">Stock </label> <input type="number"
name="stock" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary">Add
product</button>
</form>
</div>
</div>
</div>
</div>
Is there a better of doing this other than sending boolean triggers?
You could use Spring BindingResult. This is typical filled with the result of Binding and Validation results. But you can also add errors by hand.
But first you need to refactor your code, so that you use an single command/form-backing object instead of all the #Param values
public class CreateProductCommand {
private String name;
private String upc;
private String categoryName;
.... //other fields
public CreateProductCommand (){} //parameter less conturctor
Getter+Setter
}
Controller
#RequestMapping("/createProduct")
public ModelAndView createProduct(CreateProductCommand createProductCommand, BindingResult bindingResult) //Binding result must be the parameter direct next to the object that should been validated!!!
{
if (someustomValidationForUcpFail()) {
bindingResult.rejectValue("upc", //the field name of the invalid field
"error.Message.Key",
"Default Error Message");
}
if (bindingResult.hasErrors()) {
ModelMap model = new ModelMap();
model.add("createProductCommand", createProductCommand);
return new ModelAndView("createForm", model)
} else {
Product product = ...
return new ModelAndView("showProduct", "product", product)
}
}
jsp:
You need to use springs form and input tag:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:springForm="http://www.springframework.org/tags/form"
version="2.0">
....
<springForm:form action="<c:url value="/manager/createProduct">" method="POST" modelAttribute="createProductCommand">
<springForm:input path="name"/> <form:errors path="name" />
<springForm:input path="ucp"/> <form:errors path="ucp" />
....
</springForm:form>
....

send data from jsp to controller using model attribute

<body>
<jsp:useBean id="loginBean" class="com.ss.sms.bean.LoginBean"></jsp:useBean>
<div class="row">
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">Log in</div>
<div class="panel-body">
form:form id="loginForm" method="post" action="login" modelAttribute="login">
<fieldset>
<div class="form-group">
<input class="form-control" placeholder="UserId" name="userId" type="text" autofocus="autofocus" value=${loginBean.userName}>
</div>
<div class="form-group">
<input class="form-control" placeholder="Password" name="password" type="password" value=${loginBean.password}>
</div>
<div class="checkbox">
<label>
<input name="remember" type="checkbox" value="Remember Me">Remember Me
</label>
</div>
<input type="submit" class="btn btn-primary">
<div style="color: red">${error}</div>
</fieldset>
</form:form>
</div>
</div>
</div><!-- /.col-->
</div><!-- /.row -->
#RequestMapping(value="/login",method = RequestMethod.POST)
public ModelAndView login(Model md,#ModelAttribute("login")LoginBean loginBean) {
System.out.println("hello done");
System.out.println(loginBean.getUserName());
ModelAndView model = null;
if (loginBean != null && loginBean.getUserName() != null & loginBean.getPassword() != null) {
if (loginBean.getUserName().equals("santosh") && loginBean.getPassword().equals("Santosh#123")) {
model = new ModelAndView("hello");
return model;
} else {
model = new ModelAndView("login");
return model;
}
} else {
model = new ModelAndView("login");
return model;
}
}
if i understand correctly fromn your code you have problem seeing the page correctly.
In your ModelAndView you add just the view and not the model
So you need to add the object
Hence, the code can look something like that
#RequestMapping(value="/login",method = RequestMethod.POST) public ModelAndView login(Model md,#ModelAttribute("login")LoginBean loginBean) {
System.out.println("hello done");
System.out.println(loginBean.getUserName());
ModelAndView model = null;
if (loginBean != null && loginBean.getUserName() != null & loginBean.getPassword() != null) {
if (loginBean.getUserName().equals("santosh") && loginBean.getPassword().equals("Santosh#123")) {
//if the view hello expects an object add it here
model = new ModelAndView("hello");
return model;
} else {
model = new ModelAndView("login").addObject("login",loginBean);
return model;
}
} else {
model = new ModelAndView("login").addObject("login",loginBean);
return model;
}
}

Resources