I have created a form that has 2 file uploads and a few text content, it successfully uploads data in DB, when I'm trying to re-edit/update the same form. Either I'm getting bad request error if I use Multipart along with entity class. If I use multipart without entity it is creating new records but not updating the old records.
when add the entity class to this along with #RequestParam("file") MultipartFile file to save the file and other details iam getting an error while updating data.
Following is code:
#PostMapping("/update")
public String update(#RequestParam("bookPath") MultipartFile file, #RequestParam("bookCover") MultipartFile cover,
#RequestParam("bookName") String bookName, #RequestParam("totalpages") String totalpage,
#RequestParam("bookAuthor") String BA,#RequestParam("bookPrice") String Bp,
#RequestParam("bookPublicationDate") String bpd, #RequestParam("bookRating") String bookRating,
#RequestParam("bookDesc") String Bdes, #RequestParam("ReadingAge") String readingAge,
#RequestParam("AudioBook") String Ab,#RequestParam("isbn_num") String isbn,
#RequestParam("status") String satus,
#RequestParam("discount_option") String discount, #RequestParam("genres") String genras,
#RequestParam("dicsounted_price") String fixed_dis,
#RequestParam("percentge_value") String percentage, Book_dtls b)
Book_dtls is the entity class.
Error Imagelike below image.
i want to update the data along with files
Related
I'm trying to send a post request from Thymeleaf to my controller. The page dynamically creates new input fields when a button is pressed and the page can have multiple of these fields.
function addNewRow(){
let row = document.createElement("tr");
let data = document.createElement("td");
let floorData = document.createElement("td");
let imageData = document.createElement("td");
let floorInput = document.createElement("input");
let imageInput = document.createElement("input");
row.setAttribute("id","newAdditions");
floorInput.setAttribute("id","floorNumber");
floorInput.setAttribute("type", "text");
floorInput.setAttribute("placeHolder", "Floor Number");
floorInput.setAttribute("class", "form-control floorNumber");
floorData.setAttribute("id", "floorNumberData")
floorData.appendChild(floorInput);
imageInput.setAttribute("type","file");
imageInput.setAttribute("accept","image/*");
imageInput.setAttribute("id","imageData");
imageInput.setAttribute("class","imageData");
imageData.appendChild(imageInput);
row.appendChild(data);
row.appendChild(floorData);
row.appendChild(imageData);
document.getElementById("tableBody").appendChild(row);
}
Now when the submit button is pressed, the images (imageData) is passed into a List along with the floorNumber
function submitImages(){
let allItems = document.querySelectorAll('[id=newAdditions]');
for(let i = 0; i < allItems.length; i++){
let floor = allItems[i].getElementsByClassName('floorNumber');
let image = allItems[i].getElementsByClassName('imageData');
floor[0].setAttribute("name", "images[" + i +"].floorNumber");
image[0].setAttribute("name", "images[" + i +"].floorImage");
}
$('#floorForm').submit();
}
My #ModelAttribute/Dto class is as below
public class UploadFormDto{
private List<UploadData> images;
private Long id;
getters & setters
}
UploadFormDto contains
public class UploadData{
private MultipartFile floorImage;
private String floorNumber;
getters & setters
}
And my controller method is as below
#PostMapping(value = "/edit")
#Transactional
public String handleEditHotelRooms(#ModelAttribute("editForm") UploadFormDto editForm,
#PathVariable("hotelId") Hotel hotel,
BindingResult result, RedirectAttributes redirectAttributes) throws WebActionException {}
ISSUE: When the form is sent through, the list of objects populate the floorNumber correctly but the file is never sent through. What am i doing wrong or missing?
My thymeleaf page does not have the enctype='multipart/form-data' because if I add it, the controller complains that the "Current request is not a multipart request"
So i finally managed to fix this, the issue was not in the js or the DTO. The issue was on the Thymeleaf page itself, i had "ajax-form=true" in the form attribute of the page. Once that was removed, I was able to submit the form correctly and get all the images to the controller.
I am trying to use opencsv to parse a csv file like this:
name,purchase,date
TEST,TEST,2020-10-20T00:37:53.562000000Z
TEST,TEST,2020-10-20T00:37:53.562000000Z
I am trying to add the parsed data to a firebase database following this tutorial: https://attacomsian.com/blog/spring-boot-upload-parse-csv-file. This is my class for the data:
public class Records {
#CsvBindByName
private String name;
#CsvBindByName
private String purchase;
#CsvBindByName
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
When I parse the file I get this error:
Exception in thread "pool-6-thread-2" Exception in thread "pool-6-thread-1" Exception in thread "pool-6-thread-4" Exception in thread "pool-6-thread-3" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:99)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException: Conversion of 2022-10-20T00:37:53.562000000Z to com.google.cloud.Timestamp failed.
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:128)
at com.opencsv.bean.BeanFieldSingleValue.convert(BeanFieldSingleValue.java:98)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:180)
at com.opencsv.bean.AbstractMappingStrategy.setFieldValue(AbstractMappingStrategy.java:581)
at com.opencsv.bean.AbstractMappingStrategy.populateNewBean(AbstractMappingStrategy.java:328)
at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:128)
at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:83)
... 3 more
Caused by: org.apache.commons.beanutils.ConversionException: Can't convert value '2022-10-20T00:37:53.562000000Z' to type class com.google.cloud.Timestamp
at org.apache.commons.beanutils.converters.AbstractConverter.conversionException(AbstractConverter.java:474)
at org.apache.commons.beanutils.converters.StringConverter.convertToType(StringConverter.java:96)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
at com.opencsv.bean.ConverterPrimitiveTypes.convertToRead(ConverterPrimitiveTypes.java:118)
... 9 more
How can i fix this error? Do I need to change the format of the date column? I copied the date format from a record in the database so that format is how it should be stored in the database
I changed the csv format to:
name,purchase,date
TEST,TEST,2018-09-16T08:00:00
TEST,TEST,2018-09-16T08:00:00
I modified the class that binds to the csv to look like this:
public class CsvRecords {
#CsvBindByName
private String name;
#CsvBindByName
private String purchase;
#CsvBindByName
private String date;
// get and setters left out for brevity pls comment if needed
}
The POJO class for the data in db:
public class Records {
private String name;
private String purchase;
private Timestamp date;
// get and setters left out for brevity pls comment if needed
}
When uploading in the controller class I then convert the string to LocalDateTime and then again to Timestamp like this:
#PostMapping("/upload-csv-file")
public String uploadCSVFile(#RequestParam("file") MultipartFile file, Model model) {
// validate file
if (file.isEmpty()) {
model.addAttribute("message", "Please select a CSV file to upload.");
model.addAttribute("status", false);
} else {
// parse CSV file to create a list of `User` objects
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
// create csv bean reader
CsvToBean<Records> csvToBean = new CsvToBeanBuilder(reader)
.withType(Records.class)
.withIgnoreLeadingWhiteSpace(true)
.build();
// convert `CsvToBean` object to list of records
List<Records> records = csvToBean.parse();
// save users in DB?
for(int i = 0; i<records.size(); i++){
LocalDateTime localDateTime = LocalDateTime.parse(records.get(i).getDate);
Timestamp timestamp = Timestamp.valueOf(localDateTime);
Records rec = new Records(records.get(i).getName(), records.get(i).getPurchase(), timestamp)
firebaseServices.saveDetails(rec);
}
} catch (Exception ex) {
model.addAttribute("message", "An error occurred while processing the CSV file.");
model.addAttribute("status", false);
}
}
return "file-upload-status";
}
For details on the implementation of the firebaseServices class (saveDetails method) I used this tutorial
Could you have a try in this case that replaces the Timestamp to Date?
like follow this:
#CsvBindByName private Date date;
The timestamp field object is an instance from com.google.cloud.Timestamp package.
As #Allen suggested, you might have to look into java.util.date or event better, the Java 8 time APIs java.time.LocalTime to get support from ConverterPrimitiveTypes to be converted automatically.
I have one file Person.Java
public class Person {
private String firstName;
private String lastName;
}
file is stored at location say : "C:\Users\Person.Java"; This file is not part of the project.
I have written REST API endpoint which is accepting this file as a input and reading this file.
#PostMapping(value = "/poc/jsobj", produces = {APPLICATION_JSON_VALUE})
public ResponseEntity<ResponseMessage> convertToJson(#RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
String completeData = new String(bytes);
//what should I write here
}}
After reading I want to convert content of this file into JSON format.
{
"firstName":" ",
"lastName":" "
}
so, the requirement is take java file (a class) as input to controller and generate corresponding json String as it's output.
ProductController.java
#RequestMapping(value = "/adminWelcome", method = RequestMethod.GET)
public String getAdminWelcomePage(Model model) {
System.out.println("Product List:" + productService.getAllProducts());
model.addAttribute("productList", productService.getAllProducts());
return "adminHomepage";
}
ProductService.java
public List<Map<String, Object>> getAllProducts() {
String sql = "SELECT * FROM products LIMIT 3";
List<Map<String, Object>> products = jdbcTemplate.queryForList(sql);
return products;
}
Basically, this sql return the list of 3 products which are looks like
Product List:[{id=1, name=Twitter-minimal, userId=0, image=[B#96a7858, price=1213322.0, dateManufacture=2017-02-07, dateAdded=2017-02-07 15:50:12.0, category=Clothing, description=ramedadadadad}].
This is the sample of the result which I fetched from MySql database with jdbcTemplate. I upload the image using Spring MVC4 in the database. Now I want to retrieve or read the Blobimage type so that I can display those images to my jsp pages. How can I convert this Blob image so that I can properly display to pages?
The image type was defined as MultipartFile image in the domain class.
yo need resource mapping in dispatcher-servlet.xml
and
add this in your jsp page..
where static as i have defined is /WEB-INF/assets/
I am learning how to write REST APIs! How can I store form values into a text file, using rest calls?
index.html
<form action="rest/product/adddata" method="post">
Enter Id:<input type="text" name="id"/><br/><br/>
Enter Name:<input type="text" name="name"/><br/><br/>
Enter Price:<input type="text" name="price"/><br/><br/>
<input type="submit" value="Add Product"/>
</form>
service.java
#Path("/product")
public class ProductService{
#POST
#Path("/adddata")
public Response addUser(
#FormParam("id") int id,
#FormParam("name") String name,
#FormParam("price") float price) {
return Response.status(200)
.entity(" Product added successfuly!<br> Id: "+id+"<br> Name: " + name+"<br> Price: "+price)
.build();
}
}
I want to add value of id, name and price to a file. Where do I need to write function for adding data to file?
write code into
public Response addUser(
#FormParam("id") int id,
#FormParam("name") String name,
#FormParam("price") float price) {
saveFile(id,name,price);
return Response.status(200)
.entity(" Product added successfuly!<br> Id: "+id+"<br> Name: " + name+"<br> Price: "+price)
.build();
}
write code into saveFile to save into file
The best approach for doing this will be to create another class which can write and read from files. And inject that class in this rest endpoint.
Because The direct code in rest endpoint class should be to handle request not to write files
class FormSynchronizer {
public static final File FORM_BASE = new File(...); // The location of directory which will contain all these files
public void storeFile(Map map, String fileName){
File toStoreFile = new File(FORM_BASE, fileName);
/* Write code to store file */
}
}
Inject this class in your rest endpoint class
public class ProductService{
#Inject FormSynchronizer formSynchronizer;
#POST
#Path("/adddata")
public Response addUser(
#FormParam("id") int id,
#FormParam("name") String name,
#FormParam("price") float price) {
Map<String, Object> data = new HashMap<>();
data.put("id", id);
/* put all data you want to store in this map */
formSynchronizer.storeForm(data, "FORM_" + new Date().getTime()); // I used current time prefixed with 'FORM_' string as file name
return Response.status(200)
.entity(" Product added successfuly!<br> Id: "+id+"<br> Name: " + name+"<br> Price: "+price)
.build();
}
}
Use jackson to Convert Map Object to JSON file and vice-versa.
map to / from json file