I'm developing a crud API with a post method, when testing this method in my postman it returns the error
2023-02-15T13:34:35.528-03:00 WARN 8792 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<java.lang.Object> com.api.order_control.controllers.OrderController.saveOrder(com.api.order_control.dtos.OrderDto) with 2 errors: [Field error in object 'orderDto' on field 'doorNumber': rejected value [null]; codes [NotBlank.orderDto.doorNumber,NotBlank.doorNumber,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [orderDto.doorNumber,doorNumber]; arguments []; default message [doorNumber]]; default message [must not be blank]] [Field error in object 'orderDto' on field 'block': rejected value [null]; codes [NotBlank.orderDto.block,NotBlank.block,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [orderDto.block,block]; arguments []; default message [block]]; default message [must not be blank]] ]
I couldn't understand why my blank cannot work with this method and why this error. can anybody help me?
model
package com.api.order_control.models;
import jakarta.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.UUID;
#Entity
#Table(name = "restaurant_orders")
public class OrderModel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#Column(nullable = false, length = 11)
private String customerName;
#Column(nullable = false, length = 15)
private String phoneNumber;
#Column(nullable = false, length = 25)
private String address;
#Column(nullable = false, length = 10)
private String doorNumber;
#Column(length = 5)
private String block;
#Column(nullable = false, length = 30)
private String orderNote;
#Column(nullable = false)
private Float price;
#Column(nullable = false)
private LocalDateTime registrationDate;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDoorNumber() {
return doorNumber;
}
public void setDoorNumber(String doorNumber) {
this.doorNumber = doorNumber;
}
public String getBlock() {
return block;
}
public void setBlock(String block) {
this.block = block;
}
public String getOrderNote() {
return orderNote;
}
public void setOrderNote(String order) {
this.orderNote = orderNote;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public LocalDateTime getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(LocalDateTime registrationDate) {
this.registrationDate = registrationDate;
}
}
dto pack
package com.api.order_control.dtos;
import jakarta.validation.constraints.NotBlank;
public class OrderDto {
#NotBlank
private String customerName;
#NotBlank
private String phoneNumber;
#NotBlank
private String address;
#NotBlank
private String doorNumber;
#NotBlank
private String block;
#NotBlank
private String orderNote;
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String doorNumber() {
return doorNumber;
}
public void doorNumber(String doorName) {
this.doorNumber = doorName;
}
public String getBlock() {
return block;
}
public void setBlock(String block) {
this.block = block;
}
public String getOrderNote() {
return orderNote;
}
public void setOrderNote(String orderNote) {
this.orderNote = orderNote;
}
}
controller with post
package com.api.order_control.controllers;
import com.api.order_control.dtos.OrderDto;
import com.api.order_control.models.OrderModel;
import com.api.order_control.services.OrderService;
import jakarta.validation.Valid;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping("/orders")
public class OrderController {
final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
#PostMapping
public ResponseEntity<Object> saveOrder(#RequestBody #Valid OrderDto orderDto) {
var orderModel = new OrderModel();
BeanUtils.copyProperties(orderDto, orderModel);
orderModel.setRegistrationDate(LocalDateTime.now(ZoneId.of("UTC")));
orderModel.setPrice(70.8f);
return ResponseEntity.status(HttpStatus.CREATED).body(orderService.save(orderModel));
}
}
I had already had a blank error because I was using a float, but in this case "numberDoor" is just a string. What is the reason for this error?
Postman request
{
"customerName": "Ryan",
"phoneNumber": "1 99859 5854",
"address": "St Street Vl 190",
"doorNumber": "5",
"orderNote": "Pepperoni Pizza"
}
It's a validation error.
You don't pass block in your post method, but in DTO this field annotated with #NotBlack
You didn't provide eligible setter for doorNumber. As a result, this field is null in your DTO object, but again, is annotated with #NotBlack. The setter name must be setDoorNumber(String value) for that field
Related
My problem: when I do an #Post in Postman I get data back from the prices, but not kitten data.
I enter the following:
{
"name": "Frizzle",
"dateOfBirth": "2019-07-27",
"weight": 7.1,
"breed": "Birman",
"firstVaccination": "yes",
"secondVaccination": "yes",
"breedPrice": 8000,
"firstVaccinationPrice": 80.50,
"secondVaccinationPrice": 80.10
}
And this is what I get back in Postman:
{
"id": 3,
"name": null,
"dateOfBirth": null,
"weight": 0.0,
"breed": null,
"firstVaccination": null,
"secondVaccination": null,
"fileUpload": null,
"price": {
"id": 3,
"broadPrice": 8000.0,
"firstVaccinationPrice": 80.5,
"secondVaccinationPrice": 80.1,
"totalPrice": 8160.6
}
}
I've tried changing the code in several places, but I can't figure out why it outputs the price part and not the kitten data part. I want it to output the kitten data. So basically what I want is for him to reverse it, return data of the kittens and give data of the prices that are null.
My files look like this.
Kitten.java
import com.sun.istack.NotNull;
import javax.persistence.*;
import java.time.LocalDate;
#Entity
#Table(name = "kittens")
public class Kitten {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotNull
private String name;
#NotNull
#Column(name = "date_of_birth")
private LocalDate dateOfBirth;
#NotNull
#Column
private double weight;
#NotNull
#Column(name = "breed")
private String breed;
#Column(name = "first_vaccination")
private String firstVaccination;
#Column(name = "second_vaccination")
private String secondVaccination;
#OneToOne(mappedBy = "kitten")
private FileUpload fileUpload;
#OneToOne(fetch = FetchType.LAZY,
mappedBy = "kitten")
private Price price;
public Kitten(String name, LocalDate dateOfBirth, double weight, String breed, String firstVaccination, String secondVaccination) {
}
public Kitten() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getFirstVaccination() {
return firstVaccination;
}
public void setFirstVaccination(String firstVaccination) {
this.firstVaccination = firstVaccination;
}
public String getSecondVaccination() {
return secondVaccination;
}
public void setSecondVaccination(String secondVaccination) {
this.secondVaccination = secondVaccination;
}
public FileUpload getFileUpload() {
return fileUpload;
}
public void setFileUpload(FileUpload fileUpload) {
this.fileUpload = fileUpload;
}
public Price getPrice() {
return price;
}
public void setPrice(Price price) {
this.price = price;
}
}
Price.java
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sun.istack.NotNull;
import javax.persistence.*;
#Entity
#Table(name = "prices")
public class Price {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#NotNull
#Column(name = "breed_price")
private double breedPrice;
#Column(name = "first_vaccination_price")
private double firstVaccinationPrice;
#Column(name = "second_vaccination_price")
private double secondVaccinationPrice;
#JsonIgnore
#OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
orphanRemoval = true)
#JoinColumn(name = "kitten_id")
private Kitten kitten;
public Price() {
}
public Price(double breedPrice, double firstVaccinationPrice, double secondVaccinationPrice) {
this.breedPrice = breedPrice;
this.firstVaccinationPrice = firstVaccinationPrice;
this.secondVaccinationPrice = secondVaccinationPrice;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getBreedPrice() {
return breedPrice;
}
public void setBreedPrice(double breedPrice) {
this.breedPrice = breedPrice;
}
public double getFirstVaccinationPrice() {
return firstVaccinationPrice;
}
public void setFirstVaccinationPrice(double firstVaccinationPrice) {
this.firstVaccinationPrice = firstVaccinationPrice;
}
public double getSecondVaccinationPrice() {
return secondVaccinationPrice;
}
public void setSecondVaccinationPrice(double secondVaccinationPrice) {
this.secondVaccinationPrice = secondVaccinationPrice;
}
public Kitten getKitten() {
return kitten;
}
public void setKitten(Kitten kitten) {
this.kitten = kitten;
}
public Double getTotalPrice() {
return this.getBreedPrice() + this.getFirstVaccinationPrice() + this.getSecondVaccinationPrice();
}
}
KittenBuilder.java
import nl.danielle.cattery.payload.KittenRequest;
import java.time.LocalDate;
public class KittenBuilder {
//Kitten
private String name;
private LocalDate dateOfBirth;
private double weight;
private String breed;
private String firstVaccination;
private String secondVaccination;
//Price
private double breedPrice;
private double firstVaccinationPrice;
private double secondVaccinationPrice;
public KittenBuilder(KittenRequest kittenRequest) {
this.name = kittenRequest.getName();
this.dateOfBirth = kittenRequest.getDateOfBirth();
this.weight = kittenRequest.getWeight();
this.breed = kittenRequest.getBreed();
this.firstVaccination = kittenRequest.getFirstVaccination();
this.secondVaccination = kittenRequest.getSecondVaccination();
this.breedPrice = kittenRequest.getBreedPrice();
this.firstVaccinationPrice = kittenRequest.getFirstVaccinationPrice();
this.secondVaccinationPrice = kittenRequest.getSecondVaccinationPrice();
}
public Kitten buildKitten() {
return new Kitten(name, dateOfBirth, weight, breed, firstVaccination, secondVaccination);
}
public Price buildPrice() {
return new Price(breedPrice, firstVaccinationPrice, secondVaccinationPrice);
}
}
KittenRequest.java
import com.sun.istack.NotNull;
import java.time.LocalDate;
public class KittenRequest {
//Kitten
#NotNull
private String name;
#NotNull
private LocalDate dateOfBirth;
#NotNull
private double weight;
#NotNull
private String breed;
private String firstVaccination;
private String secondVaccination;
//Price
#NotNull
private double breedPrice;
private double firstVaccinationPrice;
private double secondVaccinationPrice;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getFirstVaccination() {
return firstVaccination;
}
public void setFirstVaccination(String firstVaccination) {
this.firstVaccination = firstVaccination;
}
public String getSecondVaccination() {
return secondVaccination;
}
public void setSecondVaccination(String secondVaccination) {
this.secondVaccination = secondVaccination;
}
public double getBreedPrice() {
return breedPrice;
}
public void setBreedPrice(double breedPrice) {
this.breedPrice = breedPrice;
}
public double getFirstVaccinationPrice() {
return firstVaccinationPrice;
}
public void setFirstVaccinationPrice(double firstVaccinationPrice) {
this.firstVaccinationPrice = firstVaccinationPrice;
}
public double getSecondVaccinationPrice() {
return secondVaccinationPrice;
}
public void setSecondVaccinationPrice(double secondVaccinationPrice) {
this.secondVaccinationPrice = secondVaccinationPrice;
}
}
KittenController.java
import nl.danielle.cattery.model.FileUpload;
import nl.danielle.cattery.payload.KittenRequest;
import nl.danielle.cattery.payload.ResponseMessage;
import nl.danielle.cattery.service.FileStorageServiceImpl;
import nl.danielle.cattery.service.KittenService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.net.URI;
#RestController
#RequestMapping(value = "/kittens")
public class KittenController {
final KittenService kittenService;
final FileStorageServiceImpl storageService;
public KittenController(KittenService kittenService, FileStorageServiceImpl storageService) {
this.kittenService = kittenService;
this.storageService = storageService;
}
#GetMapping(value = "")
public ResponseEntity<Object> getKittens() {
return ResponseEntity.ok().body(kittenService.getKittens());
}
#GetMapping(value = "/{id}")
public ResponseEntity<Object> getKitten(#PathVariable("id") long id) {
return ResponseEntity.ok().body(kittenService.getKittenById(id));
}
#PostMapping(value = "/add")
public ResponseEntity<Object> saveKitten(#RequestBody KittenRequest kitten) {
long newId = kittenService.saveKitten(kitten);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(newId).toUri();
return ResponseEntity.created(location).build();
}
#PutMapping(value = "/{id}")
public ResponseEntity<Object> updateKitten(#PathVariable("id") long id, #RequestBody KittenRequest kitten) {
kittenService.updateKitten(id, kitten);
return ResponseEntity.noContent().build();
}
#PutMapping(value = "/{id}/price")
public ResponseEntity<Object> updatePrice(#PathVariable("id") long id, #RequestBody KittenRequest price) {
kittenService.updatePrice(id, price);
return ResponseEntity.noContent().build();
}
#DeleteMapping(value = "/{id}")
public ResponseEntity<Object> deleteKitten(#PathVariable("id") long id) {
kittenService.deleteKitten(id);
return ResponseEntity.noContent().build();
}
#PostMapping("/upload/kittenid/{id}")
public ResponseEntity<ResponseMessage> uploadFile(#PathVariable long id, #RequestParam("file") MultipartFile file) {
try {
storageService.store(file, id);
String message = "Uploaded the file successfully: " + file.getOriginalFilename();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
} catch (Exception e) {
String message = "Could not upload the file: " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
}
}
#GetMapping("/download/{id}")
public ResponseEntity<byte[]> getFileById(#PathVariable("id") String id) {
FileUpload fileUpload = storageService.getFileById(id);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileUpload.getName() + "\"")
.body(fileUpload.getData());
}
}
KittenService.java
package nl.danielle.cattery.service;
import nl.danielle.cattery.exceptions.DatabaseErrorException;
import nl.danielle.cattery.exceptions.RecordNotFoundException;
import nl.danielle.cattery.model.Kitten;
import nl.danielle.cattery.model.KittenBuilder;
import nl.danielle.cattery.model.Price;
import nl.danielle.cattery.payload.KittenRequest;
import nl.danielle.cattery.repository.KittenRepository;
import nl.danielle.cattery.repository.PriceRepository;
import org.springframework.stereotype.Service;
import java.util.Collection;
#Service
public class KittenServiceImpl implements KittenService {
final KittenRepository kittenRepository;
final PriceRepository priceRepository;
public KittenServiceImpl(KittenRepository kittenRepository, PriceRepository priceRepository) {
this.kittenRepository = kittenRepository;
this.priceRepository = priceRepository;
}
#Override
public Collection<Kitten> getKittens() {
return kittenRepository.findAll();
}
#Override
public Kitten getKittenById(long id) {
if (!kittenRepository.existsById(id)) {
throw new RecordNotFoundException();
}
return kittenRepository.findById(id).orElse(null);
}
#Override
public long saveKitten(KittenRequest kittenRequest) {
Kitten newKitten = new KittenBuilder(kittenRequest).buildKitten();
Price newPrice = new KittenBuilder(kittenRequest).buildPrice();
Price savedPrice = priceRepository.save(newPrice);
newKitten.setPrice(savedPrice);
newPrice.setKitten(newKitten);
return kittenRepository.save(newKitten).getId();
}
#Override
public void updateKitten(long id, KittenRequest kitten) {
if (kittenRepository.existsById(id)) {
try {
Kitten existingKitten = kittenRepository.findById(id).orElse(null);
existingKitten.setName(kitten.getName());
existingKitten.setDateOfBirth(kitten.getDateOfBirth());
existingKitten.setWeight(kitten.getWeight());
existingKitten.setBreed(kitten.getBreed());
existingKitten.setFirstVaccination(kitten.getFirstVaccination());
existingKitten.setSecondVaccination(kitten.getSecondVaccination());
kittenRepository.save(existingKitten);
} catch (Exception ex) {
throw new DatabaseErrorException();
}
} else {
throw new RecordNotFoundException();
}
}
#Override
public void updatePrice(long id, KittenRequest price) {
if (priceRepository.existsById(id)) {
try {
Price existingPrice = priceRepository.findById(id).orElse(null);
existingPrice.setBreedPrice(price.getBreedPrice());
existingPrice.setFirstVaccinationPrice(price.getFirstVaccinationPrice());
existingPrice.setSecondVaccinationPrice(price.getSecondVaccinationPrice());
priceRepository.save(existingPrice);
} catch (Exception ex) {
throw new DatabaseErrorException();
}
} else {
throw new RecordNotFoundException();
}
}
#Override
public void deleteKitten(long id) {
kittenRepository.deleteById(id);
}
}
I have a lot to say about your code here, but let's see what's the main problem here. The problem is simple if you look at your KittenBuilder you create a Kitten using this builder but your Kitten constructor is empty.
public Kitten(String name, LocalDate dateOfBirth, double weight, String breed, String firstVaccination, String secondVaccination) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.weight = weight;
this.breed = breed;
this.firstVaccination = firstVaccination;
this.secondVaccination = secondVaccination;
}
This will populate the Kitten object and you're ready to go.
Some advices about your code
If you wonder why it's saving the null values when you specified the null constraints is that recent version of spring boot don't include the validation starter in the web starter, you have to include it yourself.
In you pom.xml add the following dependecy:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
And you have to include the annotation #Transactional to your services to make your operations atomic, for example in your create kitten method you want to persist the price and the kitten atomically.
#Service
#Transactional
class KittenServiceImpl implementes ...
And one the best practices also, is to not use your entites directly in your controllers, use DTO (Data Transfer Object), so you map the properties you want from your entity to your DTO (this way you can include only your kitten properties and leave the price entity).
And last bonus:
public Kitten getKittenById(long id) {
if (!kittenRepository.existsById(id)) {
throw new RecordNotFoundException("");
}
return kittenRepository.findById(id).orElse(null);
}
This can be simplified to:
public Kitten getKittenById(long id) {
return kittenRepository.findById(id).orElseThrow(() -> new RecordNotFoundException());
}
I wrote a custom validation in spring boot. The custom validation is meant to check if two fields match. Everything works fine until i try to submit the form. Boom i experience the error:
javax.validation.ConstraintViolationException: Validation failed for classes [com.joker.SampleAuthenticationWebApp.model.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Passwords do not match!', propertyPath=con_password, rootBeanClass=class com.joker.SampleAuthenticationWebApp.model.User, messageTemplate='Passwords do not match!'}
]
This problem has really hindered my learning progress. Your help would be very much appreciated.
PS: I've Scraped SO in search of a solution but all was to no avail.The Annotation:
package com.joker.SampleAuthenticationWebApp.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
#Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = FieldsValueMatchValidator.class)
public #interface FieldsValueMatch {
String message() default "Fields values don't match!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String field();
String fieldMatch();
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#interface List {
FieldsValueMatch[] value();
}
}
The Validator:
package com.joker.SampleAuthenticationWebApp.validator;
import com.joker.SampleAuthenticationWebApp.model.User;
import org.springframework.beans.BeanWrapperImpl;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch, Object> {
private String field;
private String fieldMatch;
#Override
public void initialize(FieldsValueMatch constraintAnnotation) {
this.field = constraintAnnotation.field();
this.fieldMatch = constraintAnnotation.fieldMatch();
}
#Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
try {
final Object fieldValue = new BeanWrapperImpl(value).getPropertyValue(field);
final Object fieldMatchValue = new BeanWrapperImpl(value).getPropertyValue(fieldMatch);
boolean isValid = fieldValue == null && fieldMatchValue == null || fieldValue != null && fieldValue.equals(fieldMatchValue);
if (!isValid) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addPropertyNode(fieldMatch).addConstraintViolation();
return false;
}
return isValid;
}
catch (final Exception ignore) {
// ignore
}
return true;
}
}
The User Model:
package com.joker.SampleAuthenticationWebApp.model;
import com.joker.SampleAuthenticationWebApp.validator.FieldsValueMatch;
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Set;
#Entity
#Table(name = "auth_user")
#FieldsValueMatch(field = "password", fieldMatch = "con_password", message = "Passwords do not match!")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "native")
#Column(name = "auth_user_id", unique = true)
private int id;
#NotNull
#NotEmpty(message = "First name is compulsory")
#Column(name = "firstname")
private String firstname;
#NotNull
#NotEmpty(message = "Last name is compulsory")
#Column(name = "lastname")
private String lastname;
#NotNull
#NotEmpty(message = "Email is compulsory")
#Email
#Column(name = "email")
private String email;
#NotNull
#Column(name = "phone")
private String phone;
#NotNull
#NotEmpty(message = "Password is compulsory")
#Length(min = 5, message = "Password length should be at least 5 characters")
#Column(name = "password")
private String password;
#NotEmpty(message = "Confirm Password field is compulsory")
#Transient
private String con_password;
#NotNull
#Column(name = "enabled")
private int enabled;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "auth_user_role", joinColumns = #JoinColumn(name = "auth_user_id"), inverseJoinColumns = #JoinColumn(name = "auth_role_id"))
private Set<Role> roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCon_password() {
return con_password;
}
public void setCon_password(String con_password) {
this.con_password = con_password;
}
public int getEnabled() {
return enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
I experienced this problem too . The only way to solve this is to include the annotations of #ModelAttribute and #Valid on your controller class for the bean you want to check weather the condition of #FieldsValueMatch(field = "password", fieldMatch = "con_password", message = "Passwords do not match!") is true , after that include the BindingResult right after the bean you want to check . Check if BindigResult hasErrors(), and return what is your next step .
EX:
#PostMapping("/signup")
public String signup(#ModelAttribute(name = "user") #Valid User user,BindingResult result,Model model)
if (result.hasErrors())
return "signup_form";
Hope this is clear .
I created spring boot project where I am making rest application. I have used My SQL database and I am using spring data. There is one method which adds orders based on customer id. So I am not able to figure out it will work based on spring data query or custom query and how it will be?
I have attached required codes only,
Customer.java
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name = "customers")
#NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "cust_ID_PK")
#GeneratedValue(strategy = GenerationType.AUTO)
private int custIDPK;
#Column(name = "billing_city")
private String billingCity;
#Column(name = "billing_country")
private String billingCountry;
#Column(name = "billing_state")
private String billingState;
#Column(name = "billing_street")
private String billingStreet;
#Column(name = "billing_zip")
private String billingZip;
private String company;
#Column(name = "display_name")
private String displayName;
private String email;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "other_details")
private String otherDetails;
#Column(name = "print_on_check_as")
private String printOnCheckAs;
#Column(name = "shipping_city")
private String shippingCity;
#Column(name = "shipping_country")
private String shippingCountry;
#Column(name = "shipping_state")
private String shippingState;
#Column(name = "shipping_street")
private String shippingStreet;
#Column(name = "shipping_zip")
private String shippingZip;
private String suffix;
private String title;
// bi-directional many-to-one association to Order
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private List<Order> orders;
public Customer() {
}
public int getCustIDPK() {
return this.custIDPK;
}
public void setCustIDPK(int cust_ID_PK) {
this.custIDPK = cust_ID_PK;
}
public String getBillingCity() {
return this.billingCity;
}
public void setBillingCity(String billingCity) {
this.billingCity = billingCity;
}
public String getBillingCountry() {
return this.billingCountry;
}
public void setBillingCountry(String billingCountry) {
this.billingCountry = billingCountry;
}
public String getBillingState() {
return this.billingState;
}
public void setBillingState(String billingState) {
this.billingState = billingState;
}
public String getBillingStreet() {
return this.billingStreet;
}
public void setBillingStreet(String billingStreet) {
this.billingStreet = billingStreet;
}
public String getBillingZip() {
return this.billingZip;
}
public void setBillingZip(String billingZip) {
this.billingZip = billingZip;
}
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
public String getDisplayName() {
return this.displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMiddleName() {
return this.middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getOtherDetails() {
return this.otherDetails;
}
public void setOtherDetails(String otherDetails) {
this.otherDetails = otherDetails;
}
public String getPrintOnCheckAs() {
return this.printOnCheckAs;
}
public void setPrintOnCheckAs(String printOnCheckAs) {
this.printOnCheckAs = printOnCheckAs;
}
public String getShippingCity() {
return this.shippingCity;
}
public void setShippingCity(String shippingCity) {
this.shippingCity = shippingCity;
}
public String getShippingCountry() {
return this.shippingCountry;
}
public void setShippingCountry(String shippingCountry) {
this.shippingCountry = shippingCountry;
}
public String getShippingState() {
return this.shippingState;
}
public void setShippingState(String shippingState) {
this.shippingState = shippingState;
}
public String getShippingStreet() {
return this.shippingStreet;
}
public void setShippingStreet(String shippingStreet) {
this.shippingStreet = shippingStreet;
}
public String getShippingZip() {
return this.shippingZip;
}
public void setShippingZip(String shippingZip) {
this.shippingZip = shippingZip;
}
public String getSuffix() {
return this.suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public List<Order> getOrders() {
return this.orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public Order addOrder(Order order) {
getOrders().add(order);
order.setCustomer(this);
return order;
}
public Order removeOrder(Order order) {
getOrders().remove(order);
order.setCustomer(null);
return order;
}
}
Order.java
import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
#Entity
#Table(name = "orders")
#NamedQuery(name = "Order.findAll", query = "SELECT o FROM Order o")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "order_ID_PK")
#GeneratedValue(strategy = GenerationType.AUTO)
private int order_ID_PK;
#Column(name = "custom_message")
private String customMessage;
#Temporal(TemporalType.DATE)
#Column(name = "delivery_due_date")
private Date deliveryDueDate;
#Temporal(TemporalType.DATE)
#Column(name = "invoice_creation_date")
private Date invoiceCreationDate;
#Temporal(TemporalType.DATE)
#Column(name = "payment_due_date")
private Date paymentDueDate;
// bi-directional many-to-one association to Customer
#ManyToOne
#JoinColumn(name = "cust_ID_FK")
private Customer customer;
// bi-directional many-to-many association to Product
#ManyToMany(mappedBy = "orders")
private List<Product> products;
public Order() {
}
public int getOrder_ID_PK() {
return this.order_ID_PK;
}
public void setOrder_ID_PK(int order_ID_PK) {
this.order_ID_PK = order_ID_PK;
}
public String getCustomMessage() {
return this.customMessage;
}
public void setCustomMessage(String customMessage) {
this.customMessage = customMessage;
}
public Date getDeliveryDueDate() {
return this.deliveryDueDate;
}
public void setDeliveryDueDate(Date deliveryDueDate) {
this.deliveryDueDate = deliveryDueDate;
}
public Date getInvoiceCreationDate() {
return this.invoiceCreationDate;
}
public void setInvoiceCreationDate(Date invoiceCreationDate) {
this.invoiceCreationDate = invoiceCreationDate;
}
public Date getPaymentDueDate() {
return this.paymentDueDate;
}
public void setPaymentDueDate(Date paymentDueDate) {
this.paymentDueDate = paymentDueDate;
}
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
OrderOperation.java
package com.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.model.Order;
public interface OrderOperation extends JpaRepository<Order, Long> {
#Query("SELECT c.orders FROM Customer c where c.custIDPK = :id")
public List<Order> findOrderbyID(#Param("id") int id);
}
CustomerController.java
#RestController
#RequestMapping("/customer")
public class CustomerController {
#Autowired
ICutomerService customerDAO;
#SuppressWarnings({ "unchecked", "rawtypes" })
#RequestMapping(value = { "/", "" }, method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<?> getAllCustomer() {
return new ResponseEntity(customerDAO.getAllCustomer(), HttpStatus.ACCEPTED);
}
#RequestMapping(value = "/{CustomerById}", method = RequestMethod.GET, produces = { "application/json" })
public Customer getCustomerbyId(#PathVariable("CustomerById") String cid) {
return customerDAO.findCustomerById(Integer.parseInt(cid));
}
#SuppressWarnings({ "unchecked", "rawtypes" })
#RequestMapping(value = "{CustomerById}/order", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<?> getAllOrder(#PathVariable("CustomerById") String cid) {
return new ResponseEntity(customerDAO.getOrdersbyId(Integer.parseInt(cid)), HttpStatus.ACCEPTED);
}
#SuppressWarnings({ "rawtypes", "unchecked" })
#RequestMapping(value = "order/{CustomerById}/product", method = RequestMethod.GET, produces = {
"application/json" })
public ResponseEntity<?> getAllProduct(#PathVariable("CustomerById") String cid) {
return new ResponseEntity(customerDAO.getProductsById(Integer.parseInt(cid)), HttpStatus.ACCEPTED);
}
#SuppressWarnings("rawtypes")
#RequestMapping(value = "/add", method = RequestMethod.POST)
public ResponseEntity<?> addCustomer(#RequestBody Customer c) {
boolean flag = customerDAO.addCustomer(c);
if (flag)
return new ResponseEntity(HttpStatus.CREATED);
else
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
#SuppressWarnings("rawtypes")
#RequestMapping(value = "/{CustomerById}/orders", method = RequestMethod.POST)
public ResponseEntity<?> addOrders(#PathVariable("CustomerById") String cid, #RequestBody Order c) {
// c.getCustomer().setCustIDPK(Integer.parseInt(cid));
boolean flag = customerDAO.addOrder(c);
if (flag) {
return new ResponseEntity(HttpStatus.CREATED);
} else {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
}
How should I design this addOrders method?
If you are using Spring Data then you will need to create a CrudRepository for each table you which to access. The CrudRepository allows you to easily manipulate data in your table using standard ORM practices. Here is a link with more details.
For more detailed info on how to use Spring Data check out this wonderful guide. This guide has become indispensable when working with Spring Data.
There are many options to this but i have used below approach so hope it helps you. The #Query annotation allows to execute native queries by setting the nativeQuery flag to true.
#Query(value = "select o.* from customer c inner join order o on c.customer_id = o.customer_id where o. = ?1", nativeQuery = true)
Please write sql according to your requirement.
After having sent a POST I receive a 400 error
curl localhost:8888/bills/addbill -H "Content-Type: application/json" -X POST -d '{"number":"111A111", "customer":"Customer Cuustomer Rrrr", "phone":"1 800 5551212", "manager":"Manager Manager Manager", "date":"2012-09-17", "curId":{"id":"1"}, "payments":{["id":"1"]}}'
The response is :
{"timestamp":1503684882518,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Bad Request","path":"/bills/addbill"}
I am getting an exception when I try to deserialize the my json data. How can I deserialize JSON properly?
Bill enntity file is:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import ru.test.practice.view.PaymentView;
import javax.persistence.*;
import javax.validation.constraints.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#Entity
#Table(name = "Bill")
public class Bill {
#GeneratedValue
#Id
#Column(name = "id")
private Integer id;
#Version
private int version;
#Column(name = "number")
#NotNull(message = "Num should be set")
#Size(min = 6, max = 10)
#Pattern(regexp = "^[^\\W_]+$")
private String number;
#Column(name = "customer")
#NotNull
#Size(max = 256)
#Pattern(regexp = "^[a-zA-Z\\s]*$")
private String customer;
#Column(name = "phone")
#NotNull
#Size(max = 20)
#Pattern(regexp = "(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:(\\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]\u200C\u200B)\\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)([2-9]1[02-9]\u200C\u200B|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})\\s*(?:\\s*(?:#|x\\.?|ext\\.?|extension)\\s*(\\d+)\\s*)?$")
private String phone;
#Column(name = "manager")
#Pattern(regexp = "^[a-zA-Z\\s]*$")
#Size(max = 256)
#NotNull
private String manager;
#Column(name = "date")
#NotNull
private Date date;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "cur_id")
private Currency curId;
#ManyToMany(targetEntity = ru.test.practice.model.Payment.class)
public List<PaymentView> payments = new ArrayList<>();
public List<PaymentView> getPayments() {
return payments;
}
public void setPayments(List<PaymentView> payments) {
this.payments = payments;
}
public Bill(Integer id, String number, String customer, String phone, String manager, Date date, Currency curId, List<PaymentView> payments) {
this.id = id;
this.number = number;
this.customer = customer;
this.phone = phone;
this.manager = manager;
this.date = date;
this.curId = curId;
this.payments = payments;
}
public Bill() {
this.id = null;
this.number = null;
this.customer = null;
this.phone = null;
this.manager = null;
this.date = null;
this.curId = null;
this.payments = null;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getId() {
return id;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public String getManager() {
return manager;
}
public void setManager(String manager) {
this.manager = manager;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Currency getCurId() {
return curId;
}
public void setCurId(Currency curId) {
this.curId = curId;
}
}
BillView file is
package ru.test.practice.view;
import io.swagger.annotations.ApiModelProperty;
import ru.bellintegrator.practice.model.Currency;
import java.util.Date;
import java.util.List;
public class BillView {
#ApiModelProperty(hidden = true)
public Integer id;
public String customer;
public String phone;
public String manager;
public String number;
public Date date;
public Currency curId;
public List<PaymentView> payments;
//для jackson
public BillView() {
}
public BillView(Integer id, String number, String customer, String phone, String manager, Date date, Currency curId, List<PaymentView> payments) {
this.id = id;
this.number = number;
this.customer = customer;
this.phone = phone;
this.manager = manager;
this.date = date;
this.curId = curId;
this.payments = payments;
}
#Override
public String toString() {
return "{id:" + id +
"billNumber:" + number +
";customer:" + customer +
";phone:" + phone +
";manager:" + manager +
";date:" + date +
";currencyId:" + curId +
";payments:" + payments +
"}";
}
}
Controller in BillController class that handles a POST request
#Override
#ApiOperation(value = "addBill", nickname = "addBill", httpMethod = "POST")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Success", response = String.class),
#ApiResponse(code = 404, message = "Not Found"),
#ApiResponse(code = 500, message = "Failure")})
#RequestMapping(value = "/addbill", method = {POST})
public void bill(#RequestBody BillView bill) {
billService.add(bill);
}
#Override
#ApiOperation(value = "getBills", nickname = "getBills", httpMethod = "GET")
#RequestMapping(value = "/list", method = {GET})
public List<BillView> bills() {
return billService.bills();
}
Finally my Payments Entity class:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#Entity
#Table(name = "Payments")
public class Payment {
#Id
#GeneratedValue
#Column(name = "id")
private Integer id;
#Version
private Integer version;
#Column(name = "name", nullable = false, length = 256)
private String name;
#Column(name = "price", nullable = false)
private float price;
#ManyToMany(targetEntity = ru.bellintegrator.practice.model.Bill.class, mappedBy = "curId")
private List<Bill> bills = new ArrayList<>();
public List<Bill> getBills() {
return bills;
}
public void setBills(List<Bill> bills) {
this.bills = bills;
}
public Integer getId() {
return id;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
you have problem in your json
"payments":{["id":"1"]}
since you are trying to deserialize list of type PaymentView this should be, i suppose PaymentView contains id attribute
"payments":[{"id":"1"}]
I had write a restful interface in NetbeansIDE8.2 ,and i have debug it with the PostMan App in chorme, and then an exception have experenced I will show the image down here :
the HTTP ERROR 500
and my code is here ,I have return a arryList to browser
#Path("/getStu")
#GET
public List<TfFreshstudent> queryStudentNoDomitory()
{
List<TfFreshstudent> studentList= cq.queryFreshstudentNoDomitory();
if (studentList.isEmpty()) {
return studentList;
}
return null;
}
and I have tried other sub of the automatic create code ,and the error is also happened:
#GET
public List<TfDormitory> getAllTfDormitories() {
log.debug("REST request to get all TfDormitories");
List<TfDormitory> tfDormitories = tfDormitoryFacade.findAll();
return tfDormitories;
}
I have think that it maybe the return type error maybe ArryList can't be show on browser, maybe I must parse it to json type or response
This is the entity which Jeddic was create
package com.freshV3.cart.model;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "tf_dormitory")
public class TfDormitory {
#Column(name = "id", table = "tf_dormitory", nullable = false, length = 22)
#Id
private String id;
#Column(name = "buildName", table = "tf_dormitory", length = 50)
#Basic
private String buildName;
#Column(name = "comment", table = "tf_dormitory")
#Basic
private String comment;
#Column(name = "freshStudentId", table = "tf_dormitory", length = 22)
#Basic
private String freshStudentId;
#Column(name = "isDelete", table = "tf_dormitory")
#Basic
private Integer isDelete;
#Column(name = "operator", table = "tf_dormitory", length = 20)
#Basic
private String operator;
#Column(name = "roomCode", table = "tf_dormitory", length = 32)
#Basic
private String roomCode;
#Column(name = "roomId", table = "tf_dormitory")
#Basic
private String roomId;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getBuildName() {
return this.buildName;
}
public void setBuildName(String buildName) {
this.buildName = buildName;
}
public String getComment() {
return this.comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getFreshStudentId() {
return this.freshStudentId;
}
public void setFreshStudentId(String freshStudentId) {
this.freshStudentId = freshStudentId;
}
public Integer getIsDelete() {
return this.isDelete;
}
public void setIsDelete(Integer isDelete) {
this.isDelete = isDelete;
}
public String getOperator() {
return this.operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getRoomCode() {
return this.roomCode;
}
public void setRoomCode(String roomCode) {
this.roomCode = roomCode;
}
public String getRoomId() {
return this.roomId;
}
public void setRoomId(String roomId) {
this.roomId = roomId;
}
}