Blog PeTe

jBPM – pierwsze kroki cz. 3 29.10.2008

Zaszufladkowany do: IT, Programowanie — PeTe @ 22:17
Tags: , , ,

Kontynuuję cykl artykułów dotyczących jBPM.

W poprzednim artykule stworzyliśmy widok pokazujący wszystkie dostępne procesy biznesowe. Nadszedł czas aby spróbować uruchomić prosty proces.

Na początku utworzymy akcję, która stworzy instancję wybranego procesu biznesowego. W tym celu w edytorze pliku plugin.xml dodajemy koleją akcję do utworzonego wcześniej rozszerzenia org.eclipse.ui.actionSets. Wypełniamy atrybuty akcji podobnie jak w poprzednich akcjach, w polach id i class wpisujemy jbpm.actions.RunBPAction.

Aby nasza akcja mogła uzyskać informację jaki proces z listy procesów wybrał użytkownik, uzupełniamy metodę createPartControl klasy ProcessesViewer o linijkę ustawiającą nasz viewer jako dostawcę selekcji:

getSite().setSelectionProvider(viewer);

Następnie zadbajmy o to, aby nasza akcja była dostępna tylko wówczas, jeśli zaznaczono jeden element typu ProcessDefinition oraz żeby definicja wybranego procesu znajdowała się w naszej akcji w prywatnym polu:

private ProcessDefinition selectedDefinition;.

Aby to uzyskać w metodzie selectionChanged naszej akcji umieszczamy następujący kod:

if (!selection.isEmpty() && selection instanceof StructuredSelection && ((StructuredSelection) selection).size() == 1 && ((StructuredSelection) selection).getFirstElement() instanceof ProcessDefinition) {
  action.setEnabled(true);
  selectedDefinition = (ProcessDefinition) ((StructuredSelection) selection).getFirstElement();
} else {
  action.setEnabled(false);
}

Teraz już możemy utworzyć instancję wybranego procesu oraz wreszcie go uruchomić. W metodzie run naszej akcji dodajmy:

ProcessInstance processInstance = selectedDefinition.createProcessInstance();
Token token = processInstance.getRootToken();
while (!token.hasEnded()) {
  System.out.println(token.getNode().getName());
  token.signal();
}

Wypróbujmy działanie na dowolnym procesie i zabierzmy się wreszcie za tworzenie i obsługę bardziej skomplikowanej aplikacji.

Utwórzmy nowy proces biznesowy i na jego podstawie rozwiniemy naszą aplikację o kolejne niezbędne elementy:

<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" name="first-process">
 <start-state name="start">
  <transition to="co-dalej"></transition>
 </start-state>
 <decision name="co-dalej">
  <handler class="jbpm.handlers.MyDecisionHandler"></handler>
  <transition to="cos-jeszcze" name="jeszcze cos"></transition>
 <transition to="end" name="konczymy"></transition>
 </decision>
 <task-node name="cos-jeszcze">
  <task name="komunikat" description="testowy komunikat">
   <assignment class="jbpm.handlers.MyAssignmentHandler" />
  </task>
  <transition to="end"></transition>
 </task-node>
 <end-state name="end"></end-state>
</process-definition>

Jak widać nasz prosty proces rozpoczyna się decyzją co robić dalej, którą obsługiwać ma klasa MyDecisionHandler. Następnie w zależności od dokonanego wyboru kończy działanie lub wykonuje dodatkowe zadanie.

Aby obsłużyć element decyzyjny stwórzmy klasę MyDecisionHandler. Będzie ona implementować interfejs org.jbpm.graph.node.DecisionHandler:

public class MyDecisionHandler implements DecisionHandler {
 public String decide(ExecutionContext ec) throws Exception {
  final List<Transition> listaOdpowiedzi = ec.getNode().getLeavingTransitionsList();
  Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
  Dialog dialog = new Dialog(shell) {
   protected void createButtonsForButtonBar(Composite parent) {
    int i =0;
    for (Iterator<Transition> iterator = listaOdpowiedzi.iterator(); iterator.hasNext();) {
     Transition tr = iterator.next();
     createButton(parent, i, tr.getName(), false);
     i++;
    }
   }
   protected void buttonPressed(int buttonId) {
    setReturnCode(buttonId);
    close();
   }
  };
  int odpowiedz = dialog.open();
  MessageDialog.openInformation(shell, "Jbpm Plug-in", "wybrałeś " +listaOdpowiedzi.get(odpowiedz).getName());
  return listaOdpowiedzi.get(odpowiedz).getName();
 }
}

Klasa pobiera listę możliwych odpowiedzi i tworzy dialog zawierający przyciski odpowiadające kolejnym możliwym ścieżkom procesu. Jak widzimy w kodzie aplikacji nie podajemy, jaka implementacja interfejsu org.jbpm.graph.node.DecisionHandler ma zostać użyta, wszystko zostało określone w definicji procesu. Jest to jedna z ważniejszych cech programowania zorientowanego na grafy.

Stwórzmy teraz klasę MyAssignmentHandler, która obsłuży nasze dodatkowe zadanie. Zadanie to będzie polegało na wyświetleniu komunikatu zawierającego w treści opis (description) zadania. Klasa MyAssignmentHandler będzie implementować interfejs org.jbpm.taskmgmt.def.AssignmentHandler:

public class MyAssignmentHandler implements AssignmentHandler {
 public void assign(Assignable assignable, ExecutionContext ec) throws Exception {
  Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
  MessageDialog.openInformation(shell, ec.getTask().getName(), ec.getTask().getDescription());
 }
}

W ten sposób stworzyliśmy kod niezbędny do obsłużenia całego zdefiniowanego wcześniej procesu. Widzimy, że jeśli stworzymy odpowiednią ilość kontrolek obsługujących wymagane akcje i interakcje z użytkownikiem, będziemy mogli programować procesy biznesowe przy pomocy grafów jBPM, bez linijki kodu w Javie.

Opisane tu rzeczy są tylko drobnym wycinkiem możliwości środowiska jBPM. Środowisko to jest naprawdę bogate, dobrze przemyślane i rozszerzalne. Wszystkich, których temat zainteresował odsyłam do dokumentacji projektu i własnych testów.

 

Leave a Reply