Ohjelmointi

Luo yksinkertainen työnkulun moottori keväällä

Monet Jave-yrityssovellukset edellyttävät käsittelyn suorittamista erillisessä kontekstissa kuin pääjärjestelmä. Monissa tapauksissa nämä taustaprosessit suorittavat useita tehtäviä, joista osa riippuu edellisen tehtävän tilasta. Kun vaaditaan keskenään riippuvaisia ​​käsittelytehtäviä, yhden menettelytyylisen tyyppisen menetelmän kutsuja käyttävä toteutus osoittautuu yleensä riittämättömäksi. Kehittäjä voi Springiä hyödyntämällä helposti erottaa taustaprosessin toimintojen yhdistelmäksi. Kevään kontti yhdistää nämä toiminnot muodostamaan a yksinkertainen työnkulku.

Tämän artikkelin tarkoituksiin yksinkertainen työnkulku Määritellään minkä tahansa toiminnan joukoksi, joka suoritetaan ennalta määrätyssä järjestyksessä ilman käyttäjän vuorovaikutusta. Tätä lähestymistapaa ei kuitenkaan ehdoteta korvaamaan nykyisiä työnkulun kehyksiä. Skenaarioissa, joissa tarvitaan edistyneempiä vuorovaikutuksia, kuten haaroittaminen, liittyminen tai siirtymät käyttäjän syötteen perusteella, erillinen avoimen lähdekoodin tai kaupallinen työnkulun moottori on paremmin varustettu. Yhdessä avoimen lähdekoodin projektissa on onnistuneesti integroitu monimutkaisempi työnkulun suunnittelu Springiin.

Jos käsillä olevat työnkulun tehtävät ovat yksinkertaisia, yksinkertainen työnkulun lähestymistapa on järkevä verrattuna täysin toimivaan erilliseen työnkulun kehykseen, varsinkin jos Spring on jo käytössä, koska nopea toteutus taataan ilman ylösaikaa. Lisäksi ottaen huomioon Springin kevyen Inversion-of-Control-kontin luonteen, Spring vähentää resurssien yleiskustannuksia.

Tässä artikkelissa esitellään lyhyesti työnkulku ohjelmoinnin aiheena. Käyttämällä työnkulun käsitteitä Spring käytetään puitteena työnkulun moottorin ohjaamiseen. Sitten keskustellaan tuotannon käyttöönottovaihtoehdoista. Aloitetaan yksinkertaisen työnkulun ideasta keskittymällä työnkulun suunnittelumalleihin ja niihin liittyvään taustatietoon.

Yksinkertainen työnkulku

Työnkulun mallintaminen on aihetta, jota on tutkittu jo 1970-luvulla, ja monet kehittäjät ovat yrittäneet luoda standardoidun työnkulun mallinnuseritelmän. Työnkulun mallit, valkoinen kirja, jonka on kirjoittanut W.H.M. van der Aalst et ai. (Heinäkuu 2003), on onnistunut luokittelemaan joukon suunnittelumalleja, jotka mallinnavat tarkasti yleisimmät työnkulun skenaariot. Työnkulun kaikkein vähäpätöisimpien joukossa on sekvenssikuvio. Sekvenssin työnkulun malli koostuu yksinkertaisen työnkulun kriteereistä, jotka koostuvat sarjasta suoritettuja toimintoja.

UML-toimintakaavioita (Unified Modeling Language) käytetään yleisesti työnkulun mallintamismekanismina. Kuva 1 esittää peräkkäisen työnkulkuprosessin, joka on mallinnettu käyttäen standardia UML-toimintakaaviota.

Sekvenssin työnkulku on J2EE-sovelluksissa yleinen työnkulun malli. J2EE-sovellus edellyttää yleensä tapahtumasarjan tapahtumista taustalangassa tai asynkronisesti. Kuvion 2 toimintakaavio havainnollistaa yksinkertaista työnkulkua ilmoittaakseen kiinnostuneille matkustajille, että lentoliput heidän suosikkikohteeseensa ovat laskeneet.

Kuvan 1 lentoyhtiön työnkulku on vastuussa dynaamisten sähköposti-ilmoitusten luomisesta ja lähettämisestä. Jokainen prosessin vaihe edustaa toimintaa. Joitakin ulkoisia tapahtumia on tapahduttava ennen työnkulun käynnistämistä. Tässä tapauksessa kyseinen tapahtuma on lentoyhtiön lentoreitin hinnanlasku.

Käydään läpi lentoyhtiön työnkulun liiketoimintalogiikka. Jos ensimmäisessä toiminnossa ei löydy käyttäjiä, jotka ovat kiinnostuneita pudotusilmoituksista, koko työnkulku peruutetaan. Jos kiinnostuneita käyttäjiä löydetään, muut toiminnot suoritetaan. Tämän jälkeen XSL (Extensible Stylesheet Language) -muunnos luo viestin sisällön, jonka jälkeen auditointitiedot tallennetaan. Lopuksi yritetään lähettää viesti SMTP-palvelimen kautta. Jos lähetys valmistuu virheettömästi, menestys kirjataan ja prosessi päättyy. Mutta jos virhe tapahtuu yhteydenpidossa SMTP-palvelimen kanssa, erityinen virheenkäsittelyrutiini otetaan käyttöön. Tämä virhekäsittelykoodi yrittää lähettää viestin uudelleen.

Lentoyhtiön esimerkin perusteella on selvää yksi kysymys: Kuinka voisit tehokkaasti jakaa peräkkäisen prosessin yksittäisiin toimintoihin? Tämä ongelma hoidetaan kaunopuheisesti Springin avulla. Keskustellaan nopeasti keväästä inversioksi ohjauskehykseksi.

Käänteinen ohjaus

Kevään avulla voimme poistaa vastuun hallita esineen riippuvuuksia siirtämällä tämän vastuun jousisäiliöön. Tämä vastuun siirto tunnetaan nimellä invertointi (IoC) tai riippuvuuden injektio. Katso perusteellisempi keskustelu IoC: stä ja riippuvuusinjektiosta Martin Fowlerin julkaisussa "Kontrollisäiliöiden kääntäminen ja riippuvuuden injektiomalli" (martinfowler.com, tammikuu 2004). Hallitsemalla esineiden välisiä riippuvuuksia Spring eliminoi tarpeen liimakoodi, koodi, joka on kirjoitettu ainoana tarkoituksena saada luokat tekemään yhteistyötä keskenään.

Työnkulun komponentit kevätpapuina

Ennen kuin pääsemme liian pitkälle, nyt on hyvä aika käydä läpi kevään taustalla olevat pääkäsitteet. ApplicationContext käyttöliittymä, perimällä Pavutehdas käyttöliittymä, asettaa itsensä varsinaiseksi hallitsevaksi yksiköksi tai kontiksi Springissä. ApplicationContext on vastuussa pavut, jotka tunnetaan nimellä, instantioinnista, kokoonpanosta ja elinkaaren hallinnasta Kevätpavut. ApplicationContext on määrittänyt johdotus Kevätpavut XML-pohjaisessa määritystiedostossa. Tämä kokoonpanotiedosto sanelee luonteen, jossa kevätpavut tekevät yhteistyötä keskenään. Niinpä keväällä puhuen kevätpavut, jotka ovat vuorovaikutuksessa muiden kanssa, tunnetaan nimellä yhteistyökumppaneita. Oletusarvoisesti kevätpavut ovat singletoneina ApplicationContext, mutta singleton-määritteeksi voidaan asettaa epätosi, mikä muuttaa ne käytännössä käyttäytymään siinä, mitä kevät kutsuu prototyyppi -tilassa.

Palataksemme esimerkkiin, lentolipun alennuksessa SMTP-lähetysrutiinin abstraktio kytketään viimeiseksi toiminnaksi työnkulun prosessiesimerkissä (esimerkkikoodi käytettävissä Resursseissa). Koska tämä papu on viides aktiviteetti, se on nimetty sopivasti toiminta 5. Lähettää viesti, toiminta 5 vaatii edustajan jakelijan ja virheenkäsittelijän:

Työnkulun komponenttien toteuttaminen kevätpapuina tuottaa kaksi toivottavaa sivutuotetta, yksikkötestauksen helppouden ja suuren uudelleenkäytettävyyden. Tehokas yksikkötestaus on ilmeistä IoC-konttien luonteen vuoksi. Yhteistyökumppaniriippuvuudet voidaan helposti vaihtaa IoC-säiliön, kuten Spring, kanssa testauksen aikana. Lentoyhtiön esimerkissä Toiminta Kevätpapu kuten toiminta 5 voidaan helposti noutaa erillisestä testistä ApplicationContext. SMTP-edustajan mallin korvaaminen toiminta 5 mahdollistaa yksikkötestin toiminta 5 erikseen.

Toinen sivutuote, uudelleenkäytettävyys, toteutetaan työnkulun toiminnoilla, kuten XSL-muunnoksella. Työnkulkutoimintoon tiivistetyn XSL-muunnoksen voi nyt käyttää uudelleen kaikki työnkulut, jotka käsittelevät XSL-muunnoksia.

Työnkulun johdotus

Toimitetussa sovellusliittymässä (ladattavissa resursseista) Spring ohjaa pientä pelaajajoukkoa olemaan vuorovaikutuksessa tavalla, joka muodostaa työnkulun. Tärkeimmät rajapinnat ovat:

  • Toiminta: Sisältää työnkulun yhden vaiheen liiketoimintalogiikan.
  • ProcessContext: Tyypin objektit ProcessContext siirretään työnkulun toimintojen välillä. Tämän käyttöliittymän toteuttavat objektit ovat vastuussa tilan ylläpidosta työnkulun siirtyessä toiminnasta toiseen.
  • ErrorHandler: Tarjoaa takaisinsoittomenetelmän virheiden käsittelemiseksi.
  • Suoritin: Kuvailee papua, joka toimii tärkeimmän työnkulkulangan toteuttajana.

Seuraava ote näytekoodista on Spring Bean -kokoonpano, joka sitoo lentoyhtiön esimerkin yksinkertaisena työnkulun prosessina.

             / property> org.iocworkflow.test.sequence.ratedrop.RateDropContext 

SequenceProcessor luokka on konkreettinen alaluokka, joka mallintaa sekvenssikuviota. Suorittimeen on kytketty viisi toimintoa, jotka työnkulun prosessori suorittaa järjestyksessä.

Verrattuna useimpiin menettelytapaprosesseihin työnkulun ratkaisu todella erottuu kykeneväksi erittäin vankkaan virheiden käsittelyyn. Virheenkäsittelijä voidaan kytkeä erikseen jokaiselle toiminnolle. Tämän tyyppinen käsittelijä tarjoaa tarkan virheenkäsittelyn yksittäisen toiminnan tasolla. Jos aktiviteettiin ei ole kytketty virhekäsittelijää, koko työnkulun prosessorille määritetty virhekäsittelijä hoitaa ongelman. Tässä esimerkissä, jos käsittelemätön virhe tapahtuu milloin tahansa työnkulkuprosessin aikana, se etenee, jotta ErrorHandler papu, joka on kytketty defaultErrorHandler omaisuus.

Monimutkaisemmat työnkulun kehykset jatkavat tilaa siirtymien väliseen datatallentimeen. Tässä artikkelissa olemme kiinnostuneita vain yksinkertaisista työnkulun tapauksista, joissa tilansiirto on automaattista. Osavaltiotiedot ovat käytettävissä vain ProcessContext varsinaisen työnkulun ajon aikana. Kun sinulla on vain kaksi menetelmää, voit nähdä ProcessContext käyttöliittymä on ruokavaliossa:

julkinen käyttöliittymä ProcessContext laajentaa Serializable {public boolean stopProcess (); public void setSeedData (Object seedObject); }

Betoni ProcessContext -luokka, jota käytetään lentoyhtiön esimerkkityönkulkuun, on RateDropContext luokassa. RateDropContext luokka kapseloi tiedot, jotka ovat tarpeen lentoyhtiön nopeuden pudotuksen työnkulun suorittamiseksi.

Tähän saakka kaikki pavutapaukset ovat olleet oletusarvoisesti yksinäisiä ApplicationContextkäyttäytymistä. Mutta meidän on luotava uusi ilmentymä RateDropContext luokka jokaiselle lentoyhtiön työnkulun kutsulle. Tämän vaatimuksen hoitamiseksi SequenceProcessor on määritetty ottamalla täysin pätevä luokan nimi processContextClass omaisuus. Jokaista työnkulun suoritusta varten SequenceProcessor noutaa uuden ProcessContext keväästä käyttäen määritettyä luokan nimeä. Jotta tämä toimisi, ei-yksinäinen kevätpapu tai prototyyppi tyypin org.iocworkflow.test.sequence.simple.SimpleContext on oltava olemassa ApplicationContext (katso rateDrop.xml koko listalle).

Työnkulun siirtäminen

Nyt kun tiedämme kuinka koota yksinkertainen työnkulku Springin avulla, keskitymme instantointiin siementietojen avulla. Jotta ymmärtäisimme, miten työnkulku voidaan siirtää, tarkastellaan menetelmiä, jotka ovat alttiina todelliselle Suoritin käyttöliittymä:

julkinen käyttöliittymä Suoritin {public boolean tukee (Aktiviteettitoiminta); public void doActivities (); public void doActivities (Object seedData); public void setActivities (Luettelotoiminnot); public void setDefaultErrorHandler (ErrorHandler defaultErrorHandler); }

Useimmissa tapauksissa työnkulkuprosessit edellyttävät joitain alkuvaiheen ärsykkeitä käynnistykseen. Suorittimen käynnistämiseen on kaksi vaihtoehtoa: doActivities (Object seedData) menetelmä tai sen perusteeton vaihtoehto. Seuraava koodiluettelo on doAcvtivities () täytäntöönpanoa SequenceProcessor sisältyy näytekoodiin:

 public void doActivities (Object seedData) {if (logger.isDebugEnabled ()) logger.debug (getBeanName () + "prosessori on käynnissä .."); // retrieve injected by Spring List activities = getActivities (); // hae uusi ilmentymä Workflow ProcessContext ProcessContext context = createContext (); if (seedData! = null) context.setSeedData (seedData); for (Iterator it = toiminnot.iterator (); it.hasNext ();) {Aktiviteettiaktiviteetti = (Aktiviteetti) it.sext (); if (logger.isDebugEnabled ()) logger.debug ("käynnissä oleva aktiviteetti:" + activity.getBeanName () + "argumenteilla:" + konteksti); kokeile {konteksti = aktiviteetti. suorita (konteksti); } catch (Throwable th) {ErrorHandler errorHandler = aktiviteetti.getErrorHandler (); if (errorHandler == null) {logger.info ("ei virhekäsittelijää tälle toiminnolle, suorita oletusvirhe" + "käsittelijä ja keskeytä käsittely"); getDefaultErrorHandler (). handleError (konteksti, th); tauko; } else {logger.info ("suorita virheenkäsittelijä ja jatka"); errorHandler.handleError (konteksti, th); }}