En guide til Activiti med Java

1. Oversikt

Activiti API er et arbeidsflyt- og forretningsprosessstyringssystem. Vi kan definere en prosess i den, utføre den og manipulere den på forskjellige måter ved hjelp av tjenestene som tilbys av API. Det krever JDK 7+.

Utvikling ved hjelp av API kan gjøres i hvilken som helst IDE, men for å bruke Activiti Designer trenger vi Eclipse.

Vi kan definere en prosess i den ved hjelp av BPMN 2.0-standarden. Det er en annen, mindre populær måte - å bruke Java-klasser som StartEvent, EndEvent, Brukeroppgave, SekvensFlyt, etc.

Hvis vi ønsker å kjøre en prosess eller få tilgang til noen av tjenestene, må vi opprette en ProcessEngineConfiguration.

Vi kan få ProcessEngine ved hjelp av ProcessEngineConfiguration, på noen måter, som vi vil diskutere videre i denne artikkelen. Gjennomde ProcessEngine vi kan utføre arbeidsflyt- og BPMN-operasjonene.

2. Maven-avhengigheter

For å bruke dette API-et, må vi inkludere Activiti-avhengigheten:

 org.activiti aktiviti-motor 

3. Opprette en ProcessEngine

ProcessEngine i Activiti, er vanligvis konfigurert ved hjelp av en XML-fil, activiti.cfg.xml. Et eksempel på denne konfigurasjonsfilen er:

Nå kan vi få tak i ProcessEngine bruker ProcessEngines klasse:

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine ();

Denne uttalelsen vil se etter en activiti.cfg.xml-fil i klassestien, og konstruer en ProcessEngine basert på konfigurasjonen i filen.

Eksempelkoden for konfigurasjonsfilen viser at den bare er en fjærbasert konfigurasjon. Men dette betyr ikke at vi bare kan bruke Activiti i et vårmiljø. Evnene til Spring blir bare brukt internt for å skape ProcessEngine.

La oss skrive en JUnit-testtilfelle som vil skape ProcessEngine ved hjelp av konfigurasjonsfilen vist ovenfor:

@Test offentlig ugyldig gittXMLConfig_whenGetDefault_thenGotProcessEngine () {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine (); assertNotNull (processEngine); assertEquals ("root", processEngine.getProcessEngineConfiguration () .getJdbcUsername ()); } 

4. Activiti Process Engine API og tjenester

Inngangspunktet for interaksjon med API er ProcessEngine. Gjennom Prosessmotor, vi har tilgang til forskjellige tjenester som tilbyr arbeidsflyt / BPMN-metoder. De ProcessEngine og alle serviceobjektene er trådsikre.

Hentet fra //www.activiti.org/userguide/images/api.services.png

De ProcessEngines klassen vil skanne etter activiti.cfg.xml og activiti-context.xml filer. Som nevnt tidligere, for alle activiti.cfg.xml filer, ProcessEngine vil bli opprettet på en typisk måte.

Mens for alle activiti-context.xml filer, blir den opprettet på vårveien - jeg oppretter vårapplikasjonskontekst og får tak i ProcessEngine fra det. Under gjennomføringen av en prosess vil alle trinnene besøkes i den rekkefølgen som er definert i BPMN-filen.

Under gjennomføringen av en prosess vil alle trinnene besøkes i den rekkefølgen som er definert i BPMN-filen.

4.1. Prosessdefinisjon og relaterte vilkår

EN Prosessdefinisjon representerer en forretningsprosess. Den brukes til å definere strukturen og oppførselen til forskjellige trinn i prosessen. Å distribuere en prosessdefinisjon betyr å laste prosessdefinisjonen i Activiti-databasen.

Prosessdefinisjoner er for det meste definert av BPMN 2.0-standarden. Det er også mulig å definere dem ved hjelp av Java-kode. Alle begrepene som er definert i denne delen er også tilgjengelige som Java-klasser.

Når vi begynner å kjøre en prosessdefinisjon, kan den refereres til som en prosess

EN ProcessInstance er en utførelse av en Prosessdefinisjon.

EN StartEvent er knyttet til enhver forretningsprosess. Det indikerer inngangspunktet for prosessen. Tilsvarende er det en EndEvent som indikerer slutten på prosessen. Vi kan definere forhold over disse hendelsene.

Alle trinnene (eller elementene) mellom start og slutt blir referert til som Oppgaver. Oppgaver kan være av forskjellige typer. De mest brukte oppgavene er Brukeroppgaver og Serviceoppgaver.

Brukeroppgaver, som navnet antyder, er slik at de må utføres manuelt av en bruker.

Serviceoppgaverderimot er konfigurert med et stykke kode. Hver gang utførelsen når dem, vil kodeblokken deres bli utført.

SekvensFlows koble til Oppgaver. Vi kan definere SekvensFlows av kilde- og målelementene de kobler sammen. Igjen kan vi også definere forhold over SekvensFlyter for å lage betingede stier i prosessen.

4.2. Tjenester

Vi vil kort diskutere tjenestene som tilbys av Activiti:

  • RepositoryService hjelper oss med å manipulere implementeringen av prosessdefinisjoner. Denne tjenesten omhandler statiske data relatert til en prosessdefinisjon
  • RuntimeService administrerer ProsessStoffer (for tiden kjører prosesser) samt prosessvariablene
  • TaskService holder styr på Brukeroppgaver. De Oppgaver som må utføres manuelt av en bruker, er kjernen i Activiti API. Vi kan opprette en oppgave, kreve og fullføre en oppgave, manipulere oppdragsgiver av oppgaven, etc. ved hjelp av denne tjenesten
  • FormService er en valgfri tjeneste. API-et kan brukes uten det, og uten å ofre noen av funksjonene. Den brukes til å definere startform og oppgaveskjema i en prosess.
  • IdentityService administrerer Brukere og Grupper
  • HistoryService holder oversikt over historien til Activiti Engine. Vi kan også angi forskjellige historienivåer.
  • ManagementService er relatert til metadataene og er vanligvis ikke nødvendig når du oppretter en applikasjon
  • DynamicBpmnService hjelper oss med å endre noe i en prosess uten å omplassere det

5. Arbeide med Activiti Services

For å lære hvordan vi kan jobbe med forskjellige tjenester og kjøre en prosess, la oss ta et eksempel på en prosess for "Ansattes ferieforespørsel":

BPMN 2.0-filen, VacationRequest.bpmn20.xml, for denne prosessen vil starthendelsen være definert som:

På samme måte vil den første brukeroppgaven, som er tildelt brukergruppen "ledelse", se slik ut:

 $ {ansatteName} vil ta $ {numberOfDays} dag (er) med ferie (motivasjon: $ {reason}). ledelse 

Med ServiceTask, vi må definere kodebiten som skal utføres. Vi har denne koden som en Java-klasse:

Betinget flyt vil bli vist ved å legge til “ConditionExpression” tag i “SequenceFlow”:

Her, ferieGodkjent er den formEiendom av Brukeroppgave Vist ovenfor.

Som vi kan se i diagrammet, er det en veldig enkel prosess. Arbeidstakeren fremsetter en ferieforespørsel med antall dager og startdatoen for ferien. Forespørselen går til lederen. De kan godkjenne / avvise forespørselen.

Hvis godkjent, er det definert en tjenesteoppgave for å sende bekreftelses-e-posten. Hvis det ikke er godkjent, kan den ansatte enten velge å endre og sende forespørselen på nytt, eller ikke gjøre noe.

Tjenesteoppgaver er utstyrt med noen kode å utføre (her, som en Java-klasse). Vi har gitt klassen SendEmailServiceTask.java.

Denne typen klasser bør utvide JavaDelegate. Vi må også overstyre dens henrette() metode, som vil bli utført når prosessutførelsen når dette trinnet.

5.1. Implementere en prosess

For å gjøre prosessen kjent for Activiti Engine, må vi distribuere prosessen. Vi kan gjøre det programmatisk ved hjelp av RepositoryService. La oss skrive en JUnit-test for å vise dette:

@Test offentlig ugyldig gittBPMN_whenDeployProcess_thenDeployed () {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine (); RepositoryService repositoryService = processEngine.getRepositoryService (); repositoryService.createDeployment () .addClasspathResource ("org / activiti / test / vacationRequest.bpmn20.xml") .deploy (); Langtall = repositoryService.createProcessDefinitionQuery (). Count (); assertEquals ("1", count.toString ()); }

Distribusjon betyr at motoren vil analysere BPMN-filen og konvertere den til noe kjørbart. Det vil også bli lagt til en post i repositorietabellen for hver distribusjon.

Derfor kan vi etterpå spørre om Oppbevaringssted service for å få de distribuerte prosessene; de Prosessdefinisjoner.

5.2. Starter en ProcessInstance

Etter å ha distribuert Prosessdefinisjon til Activiti Engine, kan vi utføre prosessen ved å opprette ProsessStoffer. De Prosessdefinisjon er en blåkopi, og ProcessInstance er kjøretidskjøringen av den.

For en singel Prosessdefinisjon, det kan være flere ProsessStoffer.

Alle detaljene knyttet til ProsessStoffer kan nås via RuntimeService.

I vårt eksempel, ved startbegivenheten, må vi passere antall feriedager, startdato og årsaken. Vi bruker prosessvariablene, og sender dem mens vi oppretter ProcessInstance.

La oss skrive en JUnit-testtilfelle for å få en bedre ide:

@Test offentlig ugyldighet givenDeployedProcess_whenStartProcessInstance_thenRunning () {// distribuere prosessdefinisjonen Kartvariabler = ny HashMap> (); variables.put ("ansattnavn", "John"); variables.put ("numberOfDays", 4); variables.put ("vacationMotivation", "Jeg trenger en pause!"); RuntimeService runtimeService = processEngine.getRuntimeService (); ProcessInstance processInstance = runtimeService .startProcessInstanceByKey ("vacationRequest", variabler); Langtall = runtimeService.createProcessInstanceQuery (). Count (); assertEquals ("1", count.toString ()); }

Flere forekomster av en enkelt prosessdefinisjon vil variere etter prosessvariablene.

Det er flere måter å starte en prosessforekomst på. Her bruker vi nøkkelen til prosessen. Etter å ha startet prosessforekomsten, kan vi få informasjonen om det ved å spørre RuntimeService.

5.3. Fullfører oppgaver

Når prosessforekomsten vår starter, er det første trinnet en brukeroppgave, tildelt brukergruppen "ledelse".

Brukeren kan ha en innboks som vil ha en liste over oppgaver som skal utføres av dem. Nå, hvis vi vil fortsette prosessutførelsen, må brukeren fullføre denne oppgaven. For Activiti Engine kalles det “fullføre oppgaven”.

Vi kan spørre om TaskService, for å hente oppgaveobjektet og deretter fullføre det.

Koden vi trenger å skrive for dette ser ut som:

@Test offentlig ugyldighet givenProcessInstance_whenCompleteTask_thenGotNextTask () {// distribuere prosess og start prosessforekomst TaskService taskService = processEngine.getTaskService (); Listeoppgaver = taskService.createTaskQuery () .taskCandidateGroup ("management"). List (); Oppgaveoppgave = oppgaver.get (0); Kart taskVariables = ny HashMap (); taskVariables.put ("vacationApproved", "false"); taskVariables.put ("comments", "We have a tight deadline!"); taskService.complete (task.getId (), taskVariables); Oppgave currentTask = taskService.createTaskQuery () .taskName ("Endre ferieforespørsel"). SingleResult (); assertNotNull (currentTask); }

Merk at fullstendig() Metode av TaskService tar også inn de nødvendige prosessvariablene. Vi gir svaret fra lederen.

Etter dette vil prosessmotoren fortsette til neste trinn. Her spør neste trinn den ansatte om ferieforespørselen skal sendes på nytt eller ikke.

Så, vår ProcessInstance venter nå på dette UserTask, som har navnet “Endre ferie be om".

5.4. Avbryte og aktivere en prosess

Vi kan suspendere a Prosessdefinisjon og også en ProcessInstance. Hvis vi suspenderer a ProsessDefinisjon, vi kan ikke opprette en forekomst av den mens den er suspendert. Vi kan gjøre dette ved hjelp av RepositoryService:

@Test (forventet = ActivitiException.class) offentlig ugyldig givenDeployedProcess_whenSuspend_thenNoProcessInstance () {// distribuere prosessdefinisjon repositoryService.suspendProcessDefinitionByKey ("vacationRequest"); runtimeService.startProcessInstanceByKey ("vacationRequest"); } 

For å aktivere den igjen, trenger vi bare å ringe en av repositoryService.activateProcessDefinitionXXX metoder.

På samme måte kan vi suspendere a ProsessInstans, bruker RuntimeService.

6. Konklusjon

I denne artikkelen så vi hvordan vi kunne bruke Activiti med Java. Vi laget et utvalg ProcessEngineCofiguration filen, som hjelper oss med å lage ProcessEngine.

Ved å bruke den fikk vi tilgang til forskjellige tjenester levert av API. Disse tjenestene hjelper oss med å administrere og holde styr på Prosessdefinisjoner, ProsessStoffer, Brukeroppgaver, etc.

Som alltid ligger koden for eksempler vi så i artikkelen på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found