Issue
The main entity: it uses a one-to-one relationship to the "animal_passport" table. Everything is done according to the textbook and should work well. But for some reason, both tables refer to each other when calling the get method.
package com.testapp.model;
import javax.persistence.*;
@Entity
@Table(name = "animal")
public class Animal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "animal_id", nullable = false, updatable = false)
private long id;
@Column(name = "animal_value")
private String animal_value;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "pass_id")
private PassportAnimal passportAnimal;
public Animal(String animal_value, PassportAnimal passportAnimal) {
this.animal_value = animal_value;
this.passportAnimal = passportAnimal;
}
public Animal() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAnimal_value() {
return animal_value;
}
public void setAnimal_value(String animal_value) {
this.animal_value = animal_value;
}
public PassportAnimal getPassportAnimal() {
return passportAnimal;
}
public void setPassportAnimal(PassportAnimal passportAnimal) {
this.passportAnimal = passportAnimal;
}
}
Dependent entity:
package com.testapp.model;
import javax.persistence.*;
@Entity
@Table(name = "pass_anim")
public class PassportAnimal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "pass_id", nullable = false,updatable = false)
private long id;
@Column(name = "value_pass")
private String value;
@OneToOne(mappedBy = "passportAnimal")
private Animal animal;
public PassportAnimal(String value, Animal animal) {
this.value = value;
this.animal = animal;
}
public PassportAnimal() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
Controller the animal entity:
package com.testapp.controller;
import com.testapp.model.Animal;
import com.testapp.repository.AnimalRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@RequestMapping(path = "/api")
public class AnimalController {
@Autowired
AnimalRepository animalRepository;
@GetMapping("/animal")
public ResponseEntity<List<Animal>> getAllAnimal(@RequestParam(required = false) String value)
{
try {
List<Animal> animals = new ArrayList<>();
if (value == null) {
animalRepository.findAll().forEach(animals::add);
}
if (animals.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(animals, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/animal/{id}")
public ResponseEntity<Animal> getAnimalById(@PathVariable("id") long id) {
Optional<Animal> animalOptional = animalRepository.findById(id);
if (animalOptional.isPresent()) {
return new ResponseEntity<>(animalOptional.get(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PostMapping("/animal")
public ResponseEntity<Animal> createAnimal(@RequestBody Animal animal) {
try {
Animal _animal = animalRepository.save(new
Animal(animal.getAnimal_value(),animal.getPassportAnimal()));
return new ResponseEntity<>(_animal, HttpStatus.CREATED);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping("/animal/{id}")
public ResponseEntity<Animal> updateAnimal(@PathVariable("id") long id, @RequestBody Animal
animal) {
try {
Optional<Animal> animalOptional = animalRepository.findById(id);
if (animalOptional.isPresent()) {
Animal _animal = animalOptional.get();
_animal.setAnimal_value(animal.getAnimal_value());
_animal.setPassportAnimal(animal.getPassportAnimal());
return new ResponseEntity<>(animalRepository.save(_animal), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/animal/{id}")
public ResponseEntity<HttpStatus> deleteAnimal(@PathVariable("id") long id) {
try {
animalRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/animal")
public ResponseEntity<HttpStatus> deleteAllAnimals() {
try {
animalRepository.deleteAll();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
When calling the GET method, the animal and its passport should be output. But an infinite json is output. Inside the passport, the animal is displayed again and again his passport.
Solution
You are facing the infinite recursion issue. Please have a look at @JsonManagedReference and @JsonBackReference to solve this issue.
Answered By - Alien
Answer Checked By - Terry (JavaFixing Volunteer)