Home > Enterprise >  Output Spring Boot is reversed in Postman
Output Spring Boot is reversed in Postman

Time:11-09

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);
    }
}

CodePudding user response:

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());
}
  • Related