0

Hi everyone I recently work with Spring Data and I have such a question.

I have my Entity that mapped like this:

@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Table(name = "movie")
@Entity
public class Movie extends BaseEntity {

    private String name;
    @Enumerated(EnumType.STRING)
    @Column(columnDefinition = "enum('ACTION','DRAMA','COMEDY','FANTASY','HORROR')")
    private Genre genre;

    private BigDecimal budget;

    @ManyToMany(mappedBy = "movies")
    private Set<Actor> actors;

    public Movie() {
    }
}

My Actor Entity:

@Getter
@Setter
@EqualsAndHashCode(callSuper = true, exclude = "movies")
@ToString(callSuper = true, exclude = "movies")
@Table(name = "actor")
@Entity
public class Actor extends BaseEntity {

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "salary")
    private BigDecimal salary;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "actor_movie",
            joinColumns = {@JoinColumn(name = "actor_id")},
            inverseJoinColumns = {@JoinColumn(name = "movie_id")}
    )
        private Set<Movie> movies;

    public Actor() {
    }
}

And my BaseEntity;

@Data
@MappedSuperclass
public class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

I am using JpaRepository<Actor, Long> to get my actors from database:

@Repository
public interface ActorRepository extends JpaRepository<Actor, Long> {
}

And here is my controller:

@RestController
@RequestMapping("actor")
public class ActorController {

    @Autowired
    ActorRepository actorRepository;

    @PostMapping
    public Actor save(@RequestBody Actor actor) {
        actorRepository.save(actor);
        return actor;
    }

    @GetMapping
    public Iterable<Actor> findAllActors() {
        return actorRepository.findAll();
    }

    @GetMapping("{id}")
    public Actor findActor(@PathVariable Long id) {
        return actorRepository.findById(id).orElseThrow(NotFoundException::new);
    }

    @PutMapping("{id}")
    public Actor update(@RequestBody Actor actor, @PathVariable Long id) {
        actor.setId(id);
        return actorRepository.save(actor);
    }

    @DeleteMapping("{id}")
    public ResponseEntity<Actor> delete(@PathVariable Long id) {
        actorRepository.deleteById(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

So when I'm trying to get my actor by id it gets a so many times: enter image description here

And finally it fails with StackOverFlowError:

java.lang.StackOverflowError: null
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_172]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_172]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_172]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_172]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_172]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_172]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_172]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_172]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_172]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_172]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_172]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_172]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.9.jar:2.9.9]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.9.jar:2.9.9]

Why is this happens? And how it can be fixed?

Mefisto_Fell
  • 876
  • 1
  • 10
  • 30
  • 2
    You're telling Jackson to serialize an actor. An actor has N movies. So Jackson serializes the N movies. Each movie has N actors. So Jackson serializes the actors. Each actor has N movies. So Jackson serializes the movies. Each movie has N actors. So Jackson serializes the actors, etc. etc. ad infinitum. There are plenty of ways to avoid this, and this question has been asked several times before. – JB Nizet Aug 17 '19 at 15:47
  • My preferred solution would be to stop returning entities from your controllers. Decide what the actual JSON you want to return should look like. Create DTO classes that match with this JSON. Transform entities into DTOs and return them. – JB Nizet Aug 17 '19 at 15:47
  • This question may help you: https://stackoverflow.com/questions/37392733/difference-between-jsonignore-and-jsonbackreference-jsonmanagedreference/37394318 – Jaume Morón i Tarrasa Aug 17 '19 at 15:58
  • @mefisto_fall can you please reduce the noice? Like only post the code that is relevant. We don't care much about your full controller or full entity code. Neither do we care much about your lombok annotation. That way, it will be easier for us to read and understand the problem. – Faraz Aug 17 '19 at 16:31
  • @JBNizet you are the best. – Faraz Aug 17 '19 at 16:31

0 Answers0