7 maja 2009

Proces dostarczenia usług w architekturze SOA

Model funkcjonowania działów IT w firmach, widziany z lotu ptaka, jest dosyć prosty. IT pełni rolę czysto służebną, tj. ma za zadanie dostarczać rozwiązania informatyczne zaspokajające pewne potrzeby, tudzież kaprysy osób odpowiedzialnych za rozwój biznesu. Przedstawiciel biznesu zgłasza więc do działu IT zapotrzebowanie na nowe oprogramowanie wraz z szeregiem wymagań, które odnoszą się do tego, jak dana aplikacja ma wyglądać i funkcjonować i tym samym uruchamia odpowiedni proces analizy. Przeważnie wybrany zostanie ktoś odpowiedzialny za realizacje tych wymagań, tj. kierownik projektu. Jeśli realizowana aplikacja nie jest trywialna to z pewnością będzie ona wymagała interakcji z istniejącymi w firmie systemami, czy to finansowymi, sprzedażowymi, magazynowymi czy jakimikolwiek jeszcze innymi. W organizacji opartej na architekturze zorientowanej na usługi (tj. SOA) powinno się dążyć do tego, aby osoba odpowiedzialna za realizację zadania zdefiniowanego przez biznes mogła się skupić na tymże, komunikując światu zewnętrznemu – z którym realizowana aplikacja potrzebuje się komunikować – jedynie pewne niezbędne minimum, tj. czego ona od tego świata zewnętrznego chce. A chce ona od niego, aby wykonał na żądanie pewne określone zadania, tj. mówiąc innym językiem, aby udostępnił pewne usługi. Z punktu widzenia wspomnianego kierownika projektu szczególnie korzystne byłoby, gdyby mógł się on ograniczyć do sporządzenia listy usług, które muszą mu być dostarczone przez systemy zewnętrzne dla umożliwienia realizacji jego zadania. Lista ta staje się punktem wyjścia do uruchomienia nowego procesu zarządzania (ang. governance) architekturą SOA – procesu dostarczenia usług.

Proces dostarczenia usług składa się z kilku zasadniczych kroków. W pierwszym kroku zespół który ma za zadanie dostarczyć usługi przeprowadza wstępną analizę wymagań klienta – klient występuje tu w rozumieniu osoby która zgłasza zapotrzebowanie na usługi. Mając nakreślony w sposób ogólny wymagany zakres funkcjonalny i informacyjny dla każdej usługi należy ustalić, czy usługa o podobnym zakresie funkcjonalnym już istnieje, czy jest to usługa zupełnie nowa. Należy tutaj podkreślić, że osoby odpowiedzialne za dostarczenie usługi powinny podjąć wysiłek nakierowania żądań swego klienta na właściwe tory, jeśli stawiane przez niego wymagania nie wpisują się w dotychczas znane i realizowane schematy. Może zdarzyć się bowiem, że dekompozycja funkcjonalności aplikacji na usługi została wykonana nie prawidłowo i wymagana jest korekta. W szczególności, może zdarzyć się, że istnieje usługa o odpowiednim znaczeniu funkcjonalnym ale posługująca się innym zakresem informacyjnym. Jest to wyraźny sygnał, że należy podjąć wysiłek uspójnienia procesów biznesowych i używanego modelu danych. Należy pamiętać o tym, że usługi powinny odpowiadać pewnym operacjom mającym sens z punktu widzenia prowadzonego biznesu i należy dbać o utrzymanie spójności znaczeniowej usług z funkcjami biznesowymi.

Proces analizy – analizy prowadzącej do porozumienia obydwu stron, tj. klienta i dostawcy usług – nakreślony w powyższym akapicie koniec końców prowadzi do ustalenia się pewnej listy usług, z pośród usług istniejących, które mogą być użyte bez zmian, listy usług które są na tyle podobne, że wymagają jedynie pewnego dostosowania oraz listy usług zupełnie nowych, które muszą być zaimplementowane od podstaw. Usługi powinny być implementowane w oparciu o technologie które ściśle separują specyfikację usługi od jej implementacji; wymóg ten spełniają usługi sieciowe oparte o standardy SOAP i WSDL. Umożliwia to i promuje podział procesu wykonania usługi na fazę opracowania interfejsu i fazę implementacji. Dostawca usług w pierwszej fazie tworzy i przedstawia do akceptacji klientowi kontrakt usługi w postaci pliku WSDL a dopiero potem przechodzi do implementacji. Możliwość ustalenia interfejsu przed wykonaniem usługi ma ogromne znaczenie dla skrócenia czasu implementacji całego rozwiązania – zespół implementujący aplikację nie musi bowiem oczekiwać ze swoimi pracami na wykonanie całości pracy przez dostawcę usług. Aplikacja kliencka może być w pełni zaimplementowana nawet przed dostarczeniem implementacji tych usług. Warunkiem niezbędnym dla prawidłowej realizacji procesu jest jak widać postawienie definicji usługi, wyrażonej jako dokument WSDL, ponad jej konkretną implementację, która jest rzeczą wtórną. Co prawda dla programisty implementującego usługi na platformie Java EE (i innych analogicznych) kuszącym jest, aby pracę zacząć od implementacji usługi i na jej podstawie w sposób automatyczny wygenerować plik WSDL (obecna technologia sprawia że jest to łatwe), jednak jest to podejście nie celowe z globalnego punktu widzenia.

Podejście w którym zaczyna się od wytworzenia definicji WSDL – w przeciwieństwie do podejścia w którym na podstawie implementacji pliki WSDL generuje się automatycznie – ma szereg zalet. Specyfikacje w postaci dokumentów WSDL mogą być wykorzystane jako element kontraktu pomiędzy dostawcą a klientem tam gdzie zachodzi potrzeba utrzymywania stosunków formalnych, tj. otrzymania formalnej akceptacji projektu usług przed rozpoczęciem fazy realizacji. Kolejnym powodem dla którego warto w pierwszej kolejności opracować definicję usługi w postaci pliku WSDL jest możliwość przygotowywania testów usług równolegle z ich implementacją, na podstawie samego WSDLa. Warto taki tryb pracy uczynić standardem, niezależnie od niuansów i specyfik poszczególnych projektów. Korzyści staną się jeszcze większe i bardziej widoczne, jeśli pliki WSDL budowane będą w oparciu o globalne, kanoniczne typy danych.

W artykule „JAX-WS i Maven 2 w podejściu Contract First Development” opisałem w jaki sposób implementować usługi w takim podejściu z wykorzystaniem technologii oferowanych przez platformę Java EE 5.

21 kwietnia 2009

Oracle kupuje Sun Microsystems

Producent baz danych Oracle kupuje firmę Sun Microsystems! Wartość transakcji to około 7,4 mld USD. Tym samym Oracle przejmuje wszystkie prawa do języka programowania Java, bazy danych MySQL, systemu operacyjnego Solaris oraz pakietu biurowego OpenOffice. Się porobiło. Ciekawe czy i jak wpłynie to na nasze, developerów życie.

10 kwietnia 2009

SCJP - Tokenizacja tekstu

Tokenizacja to proces w wyniku którego monolityczny tekst zostaje podzielony na ciąg pojedynczych tokenów. Tokeny to ciągi znaków ograniczone ustalonymi separatorami takimi jak spacje czy przecinki, aczkolwiek separatorem może być dowolny ciąg który da się opisać w postaci wyrażenia regularnego. Najbardziej elementarny algorytm tokenizacji w Javie implementuje metoda split(…) z klasy String. Metoda ta dokonuje podziału tekstu reprezentowanego przez obiekt dla którego została wywołana używając separatora opisanego wyrażeniem regularnym przekazanym jako argument wywołania. Przykład poniżej:
public void tokenize() {
String[] tokens = "dowolny tekst do tokenizacji".split("\\s");

for(String token : tokens)
System.out.println(token);
}

Wyrażenie regularne \s (które musimy zapisać jako \\s) oznacza biały znak (ang. whitespace character), tj. spacje, tabulacje, znaki nowej linii itd. Uruchomienie powyższej metody spowoduje więc wyświetlenie napisu:
dowolny
tekst
do
tokenizacji

Bardziej wyrafinowanych mechanizmów tokenizacji dostarcza klasa Scanner z pakietu java.util. Zasadnicza różnica w stosunku do metody split(…) polega na tym, że tokenizowany tekst jest przetwarzany stopniowo, w miarę potrzeby, i proces może być w dowolnej chwili zaniechany. Skanerem posługujemy się jak iteratorem. Klasa Scanner implementuje interfejs java.util.Iterator więc de facto jest ona iteratorem; pewnym szczególnym rodzajem iteratora, dzięki któremu możemy iterować po kolejnych tokenach przetwarzanego tekstu. Obiekt skanera tworzymy z użyciem jednego z kilku konstruktorów, z czego interesującymi dla nas są trzy pokazane poniżej:
public Scanner(String source)

public Scanner(File source) throws FileNotFoundException

public Scanner(InputStream source)

Identyczna funkcjonalnie metoda jak pokazana w pierwszym przykładzie, tyle że zaimplementowana przy użyciu skanera mogłaby więc wyglądać następująco:
public void tokenize() {
Iterator scanner = new Scanner("dowolny tekst do tokenizacji");

while (scanner.hasNext())
System.out.println(scanner.next());
}

W powyższym przykładzie nie określono separatora i w takim wypadku skaner używa separatora domyślnego jakim są białe znaki; stąd równoważność funkcjonalna z przykładem używającym metody split(…). Aby ustawić separator – opisany jako wyrażenie regularne – należy użyć metody useDelimiter(…) co pokazano poniżej:
public void tokenize() {
Scanner scanner = new Scanner("dowolny tekst do tokenizacji");

scanner.useDelimiter("\\s");

while (scanner.hasNext())
System.out.println(scanner.next());
}

Oprócz metod hasNext() i next() pochodzących z interfejsu Iterator, które zwracają wartości typu String, klasa Scanner implementuje metody hasNextInt() i nextInt(), hasNextBoolean() i nextBoolean() itd. dla pozostałych typów prostych. Przy użyciu tych metod możemy w łatwy sposób zaimplementować np. funkcję sumującą liczby naturalne występujące w danym tekście:
public int sum() {
Scanner scanner = new Scanner("a 1 b 2 c 3 d e f");

int sum = 0;

while (scanner.hasNext()) {
if (scanner.hasNextInt()) {
sum += scanner.nextInt();
} else {
System.out.println("nie int: " + scanner.next());
}
}

return sum;
}

6 kwietnia 2009

Moja prezentacja o GIu na JAVArsovii 2009

Kolejna edycja JAVArsovii - JAVArsovia 2009 - już wkrótce; wszystko wskazuje na to, że 4-tego lipca. Trwają poszukiwania sponsorów, patronów medialnych i... prelegentów. Chcesz wystąpić na konferencji? Wystarczy wysłać swoje zgłoszenie na adres c4p@javarsovia.pl i poczekać chwile na akceptacje tematu. No, chyba że temat się nie spodoba i akceptacji nie będzie:) Chętnych na pewno nie zabraknie, więc pewnie trzeba się z tym liczyć. Ja w każdym razie się zgłaszam - właśnie wysłałem swoje zgłoszenie z tematem "TIBCO GI – Interfejs użytkownika dla architektury SOA". Oto jego treść:

TIBCO General Interface to projekt open-source, na licencji BSD, dostarczający bibliotek i narzędzi do implementacji aplikacji klasy RIA. GI to z jednej strony biblioteka klas JavaScript umożliwiająca stworzenie profesjonalnej aplikacji typu AJAX bez konieczności użycia serwera aplikacyjnego czy nawet kontenera serwletów; a z drugiej strony zaawansowane, dedykowane środowisko programistyczne - TIBCO General Interface Builder. Oferta bez precedensu. GI jest rozwiązaniem wszechstronnym i elastycznym, ale ze względu na zaawansowane wsparcie dla wywołań usług sieciowych szczególnie predysponowane do zaistnienia w architekturach typu SOA.

Prezentacja ma na celu zainspirować do bliższego przyjrzenia się rozwiązaniu TIBCO. GIa i prezentację o nim dedykuje i polecam zwłaszcza tym, dla których interfejs użytkownika nie jest pępkiem świata; dla pragmatyków, którzy wiedzą że najważniejsze jest nie widoczne dla oczu, ale że zarazem przeważnie właśnie to co widać decyduje o efekcie końcowym i ostatecznej ocenie naszej pracy.

Prezentację poprowadzi Mariusz Lipiński – Inżynier Oprogramowania, pasjonat technologii, IT i Javy w szczególności. Magister Informatyki, absolwent Wydziału Matematyki, Informatyki i Mechaniki Uniwersytetu Warszawskiego. Członek Warszawskiej Grupy Użytkowników Technologii Java (Warszawa JUG), współorganizator konferencji JAVArsovia 2008. Mariusz zatrudniony jest obecnie jako Architekt SOA w jednej z największych polskich spółek. Swoje przemyślenia o tematyce IT publikuje na blogu pod adresem www.mariuszlipinski.pl.