Callbacks and Listeners PENGEMBANGAN APLIKASI ENTERPRISE © NIKO IBRAHIM FAKULTAS TEKNOLOGI INFORMASI UNIVERSITAS KRISTEN MARANATHA
Callback & Listener Methods life-cycle callback dan Listener bekerja
dengan prinsip yang sama dengan trigger di dalam database. Suatu trigger akan mengeksekusi logika bisnis untuk setiap baris di dalam tabel. Callback dan listener akan dieksekusi untuk setiap instance entity pad saat terjadi suatu event tertentu (sebelum atau sesudah terjadi event) Untuk menentukan waktu eksekusi-nya, kita dapat menggunakan annotations atau XML descriptor, yaitu: “Pre” dan “Post”
Callbacks Siklus hidup suatu entitas dapat dibagi ke dalam 4 kategori: persisting, updating, removing, dan loading, yang berkorespondensi dengan operasi database untuk
proses:
inserting, updating, deleting, and selecting, respectively.
Setiap siklus hidup memiliki event “Pre” dan “Post” yang
dapat dibaca oleh entity manager untuk mengeksekusi fungsi bisnis tertentu.
Life-Cycle Callback Annotations Annotation
Description
@PrePersist
Marks a method to be invoked before EntityManager.persist() is executed.
@PostPersist
Marks a method to be invoked after the entity has been persisted. If the entity autogenerates its primary key (with @GeneratedValue), the value is available in the method.
@PreUpdate
Marks a method to be invoked before a database update operation is performed (calling the entity setters or the EntityManager.merge() method).
@PostUpdate
Marks a method to be invoked after a database update operation is performed.
@PreRemove
Marks a method to be invoked before EntityManager.remove() is executed.
@PostRemove Marks a method to be invoked after the entity has been removed. @PostLoad
Marks a method to be invoked after an entity is loaded (with a JPQL query or an EntityManager.find()) or refreshed from the underlying database. There is no @PreLoad annotation, as it doesn’t make sense to preload data on an entity that is not built yet.
The Customer Entity with Callback Annotations @Entity public class Customer { @Id @GeneratedValue private Long id; private String firstName; private String lastName; private String email; private String phoneNumber; @Temporal(TemporalType.DATE) private Date dateOfBirth; @Transient private Integer age; @Temporal(TemporalType.TIMESTAMP) private Date creationDate; Continue…
@PrePersist @PreUpdate private void validate() { if (dateOfBirth.getTime() > new Date().getTime()) throw new IllegalArgumentException("Invalid date of birth"); if (!phoneNumber.startsWith("+")) throw new IllegalArgumentException("Invalid phone number"); }
Continue…
@PostLoad @PostPersist @PostUpdate public void calculateAge() { if (dateOfBirth == null) { age = null; return; } Calendar birth = new GregorianCalendar(); birth.setTime(dateOfBirth); Calendar now = new GregorianCalendar(); now.setTime(new Date()); int adjust = 0; if (now.get(GregorianCalendar.DAY_OF_YEAR) - birth.get(GregorianCalendar.DAY_OF_YEAR) < 0) {
adjust = -1; } age = now.get(GregorianCalendar.YEAR) - birth.get(GregorianCalendar.YEAR) + adjust;
} // Constructors, getters, setters
}
Listeners Methods Callback dalam sebuah entitas bermanfaat
apabila kita memiliki logika bisnis yang hanya berkaitan dengan entitas tersebut. Entity Listeners digunakan untuk memisahkan logika bisnis ke dalam class tersendiri sehingga dapat di-share dan dimanfaatkan oleh entitas yang lain. Untuk meregistrasi sebuah listener, entitas perlu ditambahkan annotation @EntityListeners.
A Listener Calculating the Customer’s Age public class AgeCalculationListener { @PostLoad @PostPersist @PostUpdate public void calculateAge(Customer customer) { if (customer.getDateOfBirth() == null) { customer.setAge(null); return; } Calendar birth = new GregorianCalendar(); birth.setTime(customer.getDateOfBirth()); Calendar now = new GregorianCalendar(); now.setTime(new Date()); int adjust = 0; if (now.get(GregorianCalendar .DAY_OF_YEAR) - birth.get(GregorianCalendar .DAY_OF_YEAR) < 0) { adjust = -1; } customer.setAge(now.get(GregorianCalendar .YEAR) birth.get(GregorianCalendar .YEAR) + adjust); } }
A Listener Validating the Customer’s Attributes public class DataValidationListener { @PrePersist @PreUpdate private void validate(Customer customer) { if (dateOfBirth.getTime() > new Date().getTime()) throw new IllegalArgumentException("Invalid date of birth"); if (!phoneNumber.startsWith("+")) throw new IllegalArgumentException("Invalid phone number"); } }
The Customer Entity Defining Two Listeners @EntityListeners({DataValidationListener.class, AgeCalculationListener.class}) @Entity public class Customer { @Id @GeneratedValue private Long id; private String firstName; private String lastName; private String email; private String phoneNumber; @Temporal(TemporalType.DATE) private Date dateOfBirth; @Transient private Integer age; @Temporal(TemporalType.TIMESTAMP) private Date creationDate; // Constructors, getters, setters }
Tutorial Program: Callback Methods Buatlah sebuah project baru “Java Application”
(bukan web) Aplikasi ini bertujuan untuk mendemonstrasikan Callback di dalam JPA Ikuti langkah berikut:
Buatlah entity class Customer (slide 5) Tambahkan method calculateAge dan validate pada entity class tersebut Buatlah sebuah main class untuk mendemonstrasikan input data customer, proses validasi, dan proses perhitungan usia customer ybs.
Selamat Mengerjakan