spring-bootlistenerautowired

Spring Boot @PrePersist Listener: "this.partido" is null


I'm a beginner in Spring and I'm trying to use a @PrePersist listener to validate a Partido entity before it is saved to the database. However, I keep encountering the error: java.lang.NullPointerException: Cannot invoke "es.mde.repositorios.Partido.getCampo()" because "this.partido" is null.

I don't know what I'm doing wrong.

Here is my current code:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.persistence.PrePersist;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class PartidoListener {

    @Autowired
    private PartidoDAO partidoDAO; 

    @PrePersist
    public void validacionPartido(Partido partido) {
        System.err.println("punto de fallo: 1");
        Long partidoCampoId = partido.getCampo().getId();
        LocalDateTime partidoCuando = partido.getCuando();
        System.err.println("datos de partido: " + partidoCampoId + ", " + partidoCuando );
        System.err.println("punto de fallo: 2");
        try {
            List<Partido> partidosCoincidentes = partidoDAO.findAll()
                    .stream()
                    .filter(p -> p.getCuando().equals(partidoCuando))
                    .filter(p -> p.getCampo().getId().equals(partidoCampoId))
                    .collect(Collectors.toList());
            System.err.println("punto de fallo: 3");
            boolean valido = partidosCoincidentes.isEmpty();
            System.err.println("punto de fallo: 4");
            System.err.println("partido es valido: " + valido);
            System.err.println("punto de fallo: 5");
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

Error:

java.lang.NullPointerException: Cannot invoke "es.mde.repositorios.Partido.getCampo()" because "this.partido" is null

Additional Information:

Thank you!

I expected the @PrePersist listener to validate the Partido entity before it gets saved to the database by checking for conflicts based on the Campo and Cuando fields. I tried printing debug statements to identify where the issue occurs. It appears the error happens when trying to access the Campo or Cuando fields of the Partido entity, indicating that the Partido entity itself is null at this point.

I understand that retrieving all records and comparing them in memory is not efficient. I'm open to suggestions for improving this, such as defining a unique constraint in the database.

Note: This is not my final code. I am just trying to understand how to write a @PrePersist listener with a validation method. Once I understand how to do this with one example, I will be able to implement it for other entities as well.

EDIT:

Partido.class is like that:

@Entity
@Table(name = "PARTIDOS")
@EntityListeners(PartidoListener.class)
public class Partido {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true)  
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CAMPO")
    private Campo campo;
    private LocalDateTime cuando;
    
    @OneToMany(cascade = CascadeType.ALL, targetEntity = 
    Puntuacion.class, mappedBy = "partido")
    private Collection<Puntuacion> puntuaciones = new 
    ArrayList<>();

    ...
}

Campo.class is:

@Entity
@Table(name = "CAMPOS")
public class Campo {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true)  
    private Long id;
    
    private String nombre, provincia;
    private float valorCampo, valorSlope;
    
    @OneToMany(cascade = CascadeType.ALL, targetEntity = 
    Jugador.class, mappedBy = "campo")
    private Collection<Jugador> jugadores = new ArrayList<>();
    
    @OneToMany(cascade = CascadeType.ALL, targetEntity = 
    Partido.class, mappedBy = "campo")
    private Collection<Partido> partidos = new ArrayList<>();
    ...
}

Solution

  • Solution: I found the solution to my problem. It involved a couple of changes:

    1. Injecting the DAO in the Listener Instead of trying to inject the DAO directly into the listener, I used a static variable and a setter method with @Autowired. This way, the DAO gets properly initialized.

       @Component
       public class PartidoListener {
      
           private static PartidoDAO partidoDAO;
      
           @Autowired
           public void init(PartidoDAO partidoDAO) {
               PartidoListener.partidoDAO = partidoDAO;
           }
       }
       ...
      
    2. Configuring @ComponentScan I realized that the package where my listener was located needed to be included in the @ComponentScan annotation. I had @EnableJpaRepositories configured, but @ComponentScan was missing.

    With these changes, my @PrePersist listener started working correctly, and I no longer encountered the NullPointerException.

    Thank you to everyone who helped point me in the right direction!