Panduan Aktiviti dengan Java

1. Ikhtisar

Activiti API adalah alur kerja dan sistem Manajemen Proses Bisnis. Kita dapat mendefinisikan sebuah proses di dalamnya, menjalankannya, dan memanipulasinya dengan berbagai cara menggunakan layanan yang disediakan oleh API. Ini membutuhkan JDK 7+.

Pengembangan menggunakan API dapat dilakukan di IDE apa pun, tetapi untuk menggunakan Activiti Designer, kita membutuhkan Eclipse.

Kita bisa mendefinisikan proses di dalamnya dengan menggunakan standar BPMN 2.0. Ada cara lain yang kurang populer - menggunakan kelas Java seperti StartEvent , EndEvent , UserTask , SequenceFlow , dll.

Jika kita ingin menjalankan proses atau mengakses salah satu layanan, kita perlu membuat ProcessEngineConfiguration .

Kita bisa mendapatkan ProcessEngine menggunakan ProcessEngineConfiguration, dalam beberapa cara, yang akan kita bahas lebih lanjut di artikel ini . Melaluidi ProcessEngine kita dapat melakukan Workflow dan operasi BPMN.

2. Ketergantungan Maven

Untuk menggunakan API ini, kita perlu menyertakan dependensi Activiti:

 org.activiti activiti-engine 

3. Membuat ProcessEngine

ProcessEngine di Activiti, biasanya dikonfigurasi menggunakan file XML, activiti.cfg.xml . Contoh dari file konfigurasi ini adalah:

Sekarang kita bisa mendapatkan ProcessEngine menggunakan kelas ProcessEngines :

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

Pernyataan ini akan mencari sebuah activiti.cfg. xml di classpath, dan buat ProcessEngine berdasarkan konfigurasi di file tersebut.

Kode contoh untuk file konfigurasi menunjukkan bahwa ini hanyalah konfigurasi berbasis Spring. Namun, ini tidak berarti bahwa kita hanya dapat menggunakan Activiti di lingkungan Spring. Kemampuan Spring hanya digunakan secara internal untuk membuat ProcessEngine .

Mari kita tulis kasus uji JUnit yang akan membuat ProcessEngine menggunakan file konfigurasi yang ditunjukkan di atas:

@Test public void givenXMLConfig_whenGetDefault_thenGotProcessEngine() { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); assertNotNull(processEngine); assertEquals("root", processEngine.getProcessEngineConfiguration() .getJdbcUsername()); } 

4. API dan Layanan Activiti Process Engine

Titik masuk interaksi dengan API adalah ProcessEngine . Melalui ProcessEngine, kita dapat mengakses berbagai layanan yang menyediakan metode alur kerja / BPMN. The ProcessEngine dan semua benda layanan thread aman.

Diambil dari //www.activiti.org/userguide/images/api.services.png

Kelas ProcessEngines akan memindai file activiti.cfg.xml dan activiti-context.xml . Seperti disebutkan sebelumnya, untuk semua file activiti.cfg.xml , ProcessEngine akan dibuat dengan cara yang khas.

Sedangkan, untuk semua file activiti-context.xml , itu akan dibuat dengan cara Spring - Saya akan membuat Spring Application Context dan akan mendapatkan ProcessEngine dari situ. Selama menjalankan suatu proses, semua langkah akan dikunjungi dalam urutan yang ditentukan dalam file BPMN.

Selama menjalankan suatu proses, semua langkah akan dikunjungi dalam urutan yang ditentukan dalam file BPMN.

4.1. Definisi Proses dan Istilah Terkait

Sebuah ProcessDefinition merupakan proses bisnis. Ini digunakan untuk menentukan struktur dan perilaku dari berbagai langkah dalam proses. Menerapkan definisi proses berarti memuat definisi proses ke dalam database Activiti.

Definisi proses sebagian besar ditentukan oleh standar BPMN 2.0. Dimungkinkan juga untuk mendefinisikannya menggunakan kode Java. Semua istilah yang didefinisikan di bagian ini juga tersedia sebagai kelas Java.

Begitu kita mulai menjalankan definisi proses, ini bisa disebut sebagai proses

Sebuah ProcessInstance adalah salah satu pelaksanaan dari ProcessDefinition.

Sebuah StartEvent dikaitkan dengan setiap proses bisnis. Ini menunjukkan titik masuk proses. Demikian pula, ada EndEvent yang menunjukkan akhir dari proses tersebut. Kami dapat menentukan kondisi untuk acara ini.

Semua langkah (atau elemen) di antara awal dan akhir disebut sebagai Tugas . Tugas dapat terdiri dari berbagai jenis. Tugas yang paling sering digunakan adalah UserTasks dan ServiceTasks .

UserTasks , seperti namanya, sedemikian rupa sehingga perlu dilakukan secara manual oleh pengguna.

ServiceTasks , di sisi lain, dikonfigurasi dengan sepotong kode. Setiap kali eksekusi mencapai mereka, blok kode mereka akan dieksekusi.

SequenceFlows menghubungkan Tasks . Kita dapat mendefinisikan SequenceFlows berdasarkan elemen sumber dan target yang akan mereka hubungkan. Sekali lagi, kita juga bisa mendefinisikan kondisi di atas SequenceFlows untuk membuat jalur bersyarat dalam prosesnya.

4.2. Jasa

Kami akan membahas secara singkat layanan yang disediakan oleh Activiti:

  • RepositoryService membantu kami memanipulasi penerapan definisi proses. Layanan ini menangani data statis yang terkait dengan definisi proses
  • RuntimeService mengelola ProcessInstances ( proses yang sedang berjalan) serta variabel proses
  • TaskService melacak UserTasks . The Tugas yang perlu dilakukan secara manual oleh pengguna adalah inti dari API Activiti. Kita dapat membuat tugas, mengklaim dan menyelesaikan tugas, memanipulasi penerima tugas, dll. Menggunakan layanan ini
  • FormService adalah layanan opsional. API dapat digunakan tanpa itu, dan tanpa mengorbankan fiturnya. Ini digunakan untuk menentukan formulir awal dan formulir tugas dalam suatu proses.
  • IdentityService mengelola Pengguna dan Grup
  • HistoryService melacak sejarah Activiti Engine. Kami juga dapat mengatur level sejarah yang berbeda.
  • ManagementService terkait dengan metadata dan biasanya tidak diperlukan saat membuat aplikasi
  • DynamicBpmnService membantu kami mengubah apa pun dalam suatu proses tanpa menerapkannya kembali

5. Bekerja Dengan Layanan Activiti

Untuk mempelajari bagaimana kita dapat bekerja dengan berbagai layanan dan menjalankan proses, mari kita ambil contoh proses untuk "Permintaan liburan karyawan":

File BPMN 2.0, VacationRequest.bpmn20.xml , untuk proses ini akan memiliki acara awal yang ditetapkan sebagai:

Demikian pula, tugas pengguna pertama, yang ditetapkan ke "manajemen" grup pengguna, akan terlihat seperti ini:

 ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${reason}).       management   

Dengan ServiceTask, kita perlu menentukan bagian kode yang akan dieksekusi. Kami memiliki potongan kode ini sebagai kelas Java:

Alur bersyarat akan ditampilkan dengan menambahkan tag "conditionExpression" di "sequenceFlow":

Di sini, vacationApproved adalah formProperty dari UserTask yang ditampilkan di atas.

Seperti yang bisa kita lihat di diagram, ini adalah proses yang sangat sederhana. Karyawan tersebut membuat permintaan liburan, dengan mencantumkan jumlah hari dan tanggal mulai liburan. Permintaan tersebut pergi ke manajer. Mereka dapat menyetujui / menolak permintaan tersebut.

Jika disetujui, ada tugas Layanan yang ditentukan untuk mengirim email konfirmasi. Jika tidak disetujui, Karyawan dapat memilih untuk mengubah dan mengirim ulang permintaan, atau tidak melakukan apa pun.

Tugas layanan disediakan dengan beberapa bagian kode untuk dijalankan (di sini, sebagai kelas Java). Kami telah memberikan kelas SendEmailServiceTask.java.

These types of classes should extend the JavaDelegate. Also, we need to override its execute() method, which will be performed when the process execution reaches this step.

5.1. Deploying a Process

To make our process known to the Activiti Engine, we need to deploy the process. We can do it programmatically using the RepositoryService. Let's write a JUnit test to show this:

@Test public void givenBPMN_whenDeployProcess_thenDeployed() { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() .addClasspathResource( "org/activiti/test/vacationRequest.bpmn20.xml") .deploy(); Long count=repositoryService.createProcessDefinitionQuery().count(); assertEquals("1", count.toString()); }

Deployment means that the engine will parse the BPMN file and convert it into something executable. Also, a record will be added to the Repository table for every deployment.

Hence, afterward, we can query the Repository service to get the deployed processes; the ProcessDefinitions.

5.2. Starting a ProcessInstance

After deploying the ProcessDefinition to Activiti Engine, we can execute the process by creating ProcessInstances. The ProcessDefinition is a blueprint, and the ProcessInstance is the runtime execution of it.

For a single ProcessDefinition, there can be multiple ProcessInstances.

All the details related to the ProcessInstances can be accessed through the RuntimeService.

In our example, at the start event, we need to pass the number of vacation days, the start date, and the reason. We will use the process variables, and pass them while creating the ProcessInstance.

Let's write a JUnit test case to get a better idea:

@Test public void givenDeployedProcess_whenStartProcessInstance_thenRunning() { //deploy the process definition Map variables = new HashMap>(); variables.put("employeeName", "John"); variables.put("numberOfDays", 4); variables.put("vacationMotivation", "I need a break!"); RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService .startProcessInstanceByKey("vacationRequest", variables); Long count=runtimeService.createProcessInstanceQuery().count(); assertEquals("1", count.toString()); }

The multiple instances of a single process definition will differ by the process variables.

There are multiple ways to start a process instance. Here, we are using the key of the process. After starting the process instance, we can get the information about it by querying the RuntimeService.

5.3. Completing Tasks

When our process instance starts running, the first step is a user task, assigned to the user group “management”.

The user might have an inbox that would have a list of tasks to be done by them. Now, if we want to continue the process execution, the user needs to finish this task. For Activiti Engine, it's called “completing the task”.

We can query the TaskService, to get the task object and then complete it.

The code we need to write for this looks like:

@Test public void givenProcessInstance_whenCompleteTask_thenGotNextTask() { // deploy process and start process instance TaskService taskService = processEngine.getTaskService(); List tasks = taskService.createTaskQuery() .taskCandidateGroup("management").list(); Task task = tasks.get(0); Map taskVariables = new HashMap(); taskVariables.put("vacationApproved", "false"); taskVariables.put("comments", "We have a tight deadline!"); taskService.complete(task.getId(), taskVariables); Task currentTask = taskService.createTaskQuery() .taskName("Modify vacation request").singleResult(); assertNotNull(currentTask); }

Note that the complete() method of TaskService also takes in the required process variables. We pass in the reply from the manager.

After this, the process engine will continue to the next step. Here, the next step asks the employee if the vacation request is to be re-sent or not.

So, our ProcessInstance is now waiting at this UserTask, which has the name “Modify vacation request”.

5.4. Suspending and Activating a Process

We can suspend a ProcessDefinition and also a ProcessInstance. If we suspend a ProcessDefinition, we cannot create an instance of it while it is suspended. We can do this using the RepositoryService:

@Test(expected = ActivitiException.class) public void givenDeployedProcess_whenSuspend_thenNoProcessInstance() { // deploy the process definition repositoryService.suspendProcessDefinitionByKey("vacationRequest"); runtimeService.startProcessInstanceByKey("vacationRequest"); } 

Untuk mengaktifkannya lagi, kita hanya perlu memanggil salah satu metode repositoryService.activateProcessDefinitionXXX .

Demikian pula, kita bisa menangguhkan ProcessInstance, menggunakan RuntimeService.

6. Kesimpulan

Di artikel ini, kami melihat bagaimana kami dapat menggunakan Activiti dengan Java. Kami membuat contoh file ProcessEngineCofiguration , yang membantu kami membuat ProcessEngine .

Dengan menggunakannya, kami mengakses berbagai layanan yang disediakan oleh API. Layanan ini membantu kita untuk mengelola dan melacak ProcessDefinitions , ProcessInstances , UserTasks , dll

Seperti biasa, kode untuk contoh yang kami lihat di artikel terletak di GitHub.