Nov 19, 2014

Αποστολή γεγονότων (dispatching events) σε πολλαπλά ADF task flow managed beans

Μια πολύ σημαντική αρχή του αντικειμενοστραφούς προγραμματισμού είναι ο περιορισμός του κεντρικού ελέγχου διαδικασιών και η κατανεμημένη διανομή γεγονότων (events) όπου υπάρχει ενδιαφέρον. Στον κόσμο του ADF, ένα αντιπαράδειγμα που  έρχεται στο μυαλό έχει να κάνει με μεγάλους κώδικες που συντηρούνται σε ADF managed beans και που επιτελούν διαφορετικές λειτουργίες, καλύπτοντας πολλαπλές διαφορετικές απαιτήσεις.

Έστω πως θέλουμε να δώσουμε μια κοινή συμπεριφορά στην εφαρμογή μας ώστε με ένα κουμπί να γίνεται αποθήκευση (commit) των αλλαγών. Επιπλέον, θα θέλαμε να εμφανίζεται ένα popup παράθυρο επιβεβαίωσης μετά την οριστικοποίηση. Τέλος με την ολοκλήρωση των αλλαγών θέλουμε να ενημερώνεται η κατάσταση του TabContext αν χρησιμοποιούμε το Dynamic Tabs UI Shell framework. Θα φτιάξουμε σε ένα σημείο μια συγκεντρωτική λειτουργία που θα καλύπτει όλες τις παραπάνω ανάγκες;

Μια προσέγγιση θα μπορούσε να κάνει με την υλοποίηση της διαδικασίας της αποθήκευσης και την ειδοποίηση άλλων ενδιαφερόμενων αντικειμένων για αυτήν την μεταβολή, ώστε να κάνουν αυτά τη δουλειά τους (να προβάλλουν popup, να μεταφέρουν τον χρήστη σε άλλη οθόνη, να ενημερώσουν το UI shell, κλπ) Ευτυχώς μπορούμε να ορίσουμε μια λίστα από κλάσεις που σχετίζονται με ένα ADF managed bean στον ορισμό του task flow, ώστε αυτή η λίστα να ενημερώνεται για μια μεταβολή. Ας κατασκευάσουμε για παράδειγμα ένα Java interface:

public interface CommitListener {
    void afterCommit();
}

και αντίστοιχα δυο κλάσεις που το υλοποιούν: έστω τη JSFCommitListener που εμφανίζει ένα popup και την DynamicTabListener που ενημερώνει το UI Shell. Τις δυο αυτές κλάσεις ας τις ορίσουμε στο task flow μας:
ενώ στην κλάση μας που διαχειρίζεται το κουμπί της αποθήκευσης των αλλαγών (πχ CommitBean), ας δηλώσουμε μια γενική λίστα από κλάσεις που θα πρέπει να ενημερωθούν:

    private List commitListeners;

    public void setCommitListeners(List<CommitListener> observers) {
        this.observers = observers;
    }

    public List getCommitListeners() {
        return observers;
    }

    public void onCommit() {
            for (CommitListener c : getCommitListeners()) {
                c.afterCommit();
            }
    }

Αυτό που μας απομένει είναι να κάνουμε ενσωματώσουμε (inject) τη λίστα των managed beans (listeners) στην κλάση μας CommitBean. Επιστρέφουμε λοιπόν στο task flow μας και γράφουμε τον ακόλουθο κώδικα (μιας και δεν υπάρχει υποστήριξη στον design editor για την παροχή λίστας τιμών):

<managed-bean>
    <managed-bean-name>commitBean</managed-bean-name>
    <managed-bean-class>CommitBean</managed-bean-class>
    <managed-bean-scope>backingBean</managed-bean-scope>
    <managed-property>
      <property-name>commitListeners</property-name>
      <list-entries>
            <value>#{backingBeanScope.dynamictablistener}</value>
            <value>#{backingBeanScope.jsfcommitlistener}</value>
        </list-entries>
    </managed-property>
  </managed-bean>



No comments: