Instytut Systemów Informatycznych, Wydział Cybernetyki, Wojskowa Akademia Techniczna
Paweł Mieteń, Jarosław Koszela
W dzisiejszych czasach jedną z podstawowych funkcji każdego oprogramowania jest możliwość integracji z systemami zewnętrznymi. BizAgi studio jest narzędziem, które posiada mechanizmy integracyjne. Po pierwsze posiada API w postaci WebService, które pozwala zdalnie koordynować proces oraz daje możliwość manipulowania danymi. Z drugiej strony aplikacja stworzona w BizAgi Studio pozwala wywoływać metody z zewnętrznych WebService’ów lub pozwala synchronizować dane z zewnętrznymi bazami danych.
W celu stworzenia interakcji tworzonego procesu z systemem zewnętrznym zbudujemy namiastkę serwisu internetowego. Przyjmiemy, że aplikacja ta będzie dostarczała procesowi informacji o studencie oraz w aplikacji tej będzie możliwość potwierdzenia wpłaty pieniędzy przez studenta.
Na zadaniu „Pobranie informacji o studencie” BizAgi odwoła się do wystawionego serwisu i pobierze ilość punktów ECTS studenta. Kolejnym punktem interakcji będzie wpłata pieniędzy. BizAgi po uaktywnieniu zdarzenia „Wpłynięcie pieniędzy” wyśle do serwisu zewnętrznego komunikat, że oczekuje na potwierdzenie wpłaty. W systemie internetowym zostanie zapisana informacja o oczekującym zdarzeniu, oraz zostanie zaimplementowana możliwość potwierdzenia wpłaty. Tym razem to aplikacja zewnętrzna wywoła odpowiednią metodę na WebSerwice systemu workflow, tak aby zdalnie wywołać zdarzenie przejścia na kolejny krok procesu.
Do stworzenia aplikacji internetowej użyjemy technologii ASP.NET. Będziemy posługiwać się Microsoft Visual Studio 2010 oraz bazą danych MS SQL.
Rysunek . Utworzenie nowego projektu
W celu utworzenia nowego projektu wybieramy opcję File->New->Project… .
Rysunek . Wybranei typu projektu
Naszym oczom pokaże się okno gdzie będziemy mogli wybrać typ projektu, nadać mu nazwę oraz wskazać lokalizację. Wybieramy ASP. NET Web Application, nazwę wpiszmy TutorialBizAgi.ExternalSystem oraz zostawmy domyślną lokalizację. W celu potwierdzenia wciskamy przycisk OK.
VS(Visual Studio) utworzy nam domyślny szkielet aplikacji.
Po prawej stronie mamy okienko o nazwie Solution Explorer, gdzie możemy przejrzeć aktualne pliki projektu.
Rysunek . Konfiguracja serwera do uruchamiania aplikacji
Do uruchamiania aplikacji możemy użyć serwera deweloperskiego, w tym celu na solution należy wybrać opcję właściwości(properties) i w zakładce Web zaznaczyć opcję „Use Visual Studio Development Server” oraz „Specific port”, co spowoduje, że nasz aplikacja za każdym razem będzie uruchamiała się na tym samym porcie. Jest to konieczne, ponieważ w BizAgi Studio musimy podać adres serwera, a więc nie może on się zmieniać. Po wprowadzeni zmian należy wcisnąć Carl+S, co zapisze ustawienia.
W celu odpalenia aplikacji należy wcisnąć Ctrl+F5, Visual Studio automatycznie odpali serwer deweloperski pod zdefiniowanym portem oraz otworzy przeglądarkę internetową (http://localhost:53229/).
Kolejnym krokiem jest utworzenie projektu, który będzie pełnił funkcję warstwy dostępu do danych. W tym celu w oknie Solution Explorer na węźle Solution wybieramy opcję Add->New Project… .
Rysunek . Dodanie nowego projektu do Solution
Rysunek . Wybranie typu projektu
Z listy projektów wybieramy Class Library oraz nadajemy nazwę TutorialBizAgi.ExternalSystem.Entities.
Warstwę dostępu do danych zrealizujemy wykorzystując bibliotekę ORM Entity Framework.
Rysunek . Dodanie modelu danych
W tym celu do nowo utworzonego projektu dodajemy element ADO.NET Entity Data Model nadając mu nazwę Model. VS uruchomi kreator tworzenia modelu.
Rysunek . Kreator tworzenia modelu danych
Entity Framework daje nam możliwość automatycznego utworzenia modelu na podstawie istniejącej bazy danych. Drugą możliwością jest utworzenie pustego modelu, ręczne zbudowanie struktury danych oraz wygenerowanie bazy danych na podstawie modelu. To drugie podejście nazywa się Model First i niego właśnie skorzystamy, a więc wybieramy opcję Empty model i wciskamy guzik Finish.
DO przechowywania danych będziemy używać bazy danych MS SQL Server. Aby wygenerować strukturę bazy danych musimy, uprzednio utworzyć pustą bazę na SQL serwerze. W tym celu otwórzmy okno Server Explorer(Główne menu VS->View->Server Explorer).
Rysunek . Solution Explorer - Utworzenie nowej bazy danych
Na węźle Data Connections wybieramy opcję Create New SQL Server Database… .
Rysunek . Konfiguracja połączenia oraz nadanie nazwy dla bazy
Należy wskazać instancje SQL Serwera oraz podać sposób logowania. W moim przypadku SQL Serwer, który będzie używany jest instancją domyślną więc wystarczy że podam nazwę MOJEGO komputera(WDEVPMI). Wybieram opcję autentykacji Windows Authentication oraz wpisuję nazwę bazy danych TutorialBizAgiDB. Po stworzeniu pustej bazy danych przystąpmy do zamodelowania struktury danych. Należy otworzyć plik Model.edmx, VS otworzy go w narzędziu do modelowania.
Rysunek . Model struktury danych
Na nasze potrzeby dodamy do modelu encję student gdzie będzie przechowywana informacja o ilości punktów ECTS. Do studenta będzie przypisana dowolna ilość opłat. Dodatkowo dodamy encję przedmiot, gdzie będzie lista przedmiotów, na które student będzie mógł zdawać ponownie. Tabela ta będzie podłączona do systemu work flow.
Rysunek . Generacja skryptów tworzących bazę danych
Po zamodelowaniu struktury danych korzystając z menu kontekstowego wybieramy opcję „Generate Database from Model”.
Rysunek . Wybieranie połączenia do bazy danych
Kreator tworzenia skryptu tworzącego poprosi o wybranie połączenia do bazy danych. Wybieramy uprzednio stworzoną bazę oraz zaznaczamy opcję „Save entity connection setting In App.Config as”.
Rysunek . Podgląd wygenerowanego skryptu
W ostatnim kroku podajemy nazwę pliku, do którego zostanie zapisany skrypt DLL. NA tym samym oknie istnieje możliwość zweryfikowania otrzymanego rezultatu. Po wciśnięciu przycisku Finish skrypt zostanie zapisany, a plik zostanie otwarty w VS.
Rysunek . Uruchomienie skryptu DLL
Używając menu kontekstowego i opcji „Execute SQL”, należy uruchomić skrypt.
Rysunek . Łączenie do bazy danych
W oknie należy podać nazwę serwera oraz dane dostępu. Po wciśnięciu przycisku Connect zostanie nawiązane połączenie oraz wykonany skrypt tworzący bazę danych.
Rysunek . Definicja połączenia do bazy danych
W projekcie Entities można znaleźć plik App.Config, w którym będzie zdefiniowane połączenie do bazy danych. Aby nasza aplikacja również używała takich danych konfiguracyjnych należy je skopiować do apliku Web.Coinfig w głównym projekcie.
Po przygotowaniu projektu pełniącego funkcję warstwy bazy danych, należy dołączyć go do projektu głównego. Takie połączenie nazywa się referencją.
Rysunek . Dodanie referencji
W celu dodania referencji należy wybrać opcję „Add Reference” z menu kontekstowego na węźle References.
Rysunek . Dodawanie referencji do projektu
Po uruchomieniu okna z dostępnymi elementami należy wybrać zakładkę Projects oraz wskazać projekt Entities i zatwierdzić przyciskiem OK.
Rysunek . Dodanie referencji do biblioteki DLL
.Net Fremework jest zbiorem bibliotek. Aby w projekcie głównym móc skorzystać z Entity Framework’a należy dodać referencje do biblioteki System.Data.Entity. W tym celu na oknie wyboru referencji należy przejść na zakładkę .NET i wybrać odpowiednią bibliotekę.
Nasza aplikacja musi dać możliwość zdalnego uruchamiania metod, tak aby workflow mógł komunikować się z nią. W tym celu zastosujemy technologii WebServices, która za pomocą protokołu komunikacyjnego http pozwala wywoływać zdalnie metody. Jest to metoda uniwersalna, mająca wsparcie praktycznie w każdym liczącym się środowisku programistyczny.
Rysunek . Dodanie nowego elementu do projektu
Do projektu dodamy WebService, w tym celu na głównym węźle projektu posługując się menu kontekstowym wybieramy opcję Add->New Item… .
Rysunek .Wybór typu elementu
Wybieramy typ elementu Web Service, nadajemy mu nazwę WebService i potwierdzamy wciskając przycisk Add. Do projektu doda się plik o nazwie WebService.asmx. Klikając dwukrotnie otworzymy plik implementujący metody web serwisu. Dodamy do niego następujące dwie metody:
[WebMethod]
public int PobierzPunktyEcts(int numerIndeksu)
{
int? punktyEcts = null;
using (Entities.ModelContainer dbContext = new Entities.ModelContainer())
{
punktyEcts = dbContext.Studenci.Where(s => s.NumerIndeksu == numerIndeksu)
.Select(s => (int?)s.PunktyEcts).FirstOrDefault();
if (!punktyEcts.HasValue)
{
throw new Exception("Nie istnieje student o podanym numerze indeksu");
}
}
return punktyEcts.Value;
}
[WebMethod]
public void DodajNowaOplate(int caseId, int numerIndeksu)
{
using (Entities.ModelContainer dbContext = new Entities.ModelContainer())
{
var student = dbContext.Studenci.Where(s => s.NumerIndeksu == numerIndeksu)
.FirstOrDefault();
if (student == null)
{
throw new Exception("Nie istnieje student o podanym numerze indeksu");
}
var oplata = new Entities.Oplata();
oplata.CaseId = caseId;
oplata.Student = student;
dbContext.SaveChanges();
}
}
Metoda o nazwie PobierzPunktyEcts pobierze na wejściu numer indeksu studenta i zwróci jego punkty ECTS. W przypadku jeśli w bazie danych nie zostanie znaleziony student o zadanym numerze indeksu zostanie wyrzucony wyjątek.
Jeśli w procesie składania wniosku workflow uaktywni zdarzenie pośrednie „Wpłynięcie pieniędzy” to w naszym systemie odpali się metoda DodajNowaOplate z numerem indeksu studenta oraz z identyfikatorem tego kroku procesu. Metoda doda do bazy danych nową opłatę przypisując do niej przekazany identyfikator. Jest to potrzebne ze względu, na to że z poziomu strony damy możliwość „odpalenia” tego zdarzenia. Dzięki identyfikatorowi workflow będzie jednoznacznie wiedział, o które zdarzenie nam chodzi.
W powyższych metodach użyliśmy LINQ i Entity Framework w celu odczytu i zapisanie danych do bazy.
Kolejnym krokiem jest stworzenie interfejsu użytkownika i metody, która pozwoli uruchomić zdarzenie pośrednie „Wpłynięcie pieniędzy” z poziomu naszej aplikacji zewnętrznej.
Rysunek . Interfejs potwierdzania wpłat
Na interfejsie użytkownika w liście rozwijanej będzie można wybrać wpłatę do potwierdzenia a następnie za pomocą przycisku „Potwierdź wpłatę” wyślemy do workflow odpowiedni komunikat, który uruchomi zdarzenie. Aby utworzyć taki interfejs otwórz plik Default.aspx i przełącz go w tryb Design, używając przycisku w lewym dolnym rogu okna.
Rysunek . Tryb Design i okno ToolBox
Korzystając z metody drag and drop, przenieś element Button i DropDownList z okna Toolbox na okno główne. Korzystając z menu kontekstowego wyświetl właściwości listy rozwijanej i zmieniamy jej nazwę na Wplaty. W drugiej kolejności otwieramy właściwości przycisku i zmień tekst wyświetlany na „Potwierdź wpłatę”. Następnie kliknij dwukrotnie na przycisk. VS automatycznie utworzy zdarzenie dla przycisku oraz otworzy kodem strony. W kodzie strony zaimplementuj następujące dwie metody:
protected void Button1_Click(object sender, EventArgs e)
{
using (Entities.ModelContainer dbContext = new Entities.ModelContainer())
{
int oplataId = int.Parse(Wplaty.SelectedValue);
var oplata = dbContext.Oplaty.Where(o => o.Id == oplataId)
.FirstOrDefault();
string sXml = "<BizAgiWSParam>";
sXml += "<ActivityData>";
sXml += "<idCase>" + oplata.CaseId + "</idCase>";
sXml += "<taskName>WpYniCiePieniDzy</taskName>";
sXml += "</ActivityData>";
sXml += "</BizAgiWSParam>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(sXml);
WorkflowEngineSOA.WorkflowEngineSOA ws = new WorkflowEngineSOA.WorkflowEngineSOA();
XmlNode xn = ws.performActivity(xDoc);
var t = xn.SelectSingleNode("process/processError/errorMessage");
oplata.CzyDokonana = true;
dbContext.SaveChanges();
}
}
protected override void OnPreRender(EventArgs e)
{
using (Entities.ModelContainer dbContext = new Entities.ModelContainer())
{
Wplaty.DataSource = dbContext.Oplaty
.Where(o => o.CzyDokonana == false)
.Select(o => new
{
Opis = o.Student.Imie + " " + o.Student.Nazwisko + " - CaseID: " + SqlFunctions.StringConvert((decimal)o.CaseId),
Id = o.Id
}).ToList();
Wplaty.DataBind();
}
}
Metoda Button1_Click to automatycznie wygenerowane zdarzenie, w którym odwołamy się do workflow. W tym celu do naszej aplikacji musimy dodać Web Referencje do WebSerwisu który jest wystawiany przez workflow. Na głównym projekcie z menu kontekstowego wybieramy opcję „Add Web Reference…”.
Rysunek . Dodawanie referencji do usługi sieciowej
W pole URL wpisujemy adres serwisu naszego workflowa (http://localhost:1024/TutorialBizAgi/webservices/WorkflowEngineSOA.asmx) i wciskamy zieloną strzałkę. VS wyświetli listę dostępnych metod. W polu „Web reference name” wpisujemy WorkflowEngineSOA i wciskamy przycisk “Add Reference”.
Rysunek . Podgląd dodanych referencji do usług sieciowych
Powracając do implementacji metody Button1_Click, możemy zobaczyć tam przykład skorzystania z dodanej usługi.
Drugą metodą w kodzie strony jest OnPreRender, w której jest zaimplementowane dodanie opłat do listy rozwijanej. Jest to nadpisanie metody z klasy bazowej, która to metoda jest zawsze odpalana przy wyświetlaniu strony.