Listeners can also have methods annotated with a lifecycle event. Listeners can be used to hold the business logic that would otherwise be in the entities (or another layer.) This enables the entities to be just POJOs. It also means that the testing of the business logic can be done in isolation.
Below is an example of using lifecycle events to populate an id var and also populate a lastUpdated var, in a mapped superclass:
@MappedSuperclass
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private static final int ID_LENGTH=36;
@Id
@Column(length = ID_LENGTH)
private String id;
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date dateCreated;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModified;
// constructor(s)
@PreUpdate
public void updateLastModified () {
lastModified = new Date();
}
@PrePersist
protected void generateUUID() {
id = java.util.UUID.randomUUID().toString();
dateCreated = new Date();
lastModified = new Date();
}
.....
}
An simple example of using a Listener could be where an entity has a transient var that needs to be populated after the entity has been persisted, updated or loaded.
public class AvailableCreditListener {
@PostLoad
@PostPersist
@PostUpdate
public void calculateAvailableCredit{Account account) {
account.setAvailableCredit(
account.getBalance().add(
account.getOverdraftLimit()));
}
}
The entity class would be annotated with @EntityListeners:
@EntityListeners({AvailableCreditListener.class})
public class AccountEntity extends BaseEntity {
private BigDecimal balance;
private BigDecimal overdraftLimit;
@Transient
private BigDecimal availableCredit;
// getters and setters
}
Finally, instead of annotations, an XMl mapping file can be used and deployed with the application to specify default listeners. (This mapping file is referenced by the persistence.xml file.) But an entity can use the @ExcludeDefaultListeners annotation if it does not want to use the default listeners.
@ExcludeDefaultListeners
@Entity
public class AccountEntity extends BaseEntity {
....
}