Προγραμματισμός

Χρησιμοποιήστε το Spring για να δημιουργήσετε έναν απλό κινητήρα ροής εργασίας

Πολλές εφαρμογές Jave για επιχειρήσεις απαιτούν την εκτέλεση της επεξεργασίας σε διαφορετικό περιβάλλον από αυτό του κύριου συστήματος. Σε πολλές περιπτώσεις, αυτές οι διαδικασίες backend εκτελούν πολλές εργασίες, με ορισμένες εργασίες να εξαρτώνται από την κατάσταση μιας προηγούμενης εργασίας. Με την απαίτηση αλληλοεξαρτώμενων εργασιών επεξεργασίας, μια εφαρμογή που χρησιμοποιεί ένα μόνο σετ διαδικαστικού τύπου μεθόδων κλήσεων συνήθως αποδεικνύεται ανεπαρκής. Χρησιμοποιώντας την Άνοιξη, ένας προγραμματιστής μπορεί εύκολα να διαχωρίσει μια διαδικασία backend σε ένα σύνολο δραστηριοτήτων. Το Spring container ενώνει αυτές τις δραστηριότητες για να σχηματίσει ένα απλή ροή εργασίας.

Για τους σκοπούς αυτού του άρθρου, απλή ροή εργασίας ορίζεται ως οποιοδήποτε σύνολο δραστηριοτήτων που εκτελούνται με προκαθορισμένη σειρά χωρίς αλληλεπίδραση χρήστη. Αυτή η προσέγγιση, ωστόσο, δεν προτείνεται ως αντικατάσταση των υπαρχόντων πλαισίων ροής εργασίας. Για σενάρια όπου απαιτούνται πιο προηγμένες αλληλεπιδράσεις, όπως πιρουνάκι, σύνδεση ή μεταβάσεις με βάση την είσοδο του χρήστη, ένας αυτόνομος ανοιχτός κώδικας ή ένας εμπορικός κινητήρας ροής εργασίας είναι καλύτερα εξοπλισμένος. Ένα έργο ανοιχτού κώδικα ενσωμάτωσε με επιτυχία έναν πιο περίπλοκο σχεδιασμό ροής εργασίας με το Spring.

Αν οι εργασίες της ροής εργασίας είναι απλοϊκές, η απλή προσέγγιση της ροής εργασίας έχει νόημα σε αντίθεση με ένα πλήρως λειτουργικό αυτόνομο πλαίσιο ροής εργασίας, ειδικά εάν το Spring είναι ήδη σε χρήση, καθώς η γρήγορη εφαρμογή είναι εγγυημένη χωρίς να απαιτείται χρόνος αύξησης. Επιπλέον, δεδομένης της φύσης του ελαφρού εμπορευματοκιβωτίου Inversion-of-Control της Spring, η Spring μειώνει την επιβάρυνση των πόρων.

Αυτό το άρθρο εισάγει εν συντομία τη ροή εργασίας ως θέμα προγραμματισμού. Χρησιμοποιώντας έννοιες ροής εργασίας, το Spring χρησιμοποιείται ως πλαίσιο για την οδήγηση ενός κινητήρα ροής εργασίας. Στη συνέχεια, συζητούνται οι επιλογές ανάπτυξης της παραγωγής. Ας ξεκινήσουμε με την ιδέα της απλής ροής εργασίας εστιάζοντας στα σχέδια σχεδίασης της ροής εργασίας και σε σχετικές βασικές πληροφορίες.

Απλή ροή εργασίας

Η μοντελοποίηση της ροής εργασίας είναι ένα θέμα που μελετήθηκε ήδη από τη δεκαετία του 1970 και πολλοί προγραμματιστές προσπάθησαν να δημιουργήσουν μια τυποποιημένη προδιαγραφή μοντελοποίησης ροής εργασίας. Σχέδια ροής εργασίας, μια λευκή βίβλος του W.H.M. van der Aalst et αϊ. (Ιούλιος 2003), κατάφερε να ταξινομήσει ένα σύνολο προτύπων σχεδίασης που μοντελοποιούν με ακρίβεια τα πιο κοινά σενάρια ροής εργασίας. Μεταξύ των πιο ασήμαντων μοτίβων ροής εργασίας είναι το μοτίβο ακολουθίας. Προσαρμόζοντας τα κριτήρια μιας απλής ροής εργασίας, το μοτίβο ροής εργασίας ακολουθίας αποτελείται από ένα σύνολο δραστηριοτήτων που εκτελούνται διαδοχικά.

Τα διαγράμματα δραστηριότητας UML (Unified Modeling Language) χρησιμοποιούνται συνήθως ως μηχανισμός μοντελοποίησης της ροής εργασίας. Το Σχήμα 1 δείχνει μια βασική διαδικασία ροής εργασιών ακολουθίας με μοντελοποίηση χρησιμοποιώντας ένα τυπικό διάγραμμα δραστηριότητας UML.

Η ροή εργασίας Sequence είναι ένα τυπικό μοτίβο ροής εργασίας που επικρατεί στις εφαρμογές J2EE. Μια εφαρμογή J2EE συνήθως απαιτεί μια ακολουθία συμβάντων σε ένα νήμα φόντου ή ασύγχρονα. Το διάγραμμα δραστηριότητας του Σχήματος 2 απεικονίζει μια απλή ροή εργασίας για να ειδοποιεί τους ενδιαφερόμενους ταξιδιώτες ότι ο αεροπορικός ναύλος στον αγαπημένο τους προορισμό έχει μειωθεί.

Η ροή εργασίας της αεροπορικής εταιρείας στο Σχήμα 1 είναι υπεύθυνη για τη δημιουργία και την αποστολή δυναμικών ειδοποιήσεων μέσω email. Κάθε βήμα στη διαδικασία αντιπροσωπεύει μια δραστηριότητα. Κάποιο εξωτερικό συμβάν πρέπει να συμβεί πριν τεθεί σε κίνηση η ροή εργασίας. Σε αυτήν την περίπτωση, αυτό το συμβάν είναι μείωση ποσοστού για τη διαδρομή πτήσης μιας αεροπορικής εταιρείας.

Ας δούμε την επιχειρηματική λογική της ροής εργασιών της αεροπορικής εταιρείας. Εάν η πρώτη δραστηριότητα δεν εντοπίσει χρήστες που ενδιαφέρονται για ειδοποιήσεις πτώσης τιμών, ακυρώνεται ολόκληρη η ροή εργασίας. Εάν εντοπιστούν ενδιαφερόμενοι χρήστες, οι υπόλοιπες δραστηριότητες ολοκληρώνονται. Στη συνέχεια, ένας μετασχηματισμός XSL (Extensible Stylesheet Language) δημιουργεί το περιεχόμενο των μηνυμάτων, μετά την οποία καταγράφονται οι πληροφορίες ελέγχου. Τέλος, γίνεται προσπάθεια αποστολής του μηνύματος μέσω διακομιστή SMTP. Εάν η υποβολή ολοκληρωθεί χωρίς σφάλμα, καταγράφεται η επιτυχία και η διαδικασία τερματίζεται. Ωστόσο, εάν προκύψει σφάλμα κατά την επικοινωνία με τον διακομιστή SMTP, θα αναλάβει μια ειδική ρουτίνα χειρισμού σφαλμάτων. Αυτός ο κωδικός χειρισμού σφαλμάτων θα προσπαθήσει να στείλει ξανά το μήνυμα.

Λαμβάνοντας υπόψη το παράδειγμα της αεροπορικής εταιρείας, ένα ερώτημα είναι προφανές: Πώς θα μπορούσατε να χωρίσετε αποτελεσματικά μια διαδοχική διαδικασία σε μεμονωμένες δραστηριότητες; Αυτό το πρόβλημα αντιμετωπίζεται εύγλωττα χρησιμοποιώντας το Spring. Ας συζητήσουμε γρήγορα την Άνοιξη ως πλαίσιο αντιστροφής του Ελέγχου.

Αντιστροφή ελέγχου

Το Spring μας επιτρέπει να αφαιρέσουμε την ευθύνη του ελέγχου των εξαρτήσεων ενός αντικειμένου μεταφέροντας αυτήν την ευθύνη στο δοχείο Spring. Αυτή η μεταβίβαση ευθύνης είναι γνωστή ως Inversion of Control (IoC) ή Dependency Injection. Ανατρέξτε στο "Αντιστροφή των εμπορευματοκιβωτίων ελέγχου και το μοτίβο εγχύσεων εξάρτησης" του Martin Fowler (martinfowler.com, Ιανουάριος 2004) για μια πιο εμπεριστατωμένη συζήτηση για το IoC και το Dependency Injection. Με τη διαχείριση εξαρτήσεων μεταξύ αντικειμένων, το Spring εξαλείφει την ανάγκη για κωδικός κόλλας, κωδικός γραμμένος με μοναδικό σκοπό να κάνει τα μαθήματα να συνεργάζονται μεταξύ τους.

Συστατικά ροής εργασίας ως φασόλια

Πριν φτάσουμε πολύ μακριά, τώρα είναι μια καλή στιγμή για να εξερευνήσετε τις βασικές ιδέες πίσω από την Άνοιξη. ο ApplicationContext διεπαφή, κληρονομικό από το Εργοστάσιο Bean διεπαφή, επιβάλλεται ως η πραγματική οντότητα ελέγχου ή κοντέινερ εντός της άνοιξης. ο ApplicationContext είναι υπεύθυνη για την παρουσίαση, τη διαμόρφωση και τη διαχείριση του κύκλου ζωής ενός συνόλου φασολιών που είναι γνωστά ως Ανοιξιάτικα φασόλια. ο ApplicationContext έχει διαμορφωθεί από καλωδίωση Άνοιξη φασόλια σε ένα αρχείο διαμόρφωσης που βασίζεται σε XML. Αυτό το αρχείο διαμόρφωσης υπαγορεύει τη φύση στην οποία τα φασολάκια συνεργάζονται μεταξύ τους. Έτσι, στην Άνοιξη μιλούν, τα φασόλια που αλληλεπιδρούν με άλλους είναι γνωστά ως συνεργάτες. Από προεπιλογή, τα φασόλια υπάρχουν ως μονότονοι στο ApplicationContext, αλλά το χαρακτηριστικό singleton μπορεί να οριστεί σε ψευδές, αλλάζοντας αποτελεσματικά ώστε να συμπεριφέρονται σε αυτό που ο Spring αποκαλεί πρωτότυπο τρόπος.

Επιστροφή στο παράδειγμά μας, στη μείωση των αεροπορικών ναύλων, μια αφαίρεση μιας ρουτίνας αποστολής SMTP είναι ενσύρματη ως η τελευταία δραστηριότητα στο παράδειγμα της διαδικασίας ροής εργασίας (παράδειγμα κωδικός διαθέσιμος στους πόρους) Όντας η πέμπτη δραστηριότητα, αυτό το φασόλι ονομάζεται κατάλληλα δραστηριότητα5. Για να στείλετε ένα μήνυμα, δραστηριότητα5 απαιτεί έναν συνεργάτη αντιπροσώπου και έναν χειριστή σφαλμάτων:

Η εφαρμογή των συστατικών της ροής εργασίας ως φασόλια Spring έχει ως αποτέλεσμα δύο επιθυμητά υποπροϊόντα, την ευκολία δοκιμής μονάδας και έναν μεγάλο βαθμό επαναχρησιμοποίησης. Η αποτελεσματική δοκιμή μονάδας είναι εμφανής δεδομένης της φύσης των δοχείων IoC. Χρησιμοποιώντας ένα κοντέινερ IoC όπως το Spring, οι εξαρτήσεις συνεργατών μπορούν εύκολα να αντικατασταθούν με πλαστές αντικαταστάσεις κατά τη διάρκεια της δοκιμής. Στο παράδειγμα της αεροπορικής εταιρείας, ένα Δραστηριότητα Φασόλια άνοιξη όπως δραστηριότητα5 μπορεί εύκολα να ανακτηθεί από αυτόνομο τεστ ApplicationContext. Αντικατάσταση ενός ψεύτικου αντιπροσώπου SMTP δραστηριότητα5 καθιστά δυνατή τη δοκιμή μονάδας δραστηριότητα5 χωριστά.

Το δεύτερο υποπροϊόν, η επαναχρησιμοποίηση, πραγματοποιείται από δραστηριότητες ροής εργασίας όπως ένας μετασχηματισμός XSL. Ένας μετασχηματισμός XSL, αφηρημένος σε δραστηριότητα ροής εργασίας, μπορεί τώρα να επαναχρησιμοποιηθεί από οποιαδήποτε ροή εργασίας που ασχολείται με μετασχηματισμούς XSL.

Καλωδίωση της ροής εργασίας

Στο παρεχόμενο API (με δυνατότητα λήψης από τους πόρους), το Spring ελέγχει ένα μικρό σύνολο παικτών για να αλληλεπιδράσουν με τρόπο που αποτελεί ροή εργασίας. Οι βασικές διεπαφές είναι:

  • Δραστηριότητα: Ενσωματώνει επιχειρηματική λογική ενός μόνο βήματος στη διαδικασία ροής εργασίας.
  • ProcessContext: Αντικείμενα τύπου ProcessContext περνούν μεταξύ των δραστηριοτήτων στη ροή εργασίας. Τα αντικείμενα που εφαρμόζουν αυτήν τη διεπαφή είναι υπεύθυνα για τη διατήρηση της κατάστασης καθώς η ροή εργασίας μεταβαίνει από τη μία δραστηριότητα στην άλλη.
  • Σφάλμα χειριστή: Παρέχει μια μέθοδο επανάκλησης για τον χειρισμό σφαλμάτων.
  • Επεξεργαστής: Περιγράφει ένα φασόλι που λειτουργεί ως εκτελεστής του κύριου νήματος ροής εργασίας.

Το ακόλουθο απόσπασμα από τον δείγμα κώδικα είναι μια διαμόρφωση Spring bean που δεσμεύει το παράδειγμα της αεροπορικής εταιρείας ως μια απλή διαδικασία ροής εργασίας.

             / ιδιοκτησία> org.iocworkflow.test.sequence.ratedrop.RateDropContext 

ο Επεξεργαστής ακολουθίας class είναι μια συγκεκριμένη υποκατηγορία που διαμορφώνει ένα μοτίβο ακολουθίας. Ενσύρματα στον επεξεργαστή είναι πέντε δραστηριότητες που ο επεξεργαστής ροής εργασίας θα εκτελέσει με τη σειρά.

Σε σύγκριση με τις περισσότερες διαδικαστικές διαδικασίες backend, η λύση της ροής εργασίας ξεχωρίζει ως ικανή για πολύ ισχυρό χειρισμό σφαλμάτων. Ένας χειριστής σφαλμάτων μπορεί να συνδεθεί ξεχωριστά για κάθε δραστηριότητα. Αυτός ο τύπος χειριστή παρέχει λεπτομερείς χειρισμούς σφαλμάτων σε επίπεδο επιμέρους δραστηριότητας. Εάν δεν υπάρχει ενσύρματο πρόγραμμα χειρισμού σφαλμάτων για μια δραστηριότητα, ο χειριστής σφαλμάτων που ορίζεται για τη συνολική επεξεργασία ροής εργασίας θα χειριστεί το πρόβλημα. Για αυτό το παράδειγμα, εάν παρουσιαστεί σφάλμα χωρίς χειρισμό οποιαδήποτε στιγμή κατά τη διάρκεια της διαδικασίας ροής εργασίας, θα εξαπλωθεί για να αντιμετωπιστεί από το Σφάλμα χειριστή φασόλι, το οποίο είναι ενσύρματο χρησιμοποιώντας το defaultErrorHandler ιδιοκτησία.

Τα πιο σύνθετα πλαίσια ροής εργασίας παραμένουν σε κατάσταση δεδομένων σε μια αποθήκευση δεδομένων μεταξύ των μεταβάσεων. Σε αυτό το άρθρο, ενδιαφερόμαστε μόνο για απλές περιπτώσεις ροής εργασιών όπου η μετάβαση κατάστασης είναι αυτόματη. Οι πληροφορίες κατάστασης είναι διαθέσιμες μόνο στο ProcessContext κατά το χρόνο εκτέλεσης της πραγματικής ροής εργασίας. Έχοντας μόνο δύο μεθόδους, μπορείτε να δείτε το ProcessContext η διεπαφή βρίσκεται σε δίαιτα:

δημόσια διεπαφή ProcessContext επεκτείνει το Serializable {public boolean stopProcess (); public void setSeedData (Object seedObject); }

Το σκυρόδεμα ProcessContext κλάση που χρησιμοποιείται για τη ροή εργασίας της αεροπορικής εταιρείας παράδειγμα είναι η RateDropContext τάξη. ο RateDropContext Η κλάση ενσωματώνει τα απαραίτητα δεδομένα για την εκτέλεση ροής εργασιών πτώσης τιμών αεροπορικής εταιρείας.

Μέχρι τώρα, όλες οι εμφανίσεις φασολιών ήταν μονότονοι σύμφωνα με την προεπιλογή ApplicationContextη συμπεριφορά. Αλλά πρέπει να δημιουργήσουμε μια νέα παρουσία του RateDropContext τάξη για κάθε επίκληση της ροής εργασίας της αεροπορικής εταιρείας. Για την αντιμετώπιση αυτής της απαίτησης, το Επεξεργαστής ακολουθίας έχει διαμορφωθεί, λαμβάνοντας ένα πλήρως αναγνωρισμένο όνομα κλάσης ως το processContextClass ιδιοκτησία. Για κάθε εκτέλεση ροής εργασίας, το Επεξεργαστής ακολουθίας ανακτά μια νέα παρουσία του ProcessContext από την Άνοιξη χρησιμοποιώντας το καθορισμένο όνομα τάξης. Για να λειτουργήσει αυτό, ένα φασόλι άνοιξη που δεν είναι νόστιμο ή πρωτότυπο του τύπου org.iocworkflow.test.sequence.simple.SimpleContext πρέπει να υπάρχει στο ApplicationContext (βλέπω rateDrop.xml για ολόκληρη την καταχώριση).

Σπορά της ροής εργασίας

Τώρα που ξέρουμε πώς να συνδυάσουμε μια απλή ροή εργασίας χρησιμοποιώντας το Spring, ας επικεντρωθούμε στην παρουσίαση χρησιμοποιώντας δεδομένα σπόρου. Για να καταλάβουμε πώς να σπείρουμε τη ροή εργασίας, ας δούμε μεθόδους που εκτίθενται στην πραγματική Επεξεργαστής διεπαφή:

δημόσια διεπαφή Επεξεργαστής {public boolean υποστηρίξεις (Δραστηριότητα δραστηριότητας). δημόσιο άκυρο doActivities (); δημόσιο άκυρο doActivities (Object seedData); public void setActivities (Λίστα δραστηριοτήτων) · public void setDefaultErrorHandler (ErrorHandler defaultErrorHandler); }

Στις περισσότερες περιπτώσεις, οι διαδικασίες ροής εργασίας απαιτούν κάποια αρχικά ερεθίσματα για την έναρξη. Υπάρχουν δύο επιλογές για την έναρξη ενός επεξεργαστή: το doActivities (αντικείμενο seedData) μέθοδος ή την εναλλακτική λύση χωρίς επιχειρήματα. Η ακόλουθη λίστα κωδικών είναι η doAcvtivities () εφαρμογή για το Επεξεργαστής ακολουθίας περιλαμβάνονται στον δείγμα κώδικα:

 public void doActivities (Object seedData) {if (logger.isDebugEnabled ()) logger.debug (getBeanName () + "ο επεξεργαστής εκτελείται .."); // ανάκτηση που εγχύθηκε από δραστηριότητες της Άνοιξης Λίστα = getActivities (); // ανακτήστε μια νέα παρουσία του Workflow ProcessContext ProcessContext konteks = createContext (); εάν (seedData! = null) context.setSeedData (seedData); για (Iterator it = activities.iterator (); it.hasNext ();) {Activity activity = (Activity) it.next (); if (logger.isDebugEnabled ()) logger.debug ("running activity:" + activity.getBeanName () + "χρησιμοποιώντας ορίσματα:" + περιβάλλον); δοκιμάστε το {context = activity.execute (konteks); } catch (Throwable th) {ErrorHandler errorHandler = activity.getErrorHandler (); if (errorHandler == null) {logger.info ("κανένα πρόγραμμα χειρισμού σφαλμάτων για αυτήν την ενέργεια, εκτελέστε το προεπιλεγμένο σφάλμα" + "χειριστής και επεξεργασία ματαίωσης"); getDefaultErrorHandler (). handleError (πλαίσιο, th); Διακοπή; } αλλιώς {logger.info ("εκτελέστε το πρόγραμμα χειρισμού σφαλμάτων και συνεχίστε"); errorHandler.handleError (περιβάλλον, ου); }}