Is there any possibility to validate StandardMultipartHttpServletRequest using standard #Valid annotation and custom Validator?
I've implemented such validator, annotated method param in controller the validator is not invoked.
I've figured it out myself. To make it work you need a DTO:
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
#Getter
#Setter
public class NewOrderFilesDTO {
List<MultipartFile> files;
}
Then, a validator:
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import static org.springframework.util.CollectionUtils.isEmpty;
#Component
public class NewOrderFilesValidator implements Validator {
private static final String MIME_TYPE_PDF = "application/pdf";
private static final long ALLOWED_SIZE = 3 * 1024 * 1024;
#Override
public void validate(Object target, Errors errors) {
if (target == null) {
return;
}
NewOrderFilesDTO newOrderFilesDTO = (NewOrderFilesDTO) target;
List<MultipartFile> newOrderFiles = newOrderFilesDTO.getFiles();
if (isEmpty(newOrderFiles)) {
return;
}
for (MultipartFile file : newOrderFiles) {
if (!MIME_TYPE_PDF.equals(file.getContentType())) {
errors.rejectValue(file.getName(), file.getName(), "'application/pdf' files allowed only!");
}
if (file.getSize() > ALLOWED_SIZE) {
errors.rejectValue(file.getName(), file.getName(), "File size allowed up to 3MB!");
}
}
}
#Override
public boolean supports(Class<?> cls) {
return NewOrderFilesDTO.class.equals(cls);
}
}
And finally a controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.validation.Valid;
import static org.springframework.http.HttpStatus.NO_CONTENT;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
#Controller
class OrderController {
private final NewOrderFilesValidator newOrderFilesValidator;
#Autowired
OrderController(NewOrderFilesValidator newOrderFilesValidator) {
this.newOrderFilesValidator = newOrderFilesValidator;
}
#InitBinder("newOrderFiles")
void initOrderFilesBinder(WebDataBinder binder) {
binder.addValidators(newOrderFilesValidator);
}
#ResponseStatus(NO_CONTENT)
#RequestMapping(value = ORDERS_PATH, method = POST, consumes = MULTIPART_FORM_DATA_VALUE)
void createOrder(
#Valid #ModelAttribute NewOrderFilesDTO newOrderFiles
) {
}
}
With the configuration above the DTO will be validated automatically by spring.
Related
I'm learning Java and as part of it, trying to develop a Spring Boot API that communicates with MongoDB Atlas cluster. I'm trying to write an API that would return items based on the price range value where min and max values are provided dynamically. Please help me understand where am I doing a mistake by going through the code below. I strongly feel it has to do with #Query and #PathVariable, I feel #RequestParam should be used in place of #PathVariable, however, I'm not sure what to use in place of #Query in the repository.
Here is the code of the repository
package com.webshoppingbackend.springboot.repository;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import com.webshoppingbackend.springboot.model.WebShoppingItem;
public interface WebShoppingRepository extends MongoRepository<WebShoppingItem, String> {
#Query("{category:?0}")
List<WebShoppingItem> getItemsByCategory(String category);
#Query("{brand:?0}")
List<WebShoppingItem> getItemsByBrand(String brand);
#Query("{price:{$lt:?0,$gt:?1}}")
List<WebShoppingItem> getItemsBasedOnPrice(long higherPrice, long lowerPrice);
}
Here is the code of the controller
package com.webshoppingbackend.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.webshoppingbackend.springboot.model.WebShoppingItem;
import com.webshoppingbackend.springboot.services.WebShoppingService;
#RestController
#RequestMapping("/webshopping")
public class WebShoppingController {
#Autowired
private WebShoppingService service;
#GetMapping
public List<WebShoppingItem> getAllItems() {
return service.getWebShoppingItems();
}
#GetMapping("/{itemId}")
public WebShoppingItem getItem(#PathVariable String itemId) {
return service.getItemById(itemId);
}
#GetMapping("/category/{category}")
public List<WebShoppingItem> getItemsByCategory(#PathVariable String category) {
return service.getItemsByCategory(category);
}
#GetMapping("/brand/{brand}")
public List<WebShoppingItem> getItemsByBrand(#PathVariable String brand) {
return service.getItemsByBrand(brand);
}
#GetMapping("/{price}")
public List<WebShoppingItem> getItemsBasedOnPriceRange(#PathVariable long higherPrice,
#PathVariable long lowerPrice) {
return service.getItemsBasedOnPriceRange(higherPrice, lowerPrice);
}
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public WebShoppingItem addItem(#RequestBody WebShoppingItem webShoppingItem) {
return service.addToWebShoppingItems(webShoppingItem);
}
#PutMapping
public WebShoppingItem modifyItem(#RequestBody WebShoppingItem webShoppingItem) {
return service.updateWebShoppingItem(webShoppingItem);
}
#DeleteMapping("/{itemId}")
public String deleteItem(#PathVariable String itemId) {
return service.deleteWebShoppingItem(itemId);
}
}
Here is the code in the service provider
package com.webshoppingbackend.springboot.services;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.webshoppingbackend.springboot.model.WebShoppingItem;
import com.webshoppingbackend.springboot.repository.WebShoppingRepository;
#Service
public class WebShoppingService {
#Autowired
private WebShoppingRepository repository;
// CRUD
public WebShoppingItem addToWebShoppingItems(WebShoppingItem webShoppingItem) {
webShoppingItem.setItemId(UUID.randomUUID().toString().split("-")[0]);
return repository.save(webShoppingItem);
}
public List<WebShoppingItem> getWebShoppingItems() {
return repository.findAll();
}
public WebShoppingItem getItemById(String itemId) {
return repository.findById(itemId).get();
}
public List<WebShoppingItem> getItemsByCategory(String category) {
return repository.getItemsByCategory(category);
}
public List<WebShoppingItem> getItemsByBrand(String brand) {
return repository.getItemsByBrand(brand);
}
public List<WebShoppingItem> getItemsBasedOnPriceRange(long higherPrice, long lowerPrice) {
return repository.getItemsBasedOnPrice(higherPrice, lowerPrice);
}
public WebShoppingItem updateWebShoppingItem(WebShoppingItem webShoppingItem) {
WebShoppingItem itemToBeUpdated = repository.findById(webShoppingItem.getItemId()).get();
itemToBeUpdated.setCategory(webShoppingItem.getCategory());
itemToBeUpdated.setProductName(webShoppingItem.getProductName());
itemToBeUpdated.setImageSource(webShoppingItem.getImageSource());
itemToBeUpdated.setBrand(webShoppingItem.getBrand());
itemToBeUpdated.setPrice(webShoppingItem.getPrice());
itemToBeUpdated.setRating(webShoppingItem.getRating());
itemToBeUpdated.setShippingCharges(webShoppingItem.getShippingCharges());
itemToBeUpdated.setProductDetails(webShoppingItem.getProductDetails());
return repository.save(itemToBeUpdated);
}
public String deleteWebShoppingItem(String itemId) {
repository.deleteById(itemId);
return "Deleted Web Shopping Item";
}
}
Here is the request I'm sending through Talend API Tester to test my code.
How to retrieve data from ligneCommandeDto and pass it to lignebpdto to generate dynamically a lignebpService from ligneCommandeService if affercter() is true.
the affercter() method for checking if the isAffected attribute is true, if that I call the genererbp() methode , this methode create a ligneBp so I need to fill il with data from ligneCommandeDTO.
package org.backend.gcmd.service;
import org.backend.gcmd.dto.LigneBpDTO;
import org.backend.gcmd.dto.LigneCommandeDTO;
import org.backend.gcmd.entity.LigneCommandeEntity;
import org.backend.gcmd.exceptions.technical.ObjectNotFoundException;
import org.backend.gcmd.mapper.LigneCommandeMapper;
import org.backend.gcmd.repository.LigneCommandeRepository;
import org.backend.gcmd.validator.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Optional;
import static java.util.stream.Collectors.toList;
#Service
#Transactional
public class LigneCommandeService {
#Autowired
private LigneCommandeRepository ligneCommandeRepository;
#Autowired
private LigneCommandeMapper ligneCommandeMapper;
#Autowired
private LigneBpService ligneBpService;
private LigneBpDTO ligneBpDTO;
#Autowired
private LigneBpMapper ligneBpMapper;
public LigneCommandeDTO findById(Long id) {
Validate.notNull(id, "id mus be not null");
Optional<LigneCommandeEntity> entity = ligneCommandeRepository.findById(id);
if (entity.isPresent()) {
return ligneCommandeMapper.convertToDto(entity.get());
} else {
throw new ObjectNotFoundException("LigneCommandeDTO not found");
}
}
public LigneCommandeDTO save(LigneCommandeDTO dto) {
Validate.notNull(dto, "LigneCommandeDTO must be not null");
LigneCommandeEntity entity = ligneCommandeMapper.convertToEntity(dto);
LigneCommandeEntity saved = ligneCommandeRepository.save(entity);
return ligneCommandeMapper.convertToDto(saved);
}
public LigneCommandeDTO update(LigneCommandeDTO dto) {
Validate.notNull(dto, "LigneCommandeDTO must be not null");
Validate.notNull(dto.getId(), "LigneCommandeDTO id must be not null");
findById(dto.getId());
LigneCommandeEntity entity = ligneCommandeMapper.convertToEntity(dto);
LigneCommandeEntity saved = ligneCommandeRepository.save(entity);
return ligneCommandeMapper.convertToDto(saved);
}
public Page<LigneCommandeDTO> findAllByDeletedFalse(Pageable pageable) {
Page<LigneCommandeEntity> page = ligneCommandeRepository.findAllByDeletedFalse(pageable);
return ligneCommandeMapper.convertToPageDto(page);
}
public LigneCommandeDTO affecter(Long id, Boolean isAffected) {
Validate.notNull(id, "LigneCommandeDTO must be not null");
Validate.notNull(isAffected, "LigneCommandeDTO id must be not null");
LigneCommandeDTO lcdto = findById(id);
lcdto.setIsAffected(isAffected);
update(lcdto);
genererbp();
return null;
}
public LigneBpDTO genererbp(LigneCommandeDTO ligneCommandeDTO) {
if (ligneCommandeDTO.getIsAffected()) {
return ligneBpService.findAllByDeletedFalse((Pageable) ligneBpDTO)
.stream()
.map(ligneBpMapper::convertToDto)
.collect(toList());
}
return null;
}
}
the mapper class
package org.backend.gcmd.mapper;
import org.springframework.data.domain.Page;
import java.util.List;
public interface Mapper<D, E> {
Page<D> convertToPageDto(Page<E> page);
D convertToDto(E entity);
E convertToEntity(D dto);
List<D> convertToDtoList(List<E> entities);
List<E> convertToEntitiesList(List<D> entities);
}
package org.backend.gcmd.mapper;
import org.backend.gcmd.dto.LigneBpDTO;
import org.backend.gcmd.entity.LigneBpEntity;
import org.backend.gcmd.repository.BulltinPrestationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
#Component
public class LigneBpMapper implements Mapper<LigneBpDTO, LigneBpEntity> {
#Autowired
BulltinPrestationRepository bulltinprestationRepository;
#Override
public Page<LigneBpDTO> convertToPageDto(Page<LigneBpEntity> page) {
return page.map(this::convertToDto);
}
#Override
public LigneBpDTO convertToDto(LigneBpEntity entity) {
LigneBpDTO dto = new LigneBpDTO();
dto.setId(entity.getId());
dto.setDate(entity.getDate());
dto.setHeure(entity.getHeure());
dto.setNombre(entity.getNombre());
dto.setPrestation(entity.getPrestation());
dto.setProduit(entity.getProduit());
dto.setSensTrafic(entity.getSensTrafic());
dto.setTarifUnifie(entity.getTarifUnifie());
dto.setTcConv(entity.getTcConv());
dto.setTcSuppl(entity.getTcSuppl());
dto.setTonnageMinimum(entity.getTonnageMinimum());
dto.setTonnageReel(entity.getTonnageReel());
return dto;
}
#Override
public LigneBpEntity convertToEntity(LigneBpDTO dto) {
LigneBpEntity entity = new LigneBpEntity();
entity.setId(dto.getId());
entity.setDate(dto.getDate());
entity.setHeure(dto.getHeure());
entity.setNombre(dto.getNombre());
entity.setPrestation(dto.getPrestation());
entity.setProduit(dto.getProduit());
entity.setSensTrafic(dto.getSensTrafic());
entity.setTarifUnifie(dto.getTarifUnifie());
entity.setTcConv(dto.getTcConv());
entity.setTcSuppl(dto.getTcSuppl());
entity.setTonnageMinimum(dto.getTonnageMinimum());
entity.setTonnageReel(dto.getTonnageReel());
return entity;
}
#Override
public List<LigneBpDTO> convertToDtoList(List<LigneBpEntity> entities) {
return entities.stream().map(this::convertToDto).collect(Collectors.toCollection(ArrayList::new));
}
#Override
public List<LigneBpEntity> convertToEntitiesList(List<LigneBpDTO> dtos) {
return dtos.stream().map(this::convertToEntity).collect(Collectors.toCollection(ArrayList::new));
}
}
controller
package org.backend.gcmd.controller;
import org.backend.gcmd.dto.LigneBpDTO;
import org.backend.gcmd.dto.LigneCommandeDTO;
import org.backend.gcmd.service.LigneBpService;
import org.backend.gcmd.service.LigneCommandeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
#RestController
#RequestMapping("/api/gcmd/v1/ligneCommandes")
public class LigneCommandeController {
#Autowired
private LigneCommandeService ligneCommandeService;
#GetMapping("{id}")
public ResponseEntity<LigneCommandeDTO> findById(#PathVariable Long id) {
LigneCommandeDTO ligneCommandeDTO = ligneCommandeService.findById(id);
return ResponseEntity.status(HttpStatus.OK).body(ligneCommandeDTO);
}
#PostMapping
public ResponseEntity<LigneCommandeDTO> save(#RequestBody LigneCommandeDTO ligneCommandeDTO) {
return ResponseEntity.status(HttpStatus.CREATED).body(ligneCommandeService.save(ligneCommandeDTO));
}
#PutMapping("{id}")
public ResponseEntity<LigneCommandeDTO> update(#PathVariable Long id,
#RequestBody LigneCommandeDTO ligneCommandeDTO) {
ligneCommandeDTO.setId(id);
return ResponseEntity.status(HttpStatus.ACCEPTED).body(ligneCommandeService.update(ligneCommandeDTO));
}
#GetMapping
public ResponseEntity<Page<LigneCommandeDTO>> findAllByDeletedFalse(Pageable pageable) {
return ResponseEntity.status(HttpStatus.OK).body(ligneCommandeService.findAllByDeletedFalse(pageable));
}
}
I have created a crud application Using spring boot initializer.
Dependencies:
Lombok
Spring Web
Spring Mongo
This app calls from a database/cluster that I have set up on atlas. but I want it to call the correct collection and just do a simple get all api call in postman
but I get a server 500 error
Service Java file:
package com.fullstack.app.Service;
import com.fullstack.app.exception.EntityNotFoundException;
import com.fullstack.app.Model.*;
import com.fullstack.app.Model.Request.WCCreationRequest;
import com.fullstack.app.Repository.StatusData_WCRepo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
#Service
#RequiredArgsConstructor
public class StatusDataService {
private static StatusData_WCRepo wcRepository;
public StatusData createData (WCCreationRequest request) {
StatusData statusData = new StatusData();
BeanUtils.copyProperties(request, statusData);
return wcRepository.save(statusData);
}
public static List<StatusData> getAllData() {
return wcRepository.findAll();
}
}
request:
package com.fullstack.app.Model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
#Document(collection = "StatusData_WC")
public class StatusData {
#Id
private String ID_Number;
private String Surname;
private String Full_Names;
private String Address;
private String VR;
private Integer Ward;
private Integer VD_Number;
}
Controller:
package com.fullstack.app.Controller;
import com.fullstack.app.Model.StatusData;
import com.fullstack.app.Model.Request.WCCreationRequest;
import com.fullstack.app.Service.StatusDataService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import lombok.RequiredArgsConstructor;
#RestController
#RequestMapping(value = "/api/statusData")
#RequiredArgsConstructor
public class StatusDataController {
private final StatusDataService sdService;
#GetMapping("/statusdata")
public ResponseEntity getAllData(#RequestParam(required = false) String id) {
if (id == null) {
return ResponseEntity.ok(StatusDataService.getAllData());
}
return ResponseEntity.ok(StatusDataService.getAllData());
}
}
Application properties:
spring.data.mongodb.uri=mongodb+srv://*****:******#cluster0.wlmmf.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
im using UUID in my application as Primary Key i have problem whene find data by id give me exception error.
this is Note Class
package com.example.demo.model;
import java.util.Date;
import java.util.UUID;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
#AutoConfigurationPackage
#Entity
public class Note {
#Id
#GeneratedValue( strategy = GenerationType.AUTO,generator = "pg-uuid")
#GenericGenerator(name = "pg-uuid",strategy = "uuid2")
private UUID id;
private String title;
private String text;
#ManyToOne(fetch = FetchType.LAZY,cascade = CascadeType.MERGE)
private Notebook notebook;
private Date lastModifiedOn;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Notebook getNotebook() {
return notebook;
}
public void setNotebook(Notebook notebook) {
this.notebook = notebook;
}
public Date getLastModifiedOn() {
return lastModifiedOn;
}
public void setLastModifiedOn(Date lastModifiedOn) {
this.lastModifiedOn = lastModifiedOn;
}
this is NoteController
package com.example.demo.controller;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.MyMapper;
import com.example.demo.Repository.NoteBookRepository;
import com.example.demo.Repository.NoteRepository;
import com.example.demo.model.Note;
import com.example.demo.model.Notebook;
import com.example.demo.view.NoteViewModle;
#RestController
#RequestMapping("/api/note")
#CrossOrigin
public class NoteController {
#Autowired
NoteRepository noteRepository;
#Autowired
NoteBookRepository notebookRepository;
#Autowired
MyMapper maper;
#GetMapping("/all")
public List<NoteViewModle> getAllNote(){
List<Note> list = this.noteRepository.findAll();
List<NoteViewModle> noteViewModles = (List<NoteViewModle>) list.stream().map(note ->maper.convertToNodeViewModel(note)).collect(Collectors.toList());
return noteViewModles;
}
#GetMapping("/byId/{id}")
public NoteViewModle getNotreById(#PathVariable("id") UUID id) {
System.out.println(id);
Note note = this.noteRepository.findById(id).orElse(null);
if(note == null)
{
System.out.println("In If");
throw new EntityNotFoundException();
}
NoteViewModle modle = maper.convertToNodeViewModel(note);
return modle;
}
#GetMapping("/byNoteBook/{notebookId}")
public List<Note> getNotesByNoteBook(#PathVariable("notebookId") String id)
{
return this.noteRepository.findAllByNotebook(this.notebookRepository.findById(UUID.fromString(id)).orElse(new Notebook()));
}
#PostMapping("/add")
public Note save(#RequestBody NoteViewModle modle)
{
Note note = maper.convertToNodeEntity(modle);
return this.noteRepository.save(note);
}
#DeleteMapping("/deltebyId/{id}")
public void deleteNoteById(#PathVariable("id") String id) {
this.noteRepository.deleteById(UUID.fromString(id));
}
}
this is MyMapper to mape the json data
package com.example.demo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.example.demo.Repository.NoteBookRepository;
import com.example.demo.model.Note;
import com.example.demo.model.Notebook;
import com.example.demo.view.NoteViewModle;
import com.example.demo.view.NotebookViewModel;
#Component
public class MyMapper {
#Autowired
NoteBookRepository bookRepository;
public NoteViewModle convertToNodeViewModel(Note entity) {
NoteViewModle modle = new NoteViewModle();
modle.setId(entity.getId().toString());
modle.setTitle(entity.getTitle());
modle.setText(entity.getText());
modle.setNoteBookId(entity.getNotebook().getId().toString());
modle.setData(entity.getLastModifiedOn().toString());
return modle;
}
public Note convertToNodeEntity(NoteViewModle viewModle) {
Note note = new Note();
note.setTitle(viewModle.getTitle());
note.setText(viewModle.getText());
//note.setLastModifiedOn(new SimpleDateFormat("dd/MM/yyyy").parse(viewModle.getData()));
//Notebook notebook = bookRepository.findById(UUID.fromString(viewModle.getId())).orElse(new Notebook());
return note;
}
public NotebookViewModel convertToNotebookViewModel(Notebook entity)
{
NotebookViewModel viewModel = new NotebookViewModel();
viewModel.setId(entity.getId().toString());
viewModel.setName(entity.getName());
viewModel.setNumOfNote(entity.getNotes().size());
return viewModel;
}
public Notebook convertToNotebookEntity(NotebookViewModel model) {
Notebook notebook = new Notebook();
notebook.setId(UUID.fromString(model.getId()));
notebook.setName(model.getName());
return notebook;
}
}
this is repositry class
package com.example.demo.Repository;
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Note;
import com.example.demo.model.Notebook;
#Repository
public interface NoteRepository extends JpaRepository<Note, UUID> {
List<Note> findAllByNotebook(Notebook notebook);
}
this is error is appears org.springframework.dao.EmptyResultDataAccessException: No class com.example.demo.model.Notebook entity with id 7e83b195-eb81-4752-a6fa-a5206c9eb1c6 exists!
i have a Backend based on Spring Boot, the frontend based on Angular 5.
after recieving the MultiPartFile via Angular i want to rename this file with
unique name(id of the table) and store the file into folder then put the URL of this file to DataBase PostgreSQL.
please help me, i tested a lot of methods without any good result.
i tryed to convert the MultiPartFile to File, but i don't know how to do.
please help me
Here is the Class that contain the methods of handling MultiPartFile :
package smart.syndic.metier;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;
#Service
public class StorageService
{
Logger logger = LoggerFactory.getLogger(this.getClass().getName());
private final Path rootLocation = Paths.get("fichiers/prestataires");
public void store(MultipartFile file) {
try {
Files.copy(file.getInputStream(),
this.rootLocation.resolve(file.getOriginalFilename()),
StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
}
public Resource loadFile(String filename) {
try {
Path file = rootLocation.resolve(filename);
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
} else {
throw new RuntimeException("FAIL!");
}
} catch (MalformedURLException e) {
throw new RuntimeException("FAIL!");
}
}
public void deleteAll() {
FileSystemUtils.deleteRecursively(rootLocation.toFile());
}
}
Here is the RestController :
package smart.syndic.web;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.
MvcUriComponentsBuilder;
import smart.syndic.dao.PrestatairesRepository;
import smart.syndic.dao.PrestatairesTypesRepository;
import smart.syndic.entities.Prestataires;
import smart.syndic.metier.StorageService;
#RestController
#CrossOrigin("*")
public class PrestatairesRestController
{
#Autowired
private PrestatairesRepository repository;
#Autowired
private PrestatairesTypesRepository repository2;
#Autowired
private StorageService storageService;
private List<String> files = new ArrayList<String>();
#RequestMapping(value="/prestataires/{id}",
method=RequestMethod.GET)
public Prestataires getVilles(#PathVariable Long id)
{
return repository.findOne(id);
}
#RequestMapping(value="/prestataires",
method=RequestMethod.POST)
public Prestataires addVilles(Prestataires p,
#RequestParam("multipartFile") MultipartFile file)
{
try{
storageService.store(file);
files.add(file.getOriginalFilename());
p.setPhoto("fichiers/prestataires/"+file.getOriginalFilename());
}catch(Exception e){
e.printStackTrace();
}
p.setPrestatairesTypes(repository2.findOne(p.getPrestatairesTypes()
.getId()));
return repository.save(p);
}
}
Here is the Entity Prestataires :
package smart.syndic.entities;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
#Entity
public class Prestataires implements Serializable
{
#Id #GeneratedValue
private Long id;
private String nom;
private String email;
private String tele;
private String fax;
private String rib;
private String adresse;
private String taches;
private String photo;
//-------------------Constructors--------------------
//-------------------Getters and Setters--------------------
#ManyToOne
#JoinColumn(name="ID_PRESTATAIRES_TYPES")
private PrestatairesTypes prestatairesTypes;
}
If filename is only the issue, your code is fine all you need to is create filename using some string or just clean it like below
//Create custom filename
String filename = StringUtils.cleanPath(file.getOriginalFilename());
//remove spaces and make lowercase
filename = filename.toLowerCase().replaceAll(" ", "-");
or
String filename = p.getId()+"."+file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
And then in your copy method
Files.copy(file.getInputStream(), this.rootLocation.resolve(filename),
StandardCopyOption.REPLACE_EXISTING);
Here is example
#Service
public class UploadService {
#Value("${app.image.cdn}")
private String imageCDN;
#Value("${app.upload.path}")
private String uploadPath;
private Path rootLocation;
public String store(MultipartFile file) {
String storedLocation;
rootLocation = Paths.get(uploadPath);
String filename = StringUtils.cleanPath(file.getOriginalFilename());
filename = filename.toLowerCase().replaceAll(" ", "-");
try {
if (file.isEmpty()) {
throw new StorageException("Failed to store empty file " + filename);
}
if (filename.contains("..")) {
// This is a security check
throw new StorageException(
"Cannot store file with relative path outside current directory "
+ filename);
}
Files.copy(file.getInputStream(), this.rootLocation.resolve(filename),
StandardCopyOption.REPLACE_EXISTING);
storedLocation = imageCDN+filename;
}
catch (IOException e) {
throw new StorageException("Failed to store file " + filename, e);
}
return storedLocation;
}
}
And your application.properties
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=20MB
app.upload.path=/uploads
app.image.cdn=http://yourhost.com/uploads/
And your StorageException class
public class StorageException extends RuntimeException {
public StorageException(String message) {
super(message);
}
public StorageException(String message, Throwable cause) {
super(message, cause);
}
}
Here is the RestController
package smart.syndic.web;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import smart.syndic.dao.PrestatairesRepository;
import smart.syndic.dao.PrestatairesTypesRepository;
import smart.syndic.entities.Prestataires;
import smart.syndic.metier.StorageService;
#RestController
#CrossOrigin("*")
public class PrestatairesRestController
{
#Autowired
private PrestatairesRepository repository;
#Autowired
private PrestatairesTypesRepository repository2;
#Autowired
private StorageService storageService;
private List<String> files = new ArrayList<String>();
#RequestMapping(value="/prestataires/{id}",
method=RequestMethod.GET)
public Prestataires getVilles(#PathVariable Long id)
{
return repository.findOne(id);
}
#RequestMapping(value="/prestataires",
method=RequestMethod.POST)
public Prestataires addVilles(Prestataires p,
#RequestParam("multipartFile") MultipartFile file)
{
Prestataires pp = null;
try{
pp = repository.save(p);
storageService.store(file, "prestataires",pp);
files.add(file.getOriginalFilename());
}catch(Exception e){
e.printStackTrace();
}
p.setPrestatairesTypes(repository2.findOne(p.getPrestatairesTypes().getId()));
updateVilles(p.getId(), p);
return pp;
}
#RequestMapping(value="/prestataires/{id}",
method=RequestMethod.PUT)
public Prestataires updateVilles(
#PathVariable Long id,
#RequestBody Prestataires v)
{
v.setId(id);
return repository.save(v);
}
}
The StorageService
package smart.syndic.metier;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;
import smart.syndic.entities.Prestataires;
#Service
public class StorageService
{
private String imageCDN = "http://www.yourHost.com/fichiers/";
private Path rootLocation;
public String store(MultipartFile file, String chemin, Prestataires p) {
String storedLocation = null;
rootLocation = Paths.get("fichiers/"+chemin+"/");
String filename = null;
filename = p.getId()+"."+file.getOriginalFilename()
.substring(
file.getOriginalFilename().lastIndexOf(".") + 1);
try {
if(file.isEmpty()){
throw new StorageException("Failed to store Empty"
+ " File "+filename);
}
if(filename.contains(".."))
{
throw new StorageException("Cannot store file with relative path "
+ "outside current directory "+filename);
}
Files.copy(file.getInputStream(), this.rootLocation.resolve(filename),
StandardCopyOption.REPLACE_EXISTING);
storedLocation = imageCDN + filename;
} catch (IOException e) {
throw new StorageException("Failed to store file " + filename, e);
}
p.setPhoto("fichiers/"+chemin+"/"+filename);
return storedLocation;
}
public Resource loadFile(String filename) {
try {
Path file = rootLocation.resolve(filename);
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
} else {
throw new RuntimeException("FAIL!");
}
} catch (MalformedURLException e) {
throw new RuntimeException("FAIL!");
}
}
public void deleteAll() {
FileSystemUtils.deleteRecursively(rootLocation.toFile());
}
}
The other Classes didn't have a change including the frontEnd