Eksperymentalne środowisko dla udostępniania aplikacji JEE w modelu SaaS

Wielkość: px
Rozpocząć pokaz od strony:

Download "Eksperymentalne środowisko dla udostępniania aplikacji JEE w modelu SaaS"

Transkrypt

1 AKADEMIA GÓRNICZO-HUTNICZA IM. STANISŁAWA STASZICA W KRAKOWIE WYDZIAŁ ELEKTROTECHNIKI, AUTOMATYKI, INFORMATYKI I ELEKTRONIKI KATEDRA INFORMATYKI Eksperymentalne środowisko dla udostępniania aplikacji JEE w modelu SaaS Praca magisterska Promotor: dr inż. Dominik Radziszowski KRAKÓW 2010

2 Spis treści 1 WSTĘP KONTEKST PRACY OMÓWIENIE PROBLEMU CEL PRACY STRUKTURA PRACY WPROWADZENIE TEORETYCZNE FRAMEWORK A PLATFORMA WIELOWARSTWOWA APLIKACJA ROZPROSZONA Architektura Platforma Java EE PRZETWARZANIE W CHMURZE - XAAS SOFTWARE AS A SERVICE SAAS Popularność SaaS Architektura Model dojrzałości SaaS PLATFORM AS A SERVICE - PAAS INFRASTRUCTURE AS A SERVICE - IAAS MULTITENANCY Architektury multitenant Izolacja tenantów Multitenancy a singletenancy Multitenancy a wirtualizacja Potencjalne wyzwania PLATFORMY SAAS Rodzaje platform SaaS Platforma SaaS a PaaS i IaaS MEF ZAŁOŻENIA I ANALIZA ZAŁOŻENIA Java

3 3.1.2 Framework Multitenancy Nieinwazyjność Wykorzystanie Inversion of Control Mapowanie obiektowo-relacyjne PROBLEMY W WARSTWIE DOSTĘPU DO DANYCH Baza danych DataSource Cache System plików LDAP PROBLEMY W WARSTWIE LOGIKI BIZNESOWEJ I APLIKACJI Provisioning Identyfikacja tenanta Obiekty globalne Dostęp zdalny Logowanie PROBLEMY W WARSTWIE PREZENTACJI Interfejs użytkownika (oznaczenia firmowe) Zmienne kontekstu aplikacji Identyfikacja nadchodzącego żądania MEF - IMPLEMENTACJA TECHNOLOGIE Java Enterprise Edition Spring Hibernate ibatis KOMPONENTY FRAMEWOR KU Kontekst aplikacji DataSource Cache System plików Logowanie Provisioning Identyfikacja nadchodzącego żądania TESTY

4 5.1 JPETSTORE Integracja z MEF Przypadki testowe PETCLINIC Integracja z MEF Przypadki testowe TEST WYDAJNOŚCIOWY Środowisko testowe Przebieg testów Rodzaje testów Wyniki testów Podsumowanie WNIOSKI MOŻLIWOŚCI WYKORZYSTA NIA OPROGRAMOWANIA DALSZY ROZWÓJ SYSTEMU Funkcjonalność Architektura, infrastruktura Technologie BIBLIOGRAFIA SPIS ILUSTRACJI SPIS TABEL ZAŁĄCZNIKI

5 1 Wstęp 1.1 Kontekst pracy Software as a Service stanowi jeden z modeli wdrożeniowych oprogramowania, w którym to jest ono udostępniane użytkownikom przez sieć, jako usługa na żądanie (on-demand). Właściwe oprogramowanie zainstalowane jest (najczęściej) na serwerach dostawcy SaaS i przez niego także zarządzane i uaktualniane. Na dostawcę oprogramowania spada więc konieczność administracji, zapewnienia odpowiednich środków bezpieczeństwa i monitorowania aplikacji. Klient nie ponosi jednorazowej opłaty za zakup oprogramowania; zamiast tego płatność odbywa się na zasadzie subskrypcji - co pewien czas klient opłaca możliwość dalszego korzystania z aplikacji. Standardowy model biznesowy jednorazowej sprzedaży systemu komputerowego zostaje więc zastąpiony przez okresowe opłaty, których wielkość często naliczana jest na podstawie generowanego obciążenia (pay-as-you-use). Oprócz stabilizacji przychodów i gwarancji płynności finansowej, podejście takie pozwala na wykorzystanie zjawiska ekonomii skali - dostawca SaaS jest w stanie obsłużyć wielu klientów za pomocą pojedynczego zestawu sprzętowego i pojedynczej instancji aplikacji, co znacznie redukuje średnie koszty utrzymania w porównaniu do standardowego modelu sprzedaży i instalacji oprogramowania (on-premises) [1]. Model SaaS nabiera obecnie coraz większego znaczenia; według firmy Gartner[2] (zajmującej się analizą światowego rynku IT) około 40% firm wykorzystuje aplikacje typu SaaS w ramach swoich organizacji, a coraz więcej firm zainteresowanych jest wprowadzeniem ich do swojej oferty - przewidywane jest, że do roku 2013 zysk przez nie przynoszony wzrośnie dwukrotnie, a ich udział na rynku aplikacji klasy enterprise przekroczy 13% (w roku 2009 udział ten wynosił ok. 8%). Wśród rozwiązań opartych na modelu SaaS dominują aplikacje typu CCC (Content, Communication and Collaboration), CRM (Customer Relationship Management) oraz ERP (Enterprise Resource Planning). 5

6 W chwili obecnej jednakże wciąż dominują systemy działające w modelu onpremises. Jest to standardowy model wdrożenia lokalnego, w którym klient po zakupie aplikacji instaluje ją na własnej infrastrukturze sprzętowej, konfiguruje i udostępnia swoim użytkownikom. W modelu tym każda instancja oprogramowania działa całkowicie niezależnie od pozostałych instancji, należących do innych klientów. Aplikacje SaaS z kolei charakteryzują się przede wszystkim umiejętnością obsługi wielu klientów (tak zwanych tenantów) poprzez jedną instancję oprogramowania (instancja oprogramowania jest tu terminem umownym i potraktowanym dosyć abstrakcyjnie; w szczególności może on oznaczać całą infrastrukturę sprzętowo-programową, na której de facto uruchomione jest wiele maszyn wirtualnych i faktycznych instancji aplikacji). Cechę taką nazywamy multitenancy, zaś aplikację - aplikacją typu multitenant. Oprogramowanie multitenant zbudowane jest w oparciu o odpowiednie zasady architekturalne umożliwiające dynamiczne przełączanie kontekstu, w którym działa aplikacja (czyli przykładowo źródło danych, konfiguracja), co w praktyce pozwala pojedynczej instancji aplikacji na symulację zachowania wielu niezależnych, spersonalizowanych instalacji i tym samym obsługę żądań pochodzących od różnych tenantów. Jest to główna zaleta rozwiązań typu SaaS, odróżniająca je od standardowych aplikacji działających w modelu on-premises oraz decydująca o znacznie mniejszych nakładach na utrzymanie aplikacji i przez to bezpośrednio przyczyniająca się do rosnącej popularności SaaS. Standardowe platformy deweloperskie umożliwiające tworzenie aplikacji klasy enterprise, takie jak Java Enterprise Edition, mimo rozbudowanego zestawu narzędzi wspomagających implementację i działanie każdej z warstw aplikacji, nie są niestety wyposażone w mechanizmy umożliwiające tworzenie aplikacji typu multitenant. Deweloperzy rozwiązań SaaS zmuszeni są więc do samodzielnej implementacji niezbędnych elementów infrastruktury, umożliwiających aplikacji obsługę wielu tenantów jednocześnie. Wiąże się to z dużym ryzykiem, gdyż aplikacje typu multitenant mają o wiele większe wymagania związane z bezpieczeństwem i izolacją danych i ich niedopełnienie może prowadzić do poważnych naruszeń. Na rynku pojawiają się więc platformy nowego typu: platformy SaaS, adresujące problemy związane z tworzeniem aplikacji SaaS. Jednakże, jako że SaaS jest stosunkowo świeżym trendem, są to rozwiązania często niedojrzałe i mało elastyczne - zaimplementowana za ich pomocą aplikacja staje się nieprzenośna (w kontekście innych platform), nie rozwiązują one także problemów związanych z transformacją istniejących już aplikacji na model SaaS. 6

7 1.2 Omówienie problemu Projekt, implementacja i wdrożenie wydajnej i funkcjonalnej aplikacji SaaS to zadanie trudne i stanowi z pewnością większe wyzwanie niż stworzenie takiej samej aplikacji udostępnianej w standardowym modelu on-premises. Z drugiej strony problemy, z którymi muszą zmierzyć się projektanci SaaS są obecnie dobrze zidentyfikowane i stworzonych zostało wiele opracowań prezentujących gotowe wzorce rozwiązań. Na rynku istnieją również firmy specjalizujące się w oprogramowaniu ułatwiającym tworzenie aplikacji typu SaaS, dostarczające gotowe komponenty i narzędzia. Skorzystanie z ich usług wiąże się jednak z dużymi kosztami i przeważnie na stale uzależnia aplikację od komponentów, a często i języków, pochodzących od zewnętrznych dostawców. O wiele trudniejszym zadaniem wydaje się być adaptacja istniejącego już oprogramowania na model SaaS i wdrożenie go jako usługę dostępną przez Internet. Mimo że istnieje na rynku kilka firm specjalizujących się w tym obszarze, oferowane przez nie rozwiązania wymagają, podobnie, jak w poprzednio omawianym przypadku, przeniesienia aplikacji na platformę własnościową i dużych ingerencji w samą strukturę aplikacji. Jeśli więc potencjalny dostawca SaaS szuka bardziej elastycznego sposobu na taką adaptację, ma do wyboru dwie alternatywy. Pierwszą jest napisanie aplikacji od podstaw, projektując ją zgodnie z wymogami architekturalnymi narzucanymi przez SaaS. Wydaje się, że tworzenie tej samej aplikacji po raz drugi powinno być szybsze i łatwiejsze niż w przypadku oryginału, gdyż możliwe jest ponowne wykorzystanie komponentów i nabytej w poprzednim procesie wiedzy, a co za tym idzie uniknięcie popełnionych błędów. Należy jednak dodać do tego nakład związany z zaprojektowaniem architektury dla nowego modelu, w którym będzie udostępniana aplikacja i problemy, jakie mogą z tego wyniknąć, na przykład brak możliwości wykorzystania istniejących komponentów. Technicznie podejście to jest tożsame z tworzeniem zupełnie nowej aplikacji SaaS. Drugim sposobem jest adaptacja istniejącej aplikacji na model SaaS (SaaS enabling). W zależności od aplikacji może być to zadanie trudniejsze lub mniej opłacalne niż stworzenie oprogramowania od podstaw. Istnieją trzy różne metody takiej adaptacji: Bezpośrednie zmiany w kodzie aplikacji wymaga to dokładnej analizy kodu, wyszukania wszystkich komponentów, których zachowanie należy zmienić, prawdopodobnie także przeprojektowanie aplikacji lub naruszenie istniejącej architektury. Jak widać, może to być zadanie 7

8 bardzo złożone, potencjalnie pogarszające jakość kodu w przypadku niewystarczającej analizy (wprowadzenie błędów), zaś stworzone rozwiązanie nieprzenośne. Pociąga za sobą konieczność każdorazowej implementacji odpowiednich mechanizmów w przypadku dostosowywania wielu aplikacji, a tym samym duplikację logiki odpowiedzialnej za dostosowanie do modelu SaaS. Szczególnie problematyczne jest zapewnienie odpowiedniego poziomu izolacji mechanizmy separacji poszczególnych tenantów jedynie na poziomie aplikacji są podatne na naruszenia bezpieczeństwa i mogą prowadzić do nieuprawnionego dostępu do danych. Wirtualizacja infrastruktury - jest to technika polegająca na wykorzystaniu specjalnego oprogramowania do wdrożenia wielu kopii aplikacji (po jednej dla każdego tenanta) na tej samej fizycznej maszynie. Kopie te uruchamiane są w odpowiednich kontenerach, zapewniających odizolowane środowisko wykonawcze, co symuluje fizyczną separację instancji i możliwość obsługi wielu tenantów na raz. Takie podejście nie wprowadza złożoności i konieczności zmian na poziomie samej aplikacji, co jest bardzo dużą zaletą. Wymaga jednakże utrzymywania wielu oddzielnych instalacji i utrudnia dynamiczne wdrożenie instancji dla nowych klientów. Wymagane jest także zarządzanie samymi maszynami wirtualnymi, co w przypadku, gdy aplikacja jest rozproszona lub też działających kopii jest bardzo dużo, może być skomplikowane i okazać się mało opłacalne. Pośrednie mechanizmy SaaS w środowisku aplikacji jest to podejście polegające na stworzeniu frameworku (środowiska), za pomocą którego aplikacja byłaby uruchamiana z wbudowanymi mechanizmami umożliwiającymi automatyczne wdrożenie w modelu SaaS. Taki framework stanowiłby warstwę dodatkową, działającą w sposób przeźroczysty z punktu widzenia aplikacji. Dzięki temu możliwe byłoby uniknięcie komplikacji na poziomie kodu źródłowego, zaś samo środowisko byłoby uniwersalne i mogłoby być wykorzystywane sposób zunifikowany niezależnie od aplikacji. Poniższa tabela (Tab. 1) podsumowuje wady i zalety, jakie prezentuje sobą wdrożenie każdego z przedstawionych podejść: 8

9 Modyfikacja kodu Wirtualizacja Framework Łatwość wdrożenia rozwiązania Bardzo trudne; niezbędne jest powtórzenie całego procesu analizy i implementacji od nowa w przypadku każdej aplikacji, gdyż mechanizmy nie są przenośne Łatwe; niezbędna jest odpowiednia konfiguracja środowiska wirtualizacji Stosunkowo łatwe, zależy od aplikacji; konieczne jest dostosowanie aplikacji do działania z wykorzystaniem frameworku poprzez odpowiednią jej konfigurację; framework musi obsługiwać technologię aplikacji Szybkość wdrożenia rozwiązania Wolne; musi zostać dokonana dokładna analiza wymaganych zmian i ich implementacja, a także powtórzone wszystkie testy aplikacji Bardzo szybkie; wymaga jedynie instalacji i konfiguracji odpowiedniego środowiska sprzętowego Szybkie; niezbędna jest odpowiednia konfiguracja programowa, niewymagane są zmiany w infrastrukturze sprzętowej Koszt wdrożenia rozwiązania Wysokie jednorazowe koszty dla każdej aplikacji; niezbędne jest opłacenie grupy doświadczonych programistów i procesu implementacji Wysokie koszty stałe - operacyjne; niezbędne jest utrzymanie droższej infrastruktury sprzętowej Bardzo małe koszty jednorazowe; związane są jedynie z krótkim procesem konfiguracji Inwazyjność rozwiązania Bardzo duża; zmienia się implementacja, a nawet architektura całej aplikacji Brak; aplikacja pozostaje w formie niezmienionej Mała; zmienia się konfiguracja aplikacji, możliwe, że także, w nieznacznym, zależnym od technologii, stopniu implementacja Tab. 1. Porównanie podejść w adaptacji aplikacji na model SaaS 9

10 Pierwsze z omówionych podejść - bezpośrednie dostosowanie istniejącej aplikacji - jest w praktyce ponownie tożsame z implementacją od podstaw rozwiązania SaaS. Nie jest to tematem niniejszej pracy. Wirtualizacja jest z kolei stosunkowo dobrze rozpoznanym i opisanym podejściem i nie prezentuje sobą wielu wyzwań z technicznego punktu widzenia. Najciekawszym problemem wydaje się więc adaptacja istniejącej aplikacji na model SaaS przy wykorzystaniu trzeciego z wyżej wymienionych podejść mechanizmów wbudowanych we framework aplikacji. 1.3 Cel pracy Celem niniejszej pracy jest stworzenie frameworku umożliwiającego możliwie nieinwazyjne i efektywne przeniesienie istniejącej aplikacji Java EE na model SaaS (MEF Multitenancy Enablement Framework). Poprzez framework rozumiany jest tu zestaw komponentów, które automatycznie zapewniałyby spełnienie wymogów stawianych przez aplikacje klasy SaaS. W ramach pracy wykonana będzie więc analiza problemów charakteryzujących zarówno samo podejście SaaS, jak i, bardziej specyficznie, proces migracji istniejącego oprogramowania do tego modelu. Zaproponowane rozwiązania zilustrowane będą przez konkretne implementacje komponentów składających się na framework. Założono wykorzystanie technologii o otwartym kodzie. Zaproponowane rozwiązania implementacyjne przetestowane będą za pomocą istniejących aplikacji JEE. 1.4 Struktura pracy Praca została zorganizowana następująco: rozdział 2. Wprowadzenie teoretyczne omawia szerzej model SaaS oraz pokrewne mu zagadnienia przedstawiając tym samym kontekst, do którego należy stworzone rozwiązanie, a także prezentuje definicje najbardziej istotnych pojęć używanych przez autorów. Rozdział 3. MEF założenia i analiza stanowi bardziej szczegółowe, techniczne rozważania na temat potencjalnych problemów w implementacji rozważanego środowiska i proponowanych dla nich rozwiązań. Rozdział 4. MEF - implementacja opisuje wybrane elementy implementacji MEF, zaś rozdział 5. 10

11 Testy opisuje przypadki testowe, za pomocą których zweryfikowana została funkcjonalność MEF oraz wydajność rozwiązania. Rozdział 6. Wnioski kończy właściwą część pracy prezentując analizę otrzymanych rezultatów i możliwości dalszego rozwoju frameworku MEF. Do pracy dołączono także spis źródeł (rozdział 7. Bibliografia ), ilustracji (rozdział 8. Spis ilustracji ) i tabel (rozdział 9. Spis tabel ) oraz materiały dodatkowe (rozdział 10. Załączniki ). Rozdziały: 1, 2, 3.1, 3.2 i 6 napisane zostały przez Agnieszkę Janowską, zaś rozdziały: 3.3, 3.4, 4, 5 oraz 10 przez Tomasza Sadurę. Pozostałe rozdziały: 7, 8 i 9 stworzone zostały przez autorów pracy wspólnie. 11

12 2 Wprowadzenie teoretyczne Rozdział ten ma na celu wprowadzenie czytelnika w zagadnienia teoretyczne bezpośrednio związane z tematem pracy. Nakreślone zostały w nim przede wszystkim pojęcia uwzględnione w temacie pracy oraz zasady i założenia rządzące i definiujące SaaS. Wspomniane zostały także inne modele powiązane z SaaS, tworzące ogólny obraz domeny, do której należy tworzone opracowanie. 2.1 Framework a platforma W niniejszej pracy przeplatają się dwa terminy framework oraz platforma. Istotnym jest aby już na wstępie zaznaczyć różnice dzielące te dwa pojęcia[3]. Platforma stanowi architekturę sprzętową lub programową zezwalającą na uruchomienie na niej oprogramowania. Framework zaś to pewnego rodzaju abstrakcja, szkielet dla aplikacji dostarczający komponentów o pewnym zachowaniu i umożliwiający ich ponowne wykorzystanie, czy modyfikację, najczęściej poprzez API. W skład frameworku wchodzić mogą programy wspierające, biblioteki kodu, języki skryptowe i inne elementy pozwalające na zestawienie razem różnych komponentów aplikacji. Istnieją więc dwie główne różnice pomiędzy platformą a frameworkiem. Po pierwsze, framework odnosi się jedynie do warstwy programowej, podczas gdy platformy często składają się również (lub jedynie) z warstwy sprzętowej. Druga różnica leży w zakresie "obowiązków" każdej z tych struktur. Platforma posiada możliwość uruchamiania kodu, podczas gdy framework jest w tym względzie bardziej zbliżony do biblioteki - udostępnia tylko komponenty do budowy aplikacji, skupiając się na architekturze aplikacji, nie stanowi dla niej jednak środowiska uruchomieniowego. Dobrym przykładem ilustrującym te różnice jest Java[4] i Spring [5]. Java stanowi platformę, gdyż dostarcza wirtualnej maszyny potrafiącej uruchamiać kod. Z kolei Spring jest typowym frameworkiem - korzystając ze Springa stosujemy się do pewnych zasad architekturalnych w aplikacji, dostarcza on wiele gotowych komponentów 12

13 działających w ustandaryzowany sposób, dzięki czemu zmniejsza się objętość kodu właściwiej części biznesowej aplikacji. 2.2 Wielowarstwowa aplikacja rozproszona Aplikacja rozproszona to rodzaj aplikacji działającej na więcej niż jednej maszynie, w której komunikacja odbywa się poprzez sieć[6]. Aplikacje takie są zbudowane z warstw, które stanowią części oprogramowania mogące działać na osobnych maszynach. Wraz z rozwojem Internetu i technologii komputerowych nastąpiła ewolucja rozproszonego modelu aplikacji od jedno-warstwowych architektur systemów z centralną jednostką mainframe, przez dwu-warstwowe systemu typu klient-serwer, do rozpowszechnionych obecnie aplikacji wielowarstwowych działających w Internecie Architektura Architektura większości aplikacji rozproszonych obejmuje następujące podstawowe warstwy[7]: warstwę prezentacji, odpowiedzialnej za interfejs użytkownika; warstwę biznesową, adresującą domenę aplikacji i logikę przetwarzania operującą na danych biznesowych; warstwę dostępu do danych, odpowiedzialnej za manipulację danymi i udostępnianie ich warstwie biznesowej. Zgodnie z wielowarstwowym modelem wdrożenia aplikacji rozproszonej warstwy te mogą działać na oddzielnych maszynach, co pozwala na wykorzystanie specjalistycznego sprzętu i oprogramowania, dostosowanego do zadań wypełnianych przez daną warstwę. Często spotykanym przykładem architektury wielowarstwowej jest model cztero-warstwowy, przedstawiony na poniższym diagramie (Rys. 1): 13

14 Warstwa Kliencka PC Warstwa Prezentacji Serwer Webowy Warstwa Biznesowa Serwer Aplikacji Warstwa Dostępu do Danych System Plików Baza Danych Serwery Danych Rys. 1. Architektura rozproszonej aplikacji wielowarstwowej W modelu tym cienki klient (czyli aplikacja, której zadaniem jest jedynie prezentacja interfejsu użytkownikowi i umożliwienie mu interakcji z systemem) łączy się z serwerem webowym reprezentującym warstwę prezentacji, który z kolei komunikuje się z serwerem aplikacji. Na serwerze aplikacji wdrożone są komponenty biznesowe odpowiedzialne za faktyczną funkcjonalność aplikacji. Tam również działają komponenty warstwy dostępu do danych, których zadaniem jest komunikacja z serwerem bazodanowym, na którym utrzymywane są dane biznesowe i udostępnianie ich z powrotem warstwie biznesowej. W praktycznym przypadku wdrożenia takiej architektury dla mniejszych systemów wszystkie trzy warstwy: prezentacji, biznesowa i dostępu do danych mogą fizycznie rezydować na jednym serwerze. 14

15 2.2.2 Platforma Java EE Java Enterprise Edition (JEE)[8] stanowi standardową platformę deweloperską dla rozproszonych aplikacji wielowarstwowych. Obok.NET[9] jest to właściwie najpopularniejsza platforma dla aplikacji klasy enterprise. Zgodnie z terminologią zarysowaną w rozdziale 2.1 Framework a platforma, JEE jest równocześnie platformą oraz frameworkiem. Stanowiąc przede wszystkim specyfikację środowiska aplikacji rozproszonej, pozwala równocześnie, jako platforma dla języka Java, na uruchamianie kodu. Specyfikacja JEE wymienia cztery warstwy składające się na aplikację JEE[10]: warstwa klienta, której komponenty działają na maszynie klienckiej; warstwa webowa, której komponenty działają na serwerze Java EE; warstwa biznesowa, której komponenty działają na serwerze Java EE; warstwa Enterprise Information System (EIS), której komponenty działają na serwerze EIS (w praktyce są to przeważnie bazy danych oraz systemy odziedziczone) Komponenty Poniżej wymienione komponenty stanowią rdzeń frameworku JEE oraz tworzą szkielet każdej aplikacji stworzonej za jego pomocą. Komponenty te są rozszerzane i implementowane przez deweloperów budując razem warstwy prezentacji i biznesową aplikacji[11]: Servlety - są to obiekty po stronie serwera specjalnie przystosowane do budowy dynamicznych aplikacji webowych. Ich zadaniem jest generowanie stron HTML na podstawie otrzymywanych żądań HTTP. Java ServerPages (JSP) - stanowią rozszerzenie dla Servletów wprowadzając możliwość definicji szablonów dla generowanych plików HTML i tym samym ułatwiając generowanie dynamicznych stron. Szablony te umożliwiają wykorzystanie tagów i scriptletów do enkapsulacji kodu logiki prezentacji. Enterprise JavaBeans (EJB) - stanowią framework dla rezydujących po stronie serwera komponentów biznesowych aplikacji; dostarczają środków do implementacji logiki biznesowej w sposób 15

16 zmodularyzowany, a także specyfikują środowisko uruchomieniowe i usługi dostępne dla takich komponentów Kontenery Kontenery są częścią architektury platformy JEE udostępniającą środowisko uruchomieniowe dla komponentów i umożliwiające im dostęp do usług świadczonych przez serwer JEE[12]. Każdy rodzaj komponentu musi być umieszczony w odpowiednim kontenerze - w praktyce kontenery odpowiadają poszczególnym warstwom aplikacji, co przedstawia diagram (Rys. 2): Aplikacja Kliencka Kontener Aplikacji Klienckiej HTML Przeglądarka Internetowa Warstwa Kliencka Maszyna Kliencka Servlet JSP Kontener Webowy Warstwa Webowa Serwer Java EE EJB EJB Kontener EJB Warstwa Biznesowa Warstwa EIS Serwer EIS Baza Danych Baza Danych Rys. 2. Architektura platformy Java EE Kontenery zarządzają cyklem życia komponentów, pozwalają na ich wdrożenie i uruchomienie, zapewniają także bezpieczeństwo. Uzyskana dzięki temu separacja pomiędzy infrastrukturą a samą aplikacją wprowadza możliwość ponownego 16

17 wykorzystania komponentów i pozwala programiście skupić się na właściwej logice aplikacji Warstwa klienta Jest to warstwa znajdująca się na maszynie klienckiej; jej zadaniem jest prezentacja interfejsu użytkownika. Występują dwa rodzaje klientów aplikacji JEE[11]: cienki i gruby. Cienki klient opiera się na webowym interfejsie użytkownika i jest to przeważnie przeglądarka; gruby klient to samodzielna aplikacja działająca w kontenerze klienta. Istnieje również rodzaj klienta pośredniego między cienkim a grubym - applet. Jest on uruchomiony w kontenerze appletu, którym jest jednak przeważnie przeglądarka internetowa Warstwa webowa Warstwa ta odpowiedzialna jest za prezentację oraz logikę aplikacji. W skład komponentów tej warstwy wchodzą Servlety oraz JSP generujące strony HTML, które z kolei wyświetlane są przez klientów webowych Warstwa biznesowa Warstwa ta reprezentuje logikę biznesową mającą za zadanie spełnić określone cele bezpośrednio związane z domeną biznesową aplikacji. Komponentami odpowiedzialnymi za tą logikę są EJB działające w kontenerze EJB. Dzięki luźnemu powiązaniu pomiędzy kontenerami i architekturze komponentowej możliwe jest ponowne wykorzystanie komponentów biznesowych w innych aplikacjach, możliwy jest także dostęp do innych warstw biznesowych pozwalając na wykorzystanie dodatkowych funkcjonalności. 17

18 Warstwa EIS Na warstwę tą składają się systemy wchodzące w skład infrastruktury IT danego przedsiębiorstwa, a więc bazy danych, systemy ERP (Enterprise Resource Planning) i inne systemy odziedziczone. Dzięki JEE możliwy jest zunifikowany i jednolity dostęp do danych dostarczanych przez te systemy. 2.3 Przetwarzanie w chmurze - XaaS Wraz z rozwojem Internetu i pojawieniem się opartych na nim nowych modeli udostępniania i sprzedaży usług IT, zapoczątkowanych przez takie firmy jak Amazon[13], czy Google[14], dużą popularność uzyskał termin przetwarzania w chmurze. Chmurę (Cloud) można zdefiniować jako zbiór dostępnych przez Internet usług obejmujących oprogramowanie, platformy deweloperskie, czy infrastruktury sprzętowe[15], zaś przetwarzanie w chmurze jako ich wykorzystanie. Usługi te są oparte na zdecentralizowanym środowisku, elastyczne i wysoko skalowalne, co powoduje, że chmura jest jednym z najważniejszych (jeśli nie najważniejszym) trendów ostatnich lat w branży IT[16]. Do wymienionych w definicji chmury elementów: oprogramowania, platformy i infrastruktury często odnosi się jako warstw chmury[17]. Możliwości udostępniane przez chmurę często określa się wspólnym przyrostkiem aas as a Service czyli jako usługa, a więc przykładowo do oprogramowania jako usługi (dostępnej w chmurze) odnosi się terminem SaaS Software as a Service. Pojęciem grupującym szereg modeli typu aas, udostępniających różne elementy składające się na system komputerowy, jest XaaS, czyli X as a Service, czy też Everything as a Service (wszystko jako usługa). XaaS jest praktyczną realizacją abstrakcyjnego pojęcia chmury. Usługi określane wspólnie terminem XaaS przybierają najróżniejsze formy, możemy więc wyróżnić modele takie, jak wspomniany Software as a Service (SaaS), który jest modelem najbardziej rozpowszechnionym, Infrastructure as a Service (IaaS) infrastruktura jako usługa, Platform as a Service (PaaS) platforma jako usługa, Storage as a Service (STaaS) pamięć masowa jako usługa, Communication as a Service (CaaS) komunikacja jako usługa, Testing as a Service (TaaS) testowanie jako usługa, Integration as a Service (INTaaS) integracja jako usługa, itp.[15] 18

19 Modelami najszerszymi, stanowiącymi nadzbiory dla bardziej wyspecjalizowanych rozwiązań wchodzących w skład XaaS, są, wymienione w pierwszej kolejności, SaaS, PaaS i IaaS. Zostały one szerzej przedstawione w kolejnych rozdziałach. Modele te przekładają się bezpośrednio na wspomniane już warstwy chmury; sposób, w jaki są ze sobą powiązane, zilustrowany jest na diagramie (Rys. 3): Chmura Użytkownicy końcowi Warstwy chmury Warstwa usług (aplikacje webowe, usługi na żądanie) Usługi dostępne w chmurze SaaS Deweloperzy aplikacji Administratorzy sieci, projektanci infrastruktury sprzętowej Warstwa platformy (serwery aplikacji, serwery webowe, bazy danych, niskopoziomowe elementy infrastruktury programowej) Warstwa infrastruktury (sprzęt, maszyny wirtualne, OS) PaaS IaaS Warstwa dostępowa (Internet/Intranet) Rys. 3. Warstwy i usługi w chmurze Diagram przedstawia kolejne warstwy składające się na chmurę i jednocześnie domenę i elementy obejmowane przez wymienione modele aas. Łączące je strzałki oznaczają sposób, w jaki mogą one nakładać się na siebie. I tak SaaS może wykorzystywać PaaS jako warstwę wspierającą, może również być zbudowane bezpośrednio na IaaS albo też w ogóle nie wykorzystywać chmury jako takiej i być udostępniane na dedykowanej infrastrukturze. Podobnie ma się rzecz z PaaS może wykorzystywać IaaS jako warstwę wspierającą, ale może także działać w ramach własnej infrastruktury. 19

20 2.4 Software as a Service SaaS Software as a Service, czyli oprogramowanie jako usługa, jest to model biznesowy i wdrożeniowy tworzenia i udostępniania aplikacji. Oprogramowanie SaaS wdrażane jest jako usługa dostępna na żądanie, przez sieć (w praktyce najczęściej Internet) i stanowi przykład aplikacji rozproszonej opisanej w rozdziale 2.2. W standardowym modelu udostępniania oprogramowania on-premises, czyli na terenie przedsiębiorstwo, które zakupuje nowe oprogramowanie musi również zainwestować, oprócz odpowiednich licencji, w infrastrukturę sprzętową i zasoby ludzkie. Aplikacja jest instalowana na lokalnych serwerach, udostępniana pracownikom w Intranecie (lub też klientom zewnętrznym przez Internet) i zarządzana przez dział IT. Aby korzystać z aplikacji SaaS firma nie musi dokonywać żadnej z tych czynności - aplikacja działa w chmurze, na zdalnych serwerach dostawcy oprogramowania, potencjalny klient potrzebuje więc jedynie dostępu do Internetu. Oprogramowanie takie opłaca się przeważnie na zasadzie pay-as-you-go okresowych subskrypcji. Podejście to jest wyjątkowo atrakcyjne dla małych i średnich przedsiębiorstw inwestujących w nowe rozwiązania, gdyż zakup usług SaaS nie wymaga żadnego wkładu początkowego (poza tym związanym z opłatą subskrypcji) i niesie za sobą niewielkie ryzyko inwestycyjne w porównaniu do modelu on-premises. Klienci rozwiązania SaaS nazywani są tenantami. Nie należy tego pojęcia mylić z użytkownikami aplikacji - tenantami są przeważnie całe organizacje (firmy, korporacje), każdy z tenantów posiada swoich pracowników, czy klientów, i to oni dopiero stanowią użytkowników końcowych, do których skierowana jest aplikacja SaaS. Przykładowymi aplikacjami SaaS dostępnymi na rynku jest system CRM salesforce.com[18], NetSuite[19], czy oferowane darmowo Google Apps[20] Popularność SaaS Szereg makroczynników ma wpływ na rosnącą popularność systemów SaaS: 20

21 ekonomiczne - z punktu widzenia firm użytkujących oprogramowanie inwestycje oparte na oprogramowaniu typu SaaS wymagają o wiele mniejszego kapitału, co dotyczy zarówno zasobów pieniężnych (czasowe subskrypcje zamiast licencji, mniejsze ryzyko związane z inwestycją), ludzkich (nie jest wymagany rozbudowany dział IT, gdyż oprogramowanie nie jest instalowane na firmowych serwerach i stacjach roboczych), jak i czasowych (czas niezbędny na wdrożenie aplikacji jest krótszy, gdyż nie ma potrzeby instalacji dedykowanej infrastruktury sprzętowej); dla firm zmagających się z kryzysem takie korzyści mają niebanalne znaczenie, co zapewne miało swój wpływ na wzrost udziału aplikacji SaaS na rynku w ostatnich latach; społeczne - w dzisiejszych czasach Internet wykorzystywany jest powszechnie, zarówno w życiu prywatnym, jak i zawodowym, liczba jego użytkowników wciąż rośnie, zaś możliwości, jakie są oferowane przez globalną sieć są coraz bardziej rozległe. SaaS, jako oprogramowanie dostępne przez Internet, wpasowuje się w ten trend. Firmy chcą, aby ich systemy były łatwo dostępne, zarówno dla pracowników (którzy mogą wykonywać swoją pracę z dowolnego miejsca), jak i klientów, a także wykorzystać możliwości, jakie oferuje Internet (np. sieci społecznościowe); technologiczne - już od jakiegoś czasu jednym z najsilniejszych trendów technologicznych są architektury oparte o współdzielone zasoby, co pozwala na wykorzystanie ich w sposób bardziej efektywny, łatwiejsze skalowanie i zredukowanie kosztów utrzymania systemu. Początkowo była to wirtualizacja (na różnych poziomach), która z czasem, wykorzystana na skalę masową, stanęła u podstaw przetwarzania w chmurze (Cloud computing), powstały architektury typu SOA (Service Oriented Architecture) i wykorzystanie usług zdalnych; środowiskowe - w związku z rosnącym wykorzystaniem elektryczności, emisją dwutlenku węgla i wytwarzaniem odpadów, przemysł IT poddawany jest coraz ściślejszym regulacjom. Powoduje to konieczność dążenia do lepszego wykorzystania istniejących zasobów sprzętowych, zmniejszenia kosztów ich eksploatacji, a tym samym redukcję ich szkodliwego wpływu na środowisko, na co odpowiedzią jest przetwarzanie w chmurze (którego większą część stanowi SaaS). Przewiduje się, że ostatecznie prywatne stacje robocze służyć będą jedynie do łączenia się z siecią i za jej pomocą korzystania z danych i oprogramowania przechowywanych na zdalnych serwerach. 21

22 2.4.2 Architektura Jakkolwiek model SaaS jest modelem biznesowym lub też wdrożeniowym aplikacji, nie zaś modelem architektonicznym, Microsoft wyróżnia pewne cechy charakteryzujące większość dobrze zaprojektowanych rozwiązań SaaS[1]. 1. Multitenancy - jest to pojęcie odnoszące się do możliwości obsługi wielu tenantów przez pojedynczą instancję aplikacji. Z takiej aplikacji może korzystać jednocześnie wielu użytkowników pochodzących z zupełnie oddzielnych organizacji, przy czym aplikacja zapewnia zupełną izolację pomiędzy nimi. System musi być więc tak zaprojektowany, aby współdzielić zasoby wchodzące w jego skład, a jednocześnie zachować separację i umiejętność odróżnienia danych poszczególnych tenantów. 2. Konfigurowalność - tenanci bardzo często potrzebują aplikacji dostosowanej do ich potrzeb, wymogów korporacyjnych, procesów biznesowych. Oczywiście nie jest możliwe zapewnienie tego bezpośrednio na poziomie kodu - aplikacja ma służyć wielu tenantom na raz. Dobrze zaprojektowane aplikacje udostępniają więc szerokie możliwości, oparte na zewnętrznych ustawieniach, konfiguracji, dzięki czemu tenanci są w stanie dostosować ich wygląd i zachowanie dla swoich użytkowników. 3. Skalowalność - oznacza umiejętność łatwej adaptacji oprogramowania do zwiększonego wykorzystania (na przykład przy wzroście liczby użytkowników) i współbieżności poprzez efektywne wykorzystanie dostępnych oraz dodatkowych zasobów, optymalizację przetwarzania w obszarach krytycznych i bezstanowość. Ma ona krytyczne znaczenie, gdyż liczba użytkowników aplikacji SaaS może rosnąć bardzo szybko. Z architekturalnego punktu widzenia aplikacje SaaS zgodne są z opisanym w rozdziale 2.2 wielowarstwowym modelem aplikacji rozproszonej, jakkolwiek, aby być w stanie efektywnie operować w chmurze, muszą uwzględniać w swojej architekturze pewne rozszerzenia[21], co przedstawia poniższy diagram (Rys. 4): 22

23 Tenant Warstwa Kliencka Tenant Warstwa Kliencka Tenant Warstwa Kliencka SaaS Warstwa Prezentacji Warstwa Dystrybucji Usługi JEE Usługi SaaS Konfiguracja i Personalizacja Warstwa Biznesowa Warstwa Dostępu do Danych Równoważenie Obciążenia Uwierzytelnianie i Bezpieczeństwo Monitoring Integracja Pomiary i Naliczanie Opłat Provisioning Metadane Warstwa EIS System Plików Baza Danych LDAP Systemy On-premises Rys. 4. Architektura aplikacji SaaS Aplikacje SaaS charakteryzują się więc bardzo często warstwą dystrybucji. Jakkolwiek nie jest to warstwa specyficzna jedynie dla SaaS charakteryzuje ona większość aplikacji klasy enterprise to ma ona zasadnicze znaczenie dla tej architektury. Dzięki warstwie dystrybucji możliwe jest zastosowanie mechanizmów równoważenia obciążenia (load balancing) w celu dynamicznego przekierowania nadchodzących żądań na inne instalacje, co zapewnia wysoką skalowalność i odpowiedni poziom jakości usług w systemach obsługujących wielu tenantów. Architektura SaaS obejmuje także wiele rodzajów usług należących do warstwy aplikacji i wspierających właściwą funkcjonalność. Większość z nich jest charakterystyczna dla wszystkich rozwiązań klasy enterprise, jednakże w przypadku aplikacji on-premises udostępniane są one przeważnie przez platformę dostępną po stronie klienta zakupującego aplikację w SaaS to dostawca aplikacji musi je zapewnić, dlatego też zostały one uwzględnione na diagramie architektury. Do usług tych należą: warstwa równoważenia obciążenia i zarządzania ruchem kierowanym do aplikacji (load balancer), warstwa autoryzacji i bezpieczeństwa (rozbudowana jednakże w stosunku do standardowych rozwiązań o mechanizmy 23

24 multitenancy, dzięki którym użytkownicy mają dostęp jedynie do danych reprezentowanych przez nich tenantów), warstwa integrująca aplikację z systemami zastanymi (legacy systems), czyli w przypadku SaaS z systemami onpremises, lub też z innymi systemami SaaS (mashups) oraz warstwa monitoringu nadzorującą obciążenie i zachowanie aplikacji. Do warstw nowych, specyficznych jedynie dla SaaS, należą: warstwa umożliwiająca automatyczną rejestrację i dynamiczną alokację zasobów dla nowego tenanta (provisioning) i warstwa zajmująca się pomiarem aktualnego wykorzystania zasobów przez danych tenantów i zgodnie z nim naliczająca opłaty (pay-as-you-use) Model dojrzałości SaaS Rozwiązanie SaaS może być oferowane na różnych poziomach dojrzałości, które zależą od wymienionych powyżej cech architekturalnych. Posiadanie ich przez aplikację jest pożądane, ale niewymagane, aby była ona rozpatrywana jako SaaS. Kolejne poziomy dojrzałości osiąga się właśnie poprzez dodanie którejś z wymienionych wyżej charakterystyk; poziomy te definiowane są następująco[1]: 1. Rozwiązanie ad hoc - w podejściu tym aplikacja nie charakteryzuje się żadną z trzech wymienionych powyżej cech; jest udostępniana każdemu z tenantów jako osobna instancja działająca na serwerze hostującym. Instancje te są dostosowywane dla każdego klienta z osobna i działają całkowicie niezależnie od siebie. Model ten jest więc bardzo podobny do standardowego podejścia on-premises, z tą tylko różnicą, że klienci nie utrzymują aplikacji na swoich serwerach, a na serwerach należących do dostawcy usług SaaS. Pozwala to na poczynienie pewnych oszczędności dzięki centralizacji wdrożenia i zarządzania, a więc zmniejszonym kosztom administracyjnym i bardziej efektywnym wykorzystaniu zasobów sprzętowych, jednakże daleko im jeszcze do zalet oferowanych przez całkowicie dojrzałe aplikacje SaaS. Model ten jest najłatwiejszy do zastosowania w przypadku, gdy pożądana jest szybka i prosta transformacja istniejącej aplikacji na SaaS. Nie są wymagane bowiem praktycznie żadne zmiany w samej aplikacji, zmienia się jedynie sposób jej wdrożenia i udostępniania. Stanowi to dużą zaletę w przypadku bardzo wczesnych faz przenoszenia na model SaaS, gdy przydatna jest analiza popytu na daną usługę i wstępne uwagi od potencjalnych klientów. 24

25 2. Aplikacja konfigurowalna - na tym poziomie aplikacja wciąż udostępniana jest jako dedykowane dla tenantów, niezależne instancje, jednakże spełnia już wymóg konfigurowalności. Oznacza to, że zamiast osobno dostosowywać każdą z instancji dla poszczególnych tenantów, klient ma możliwość samemu skonfigurować aplikację tak, by spełniała jego wymogi odnośnie wyglądu czy procesów biznesowych. W praktyce oznacza to, że dostawca udostępnia ten sam kod aplikacji każdemu z tenantów, gdyż mechanizmy konfiguracji są wbudowane bezpośrednio w logikę aplikacji; kod nie musi być ręcznie zmieniany w celu personalizacji, zamiast tego opiera się on na pewnego rodzaju metadanych specyficznych dla tenanta. Przejście na ten poziom wymaga już przeważnie poważnych zmian w architekturze aplikacji, jednakże z drugiej strony pozwala na znaczną redukcję wysiłków administracyjnych związanych przykładowo z uaktualnieniami - na poprzednim poziomie dojrzałości każda z instancji opierała się na innym kodzie, a więc aktualizacje i poprawki musiały być aplikowane niezależnie dla każdej z nich; na tym poziomie, dzięki tej samej wersji kodu u wszystkich tenantów, mogą być one uaktualniane jednocześnie. 3. Aplikacja konfigurowalna, typu multitenant - jest to najbardziej znaczący przeskok z punktu widzenia architektury aplikacji. Jest ona bowiem wdrożona jako pojedyncza instancja obsługująca wielu tenantów jednocześnie, pozwalająca na dynamiczną konfigurację opartą na metadanych. Z punktu widzenia użytkowników jest to niezauważalna zmiana w porównaniu z drugim poziomem dojrzałości - nie zdają oni sobie sprawy z tego, że współużytkują aplikację wraz z innymi tenantami. Na poziomie aplikacji niezbędne jest wbudowanie mechanizmów zapewniających tą przeźroczystość - współdzielenia i koordynowania dostępu do zasobów, separacji danych poszczególnych tenantów, autoryzacji i bezpieczeństwa. Dzięki temu uzyskujemy duży skok wydajności całego systemu - jako że pojedyncza instancja potrafi teraz obsłużyć wielu tenantów na raz, wymagana jest dużo mniej rozbudowana architektura sprzętowa, co bezpośrednio przekłada się na zmniejszone koszty utrzymywania aplikacji. Wadą takiego rozwiązania jest mała skalowalność - przy dodawaniu kolejnych tenantów jedna instancja może przestać być wystarczająca by efektywnie przetwarzać wszystkie żądania. Jedynym sposobem na podniesienie wydajności aplikacji jest uruchomienie jej na mocniejszym serwerze, jednakże takie skalowanie ma swoje granice. 25

26 4. Aplikacja skalowalna, konfigurowalna, typu multitenant - jest to poziom, gdzie aplikacja typu SaaS osiąga największą dojrzałość. Tak jak na poprzednim poziomie spełnia ona założenia konfigurowalności i działania w modelu multitenant, jednakże w tym przypadku dochodzą również mechanizmy równoważenia obciążenia (load balancing), które mają za zadanie dynamicznie uruchamiać nowe instancje aplikacji i przekierowywać do nich ruch pochodzący od różnych tenantów. Dzięki temu aplikacja staje sie wysoce skalowalna - ilość instancji dopasowuje się do aktualnego obciążenia, może być automatycznie zmniejszana lub zwiększana. Teoretycznie taka farma może obsłużyć dowolną ilość tenantów (zależy to jedynie od wydajności fizycznej infrastruktury - w razie potrzeby można dokupić dodatkowe serwery). Warto zauważyć, że w kontekście istniejących aplikacji wyżej wymienione elementy konfigurowalności i skalowalności są problemami bardzo dobrze znanymi i szeroko zaadresowanymi charakteryzuje się nimi wiele aplikacji JEE. W szczególności skalowalność - jest to de facto standard i nieodzowna charakterystyka rozwiązań klasy enterprise. Standardowa architektura i model udostępniania aplikacji nie uwzględnia jednakże mechanizmów multitenancy dlatego jest to zagadnienie szczególnie interesujące z punktu widzenia niniejszego opracowania, jego badaniom poświęcona jest większa część pracy. 2.5 Platform as a Service - PaaS Platform as a Service, czyli platforma jako usługa, jest to zbiór dostępnych przez sieć narzędzi i komponentów wspierających cykl tworzenia i udostępniania aplikacji. Fazy tego cyklu obejmują: projekt aplikacji, implementację, testowanie, wdrażanie i hosting. PaaS może oferować narzędzia wspierające je wszystkie lub też jedynie część z nich. W szczególności PaaS może dostarczać gotowych komponentów do wykorzystania w aplikacji, przykładowo komponentów zapewniających bezpieczeństwo w aplikacji (uwierzytelniania i autoryzacji), mechanizmów skalowania, wersjonowania aplikacji, zarządzania stanem, baz danych, itp. Najbardziej dojrzałe rozwiązania PaaS oferują kompletne, zintegrowane środowiska deweloperskie i uruchomieniowe, zapewniające kontrolę wersji, platformę komunikacyjną dla deweloperów, narzędzia wspomagające tworzenie kodu, szeroką gamę gotowych komponentów i mechanizmów do 26

27 wykorzystania oraz infrastrukturę sprzętowo-programową utrzymującą działającą aplikację. Tym, co odróżnia PaaS od standardowych platform jest dostępność jako usługa, co w praktyce oznacza, że deweloperzy programują "w Internecie". Wśród dostępnych na rynku rozwiązań możemy wyróżnić dwie podgrupy rozwiązań PaaS: platformy dla użytkowników biznesowych - są to platformy charakteryzujące się prostotą użycia, dzięki czemu deweloper aplikacji nie musi być koniecznie programistą; aplikacja (obiekty biznesowe przechowywane w bazie, moduły logiczne, interfejs użytkownika) tworzona jest często za pomocą wizualnych komponentów, metodą przeciągnij-upuść. Prostota ta oferowana jest kosztem elastyczności - dodawanie własnego kodu do źródeł takiej aplikacji nie jest możliwie - znacznie ogranicza to możliwości dostosowania oprogramowania do niestandardowych wymagań firmy. Istniejącymi na rynku przykładami takich platform są: Caspio[22], Rollbase[23], PerfectForms[24]; platformy programistyczne - niskopoziomowe platformy deweloperskie, w obrębie których programiści własnoręcznie implementują komponenty aplikacji; platformy takie zapewniają jedynie infrastrukturę: system operacyjny, mechanizmy równoważenia obciążenia i skalowalności, itp. Platformy takie są bardzo elastyczne, zezwalają na o wiele większą swobodę w konstrukcji aplikacji niż to było w przypadku platform dla użytkowników końcowych. Różnią się między sobą wspieranymi językami programowania czy bazami danych. Istniejące na rynku rozwiązania tego typu to między innymi: Google App Engine[14], platforma force.com[25], czy Apprenda SaaSGrid[26]. 2.6 Infrastructure as a Service - IaaS Infrastructure as a Service, czyli infrastruktura jako usługa, jest to rodzaj usług umożliwiający dostęp do niskopoziomowych elementów infrastruktury komputerowej na żądanie. Do zasobów takich należą fizyczne osprzętowanie (procesory, pamięć), serwery bazodanowe, sprzęt sieciowy, czy systemy operacyjne. Zasoby te znajdują się "w chmurze" - utrzymywane są, zarządzane i administrowane przez dostawcę usług IaaS. Użytkownicy najczęściej "wynajmują" odpowiednią konfigurację sprzętową i płacą na podstawie aktualnego zużycia. 27

28 Dzięki dużym możliwościom oferowanym przez IaaS, elastyczności i konfigurowalności, usługi tego typu osiągają stosunkowo dużą popularność wśród rozwiązań "aas". Dodanie nowych zasobów sprzętowych odbywa się praktycznie natychmiastowo, automatycznie, nie wymuszając tworzenia nowej infrastruktury sprzętowej na terenie firmy. Bardzo łatwa skalowalność powoduje, że sprzęt "nie marnuje się", jest on wykorzystywany bardzo efektywnie - klient ponosi koszty zgodne z faktycznie generowanym obciążeniem, czerpiąc wymierne korzyści ze zjawiska ekonomii skali. W praktyce IaaS opiera się na mechanizmach wirtualizacji użytkownikowi oddawana jest do dyspozycji maszyna wirtualna, nie zaś faktyczna, pełna instalacja sprzętowa[27]. W praktyce IaaS to przede wszystkim publiczne i prywatne chmury: chmury publiczne - które udostępniają zasoby sprzętowe "w locie", zaś dostęp do nich odbywa się za pomocą Internetu. W zależności od dostawcy lub potrzeb klienta mogą one udostępniać całe fizyczne maszyny lub jedynie wirtualne instancje. Przykładami takich rozwiązań IaaS są: Amazon EC2[28], Microsoft Azure[29], Rackspace Mosso Cloud[30]; chmury prywatne - chmury działające "lokalnie", w obrębie korporacyjnego firewalla; zakładane są, gdy wymogi bezpieczeństwa są bardziej restrykcyjne. Przykłady takich rozwiązań stanowią: Eucalyptus[31], czy Nimbus[32]. 2.7 Multitenancy Multitenancy jest fundamentalnym podejściem architekturalnym charakteryzującym rozwiązania typu SaaS - określa zdolność systemu do obsługi wielu tenantów. Jako tenant rozumiana jest tu organizacja będąca klientem dostawcy usług SaaS; organizacja ta posiada wielu użytkowników końcowych będących właściwymi adresatami rozwiązania. W zależności od charakteru organizacji użytkownicy ci mogą być przykładowo pracownikami korporacji, czy klientami indywidualnymi firmy działającej na rynku IT. To głównie dzięki multitenancy możliwe jest wykorzystanie zjawiska ekonomii skali i tak znaczna redukcja kosztów utrzymania infrastruktury aplikacji, co procentuje zarówno z punktu widzenia dostawcy, jak i odbiorcy rozwiązania multitenant. 28

29 Zastosowanie podejścia multitenant wymusza jednak na dostawcy aplikacji całkowitą zmianę architektury w porównaniu do modelu singletenant i niesie za sobą wiele wyzwań natury technicznej. Rozdział ten krótko charakteryzuje zalety i wady multitenancy w porównaniu do innych podejść oraz nakreśla problemy, które może napotkać twórca architektury tego typu Architektury multitenant Multitenancy na poziomie systemu komputerowego może zostać zapewnione przez dwa różne podejścia[33]: wirtualizację multitenancy na poziomie infrastruktury zapewnione poprzez wykorzystanie technik wirtualizacji (przy czym technik tych może być bardzo dużo wirtualizacja jest tu więc potraktowana jako koncepcja, nie zaś konkretna technologia), przykładowo uruchomienie na tej samej infrastrukturze sprzętowej wielu instancji aplikacji, każdej w oddzielnej maszynie wirtualnej (systemie operacyjnym); multitenancy na poziomie aplikacji gdzie mechanizmy izolacji pomiędzy tenantami wbudowane są w aplikację, dzięki czemu aplikacja może być uruchomiona w jednej instancji, na pojedynczej infrastrukturze sprzętowej. Zależność między podejściem singletenant, a wirtualizacją i aplikacją w modelu multitenant zobrazowana jest na poniższym diagramie (Rys. 5). 29

30 Tenant 1 Tenant 2 Tenant 3 Tenant 1 Tenant 2 Tenant 3 Tenant 1 Tenant 2 Tenant 3 Wirtualizacja Multitenancy Aplikacja 1 Aplikacja 2 Aplikacja 3 Aplikacja 1 Aplikacja 2 Aplikacja 3 Aplikacja Single-tenant Multi-instance Multi-tenant Multi-instance Multi-tenant Single-instance Rys. 5. Zależność pomiędzy singletenancy, wirtualizacją i multitenancy Model, w którym obsługa wielu tenantów zapewniona jest poprzez techniki wirtualizacji może być traktowany jako faza przejściowa przed budową w pełni współdzielonego rozwiązania opartego o multitenancy na poziomie aplikacji (aczkolwiek efektywność obu podejść silnie zależy od charakteru aplikacji wśród największych dostawców usług SaaS wciąż istnieje podział na zwolenników wirtualizacji i tych, którzy twierdzą, że aplikacja SaaS musi być oparta o architekturę multitenant[34][35][36]). Szczegółowe porównanie wad i zalet podejść: singletenancy, wirtualizacja i multitenancy przedstawione zostało w kolejnych rozdziałach Izolacja tenantów Podczas gdy w przypadku standardowych aplikacji typu singletenant poszczególni tenanci odizolowani są od siebie fizycznie, już na poziomie infrastruktury sprzętowej, aplikacje multitenant muszą posiadać dodatkowe mechanizmy zapewniające separację i logiczną izolację na poziomie warstw samej aplikacji. Mechanizmy te stanowią pewnego rodzaju filtry w zależności od kontekstu, w jakim znajduje się aplikacja (czyli w praktyce od którego tenanta nadeszło żądanie) filtrują one współdzielone zasoby (bazę danych, system plików, 30

31 komponenty aplikacji) zezwalając na dostęp jedynie do tych, które należą do tenanta i tym samym dzieląc je na logiczne partycje, co pozwala na uzyskanie izolacji. Tenant 2 Przełącznik Kontekstu Tenant 1 Tenant 3 CSS, logo, konfiguracje interfejsu Zasób Tenanta 2 Obiekty biznesowe, konfiguracje procesów Zasób Tenanta 2 Zasób Tenanta 1 Zasób Tenanta 3 Bazy danych, pliki, wpisy w katalogu LDAP Zasób Tenanta 2 Zasób Tenanta 1 Zasób Tenanta 3 Zasób Tenanta 1 Zasób Tenanta 3 Filtry Warstwy Prezentacji Filtry Warstwy Biznesowej Filtry Warstwy Dostępu do Danych Aktualny Kontekst: Tenant 1 Warstwa Prezentacji Warstwa Biznesowa Warstwa Dostępu do Danych Rys. 6. Mechanizm selektywnego dostępu do zasobów w aplikacjach multitenant Wykorzystanie warstwy selektywnego dostępu stanowi główną charakterystykę, z punktu widzenia architektury, aplikacji typu multitenant i tym samym podstawową różnicę w porównaniu z modelami singletenancy i opartymi na wirtualizacji. Warstwa ta ma krytyczne znaczenie od niej zależy bezpieczeństwo danych tenantów, dlatego deweloperzy aplikacji multitenant muszą szczególnie zadbać o jakość implementacji mechanizmów selektywnego dostępu i ustalających aktualny kontekst. 31

32 2.7.3 Multitenancy a singletenancy Aplikacje typu singletenant zawsze wymagają dedykowanej infrastruktury sprzętowo-programowej (składającej się z, między innymi, sprzętu komputerowego, sieciowego, instancji aplikacji, bazy danych, ale także ludzi odpowiedzialnych za utrzymanie całego systemu i jego administrację), aby obsłużyć pojedynczego tenanta, podczas gdy rozwiązania multitenant są zdolne, za pomocą takiej samej, pojedynczej infrastruktury, obsłużyć wielu tenantów na raz. Z punktu widzenia użytkowników korzystanie z aplikacji multitenant niczym nie różni się od aplikacji singletenant - nie zdają oni sobie często sprawy, że ta sama instancja obsługuje również wiele innych organizacji. Jest to osiągalne dzięki mechanizmom izolacji każdego z tenantów. Izolacja jest kluczowa dla architektur typu multitenant - ujawnienie wrażliwych danych organizacji jej konkurentom miałoby daleko idące negatywne konsekwencje zarówno dla samego tenanta, jak i dostawcy aplikacji - oprócz utraty zaufania swoich istniejących klientów, "zła sława" stworzona przez prasę po takim incydencie mogłaby skutecznie uniemożliwić pozyskanie nowych. Dlatego też twórcy aplikacji multitenant szczególny nacisk kładą na mechanizmy izolacji i autoryzacji w dostępie do danych. Kolejnym istotnym aspektem w porównaniu podejść singletenant i multitenant jest stabilność aplikacji - podczas gdy ewentualna awaria, czy poważny błąd systemu obsługującego pojedynczego tenanta niesie ze sobą konsekwencje jedynie dla jego organizacji, awaria systemu typu multitenant powoduje przerwę w usługach świadczonym wielu organizacjom naraz, co ma o wiele poważniejsze negatywne skutki dla dostawcy aplikacji. Zamiast jednego klienta może on bowiem utracić wszystkich. Aplikacje, których pojedyncze instancje obsługują pojedynczych tenantów, łatwiej jest dostosować do niestandardowych wymogów klienta. Zmiany można bowiem zawrzeć bezpośrednio w kodzie lub konfiguracji aplikacji, każda z instancji może być dowolnie dostosowana zgodnie z życzeniem klienta. Nie jest to możliwe w przypadku aplikacji multitenant - jako że ten sam kod obsługuje wszystkich tenantów, musi on pozostać uniwersalny. Dlatego też tworzone są specjalne mechanizmy pozwalające na personalizację aplikacji bez zmiany kodu. Pozwalają one na "przekształcenie" aplikacji w czasie działania, zgodnie z ustawieniami aktualnie z niej korzystającego tenanta; ustawienia te 32

33 przechowywane są w postaci odizolowanych konfiguracji, a ich zastosowanie odbywa się całkowicie niezależnie. Z punktu widzenia deweloperów rozwój aplikacji multitenant jest łatwiejszy, gdyż muszą oni utrzymywać kod tylko w jednej wersji; w przypadku singletenancy zmuszeni są oni do utrzymywania wielu wersji aplikacji (po jednej dla każdego z tenantów), często przeznaczonych na różne platformy operacyjne, co utrudnia wprowadzanie poprawek i rozbudowę funkcjonalności. Pozytywną konsekwencją wykorzystania pojedynczej instancji do obsługi wszystkich tenantów jest także lepsza jakość kodu i co za tym idzie satysfakcja klienta - dostawca aplikacji dysponuje bowiem informacjami od całej społeczności użytkowników, ewentualne błędy, czy spadki wydajności są szybciej wykrywane i lepiej diagnozowane, a poprawki i nowe funkcje widoczne są natychmiastowo u wszystkich tenantów. Z drugiej strony tak zwane wymuszane uaktualnienia mogą stanowić wadę z punktu widzenia użytkowników. Poniższa tabela (Tab. 2) przedstawia zestawienie najważniejszych elementów odróżniających podejścia singletenancy i multitenancy: Instalacja Koszt dla jednego tenanta Wdrożenie nowego tenanta Wykorzystanie możliwości sprzętu Singletenancy Osobna instancja i infrastruktura sprzętowa dla każdego tenanta Bardzo duży; koszt pojedynczej infrastruktury Bardzo wolne; niezbędna jest instalacja odpowiedniej infrastruktury sprzętowej i oprogramowania Często bardzo niewielkie; każda z maszyn wykorzystana w małym stopniu Multitenancy Ta sama instancja i infrastruktura sprzętowa dla wszystkich tenantów Mały; koszt infrastruktury podzielony przez liczbę tenantów Automatyczne, natychmiastowe Optymalne; kolejna infrastruktura sprzętowa instalowana dopiero, gdy poprzednia wykorzystywana jest w stopniu maksymalnym 33

34 Izolacja tenantów Konfigurowalność Konsekwencje awarii Kod źródłowy Skalowalność Bardzo duża; fizyczna izolacja Bardzo duża; na poziomie kodu źródłowego Dla pojedynczego tenanta Wiele różnych wersji; oddzielne uaktualnienia Bardzo duża; zawsze można dodać kolejną instalację sprzętowoprogramową (abstrahując od kosztów) Średnia; izolacja w warstwie dostępu do danych Mniejsza; zależna od mechanizmów wbudowanych we framework, na poziomie metadanych Dla wszystkich tenantów Jedna wersja; uaktualnienia wymuszane Zależy; w przypadku zastosowania mechanizmów równoważenia obciążenia bardzo duża; w przeciwnym wypadku ograniczona przez możliwości jednej maszyny lub aplikacji Tab. 2. Różnice pomiędzy singletenancy a multitenancy Multitenancy a wirtualizacja Wirtualizacja to technika, dzięki której możliwe jest stworzenie pewnego rodzaju abstrakcji dostępnych zasobów i wirtualnej infrastruktury w obrębie tej samej instalacji sprzętowej[37]. W przypadku aplikacji SaaS umożliwia to wykorzystanie tej samej infrastruktury do uruchomienia wielu instancji aplikacji, z których każda obsługuje innego tenanta. Jest to alternatywa dla pełnego multitenancy na poziomie aplikacji. Najczęstszym przykładem wykorzystania wirtualizacji jest zastosowanie maszyn wirtualnych emulujących oddzielne warstwy sprzętowe. Na pojedynczej infrastrukturze sprzętowej uruchomione może być więc kilka instancji takich maszyn, każda wyposażona we własny system operacyjny i uruchomioną instancję aplikacji obsługującą pojedynczego tenanta. Przykładem takiego rozwiązania jest Microsoft Virtual Server[38]. Innym podejściem są wirtualne usługi. Zapewniają 34

35 one wirtualizację na wyższym poziomie niż w przypadku wirtualnych maszyn - korzystają z tego samego jądra systemu operacyjnego w przypadku niskopoziomowych operacji trybu jądra (sterowniki sprzętowe, sieciowe) tworząc wirtualne partycje umożliwiające oddzielenie dopiero aplikacji działających w trybie użytkownika, co pozwala na pewną oszczędność zasobów obliczeniowych w porównaniu z kosztownymi maszynami wirtualnymi. Dostępne na rynku rozwiązania tego rodzaju to Parallels Virtuozzo Containers[39] i Solaris Containers[40]. Oba podejścia - wirtualne maszyny i wirtualne usługi (kontenery) - wymagają jednak najczęściej statycznej prealokacji zasobów dla każdego z tenantów, co sprawia, że wirtualizacja jest o wiele kosztowniejszym rozwiązaniem w porównaniu z aplikacjami multitenant - zarówno z punktu widzenia dostawcy usług, jak i jego klientów. Oprócz wirtualizacji opartej na statycznej alokacji zasobów na rynku są dostępne także rozwiązania dynamiczne. Przykładem takiego rozwiązania są wirtualne sesje użytkownika - zasoby alokowane są dopiero po nawiązaniu sesji i zwalniane wraz z jej końcem (przykładowo Microsoft Remote Desktop Services[41] usługi te zostały jednakże zaprojektowane w celu umożliwienia użytkownikom zdalnego dostępu do pulpitu, nie zaś z myślą o wirtualizacji dla aplikacji multitenant, nie oferują więc zbyt wysokiej skalowalności). Istnieją również rozwiązania oparte o "piaskownice" (sandbox) aplikacji, działających zarówno po stronie serwera, jak i klienta. Piaskownice działające na serwerze stanowią pule procesów systemu operacyjnego obsługujących żądania pochodzące z aplikacji; procesy te są odizolowane, dzięki czemu ewentualne problemy z ich stabilnością nie mają wpływu na resztę systemu, co poprawia ogólną wydajność i bezpieczeństwo aplikacji. Podejście to można zrealizować za pomocą puli aplikacji (Application Pool) dostarczanej jako jedna z funkcjonalności serwera Microsoft IIS[42]. Piaskownice po stronie klienta działają na zasadzie strumieniowania aplikacji i uruchamiania jej na maszynie klienckiej, za pomocą odpowiednio dostosowanego i skonfigurowanego środowiska. Przykładami systemów udostępniających takie możliwości są: Symantec Workspace Streaming[43], Citrix XenApp[44], czy Microsoft App-V[45]. Takie rozwiązanie wydaje się być szczególnie przydatne, kiedy cienki klient nie jest wystarczający, czyli na przykład aplikacja wymaga rozbudowanego i skomplikowanego interfejsu użytkownika[46]. Niewątpliwą zaletą podejścia opartego na wirtualizacji jest szybkość jego wdrożenia i możliwość uniknięcia konieczności przeprojektowania aplikacji. Czy to z powodu braku niezbędnych zasobów (pieniężnych, czasowych, ludzkich), czy wysokiego ryzyka związanego z takim przedsięwzięciem, dostawca usług SaaS 35

36 może chwilowo wybrać wirtualizację zamiast pełnego rozwiązania multitenant. Pozwala to na początkowe testy zachowania aplikacji SaaS z punktu widzenia klientów i zbadanie zapotrzebowania rynku na takie usługi. Wirtualizacja zapewnia również lepszy poziom izolacji i bezpieczeństwa, a także większe możliwości dostosowania jakości usług do wymagań poszczególnych tenantów. Na szerszą skalę jednakże wirtualizacja praktycznie zawsze okazuje się być mniej opłacalna od pełnych rozwiązań typu multitenant. Środowiska wirtualne są skalowalne jedynie do pewnego stopnia (dużo mniejszego niż w przypadku multitenancy), przykładowo na jednym serwerze sprzętowym można utworzyć przeważnie bardzo ograniczoną liczbę maszyn wirtualnych (wyjątek stanowią mechanizmy Solaris Zones[40]), co w przypadku rozbudowanych aplikacji obsługujących wielu tenantów pociąga za sobą konieczność znacznej rozbudowy infrastruktury i ogranicza korzyści płynące ze zjawiska ekonomii skali. Mogą również pociągać za sobą problemy z automatycznym provisioningiem aplikacji oraz innymi niezbędnymi usługami. Poniższa tabela (Tab. 3) zestawia podejścia wirtualizacji (przy założeniu wykorzystania podstawowych mechanizmów, takich jak wirtualne maszyny, czy kontenery) i multitenancy: Instalacja Koszt dla jednego tenanta Wykorzystanie możliwości sprzętu Izolacja Wirtualizacja Osobna instancja i maszyna wirtualna na współdzielonej infrastrukturze dla każdego tenanta Średni; koszt infrastruktury podzielony przez liczbę maszyn wirtualnych, które można na niej uruchomić Średnie; duży nakład stwarzany przez mechanizmy wirtualizacji Duża; izolacja na poziomie infrastruktury Multitenancy Ta sama instancja i infrastruktura sprzętowa dla wszystkich tenantów Mały; koszt infrastruktury podzielony przez liczbę tenantów Optymalne; kolejna infrastruktura sprzętowa instalowana dopiero, gdy poprzednia wykorzystywana jest w stopniu maksymalnym Średnia; izolacja w warstwie dostępu do danych 36

37 Kod źródłowy Konieczność zmian w aplikacji Skalowalność Wiele różnych wersji; oddzielne uaktualnienia (można jednak zautomatyzować) Żadna; kod aplikacji pozostaje niezmieniony Średnia, zależna od zastosowanego rozwiązania; przykładowo na jednym serwerze można utworzyć tylko kilka maszyn wirtualnych Jedna wersja; uaktualnienia wymuszane Duża; przeważnie wymaga przeprojektowania całej aplikacji i rozległych zmian w kodzie Zależy; w przypadku zastosowania mechanizmów równoważenia obciążenia bardzo duża; w przeciwnym wypadku ograniczona przez możliwości jednej maszyny lub aplikacji Tab. 3. Różnice pomiędzy wirtualizacją a multitenancy Potencjalne wyzwania Przejście z modelu singletenant na model multitenant pociąga za sobą kilka trudnych do rozwiązania problemów[47][48]: koszty modyfikacji architektury - niezależnie od tego, jak zostanie przeprowadzony proces przejścia na model multitenant (przeprojektowanie całej aplikacji lub też wbudowanie w istniejącą architekturę elementów odpowiedzialnych za mechanizmy multitenancy) niesie to za sobą spore nakłady pieniężne i czasowe; często małe przedsiębiorstwa nie mogą pozwolić sobie na takie wydatki; bezpieczeństwo - dane wszystkich tenantów przechowywane będą w jednej bazie danych, co wywołuje przeważnie poważne obawy u klienta, dlatego też dostawca ponosi często dodatkowe koszty związane z zaprojektowaniem mechanizmów bezpieczeństwa i separacji danych poszczególnych tenantów; odnosi się to także do innych zasobów współdzielonych, takich jak system plików, artefakty JEE, czy Web Service'y; 37

38 hosting - niezależnie od tego, czy firma tworząca rozwiązanie multitenant utrzymuje aplikację na własnych serwerach, czy też zleca to firmie hostującej, stworzenie czy zakup odpowiedniej infrastruktury nie jest prostym zadaniem, przede wszystkim ze względu na wymogi stawiane przez aplikacje multitenant - specyficzne konfiguracje bazy danych, współdzielenie zasobów, większe przepustowości łącz, konieczność równoważenia obciążenia, skalowalność, itp.; zasoby ludzkie - architektury typu multitenant są bardziej wymagające, zarówno z architektonicznego, jak i wdrożeniowego punktu widzenia, dlatego też do stworzenia i utrzymania aplikacji tego typu niezbędny jest zespół doświadczonych programistów, architektów i administratorów; dostępność - aplikacja będzie obsługiwać wielu tenantów na raz, co oznacza wielokrotnie więcej użytkowników niż do tej pory, a w konsekwencji o wiele większy wpływ nawet drobnych błędów na wydajność i dostępność aplikacji; musi być więc ona gruntownie przetestowana, tak, by upewnić się, że nie mają miejsca przykładowo wycieki pamięci; możliwości personalizacji - w przypadku aplikacji multitenant możliwości personalizacji aplikacji zgodnie z potrzebami poszczególnych tenantów, ze względu na wspólny kod źródłowy, mogą być bardzo ograniczone, podczas gdy w przypadku aplikacji singletenant takie ograniczenia praktycznie nie istnieją; zależy to jednak w dużej mierze od rodzaju aplikacji; poziom jakości usług - więksi klienci często oczekują lepszej niż standardowa jakości usług, zaś w przypadku aplikacji multitenant może to być trudne do zapewnienia; wymuszane uaktualnienia - ze względu na wspólną bazę kodów źródłowych ewentualne patche i uaktualnienia są widoczne przez wszystkich tenantów, nie mają oni możliwości wyboru wersji, z której chcą korzystać; provisioning - aplikacje multitenant, w przeciwieństwie do singletenant, muszą posiadać mechanizmy pozwalające na, w miarę możliwości, automatyczny provisioning (czyli dostosowanie aplikacji do obsługi nowego tenanta) nie przerywający działania aktualnej instancji aplikacji. 38

39 Bardziej szczegółowa, techniczna analiza problemów mogących wystąpić podczas przenoszenia aplikacji na model multitenant przedstawiona jest w rozdziale 3 MEF założenia i analiza. 2.8 Platformy SaaS Platforma SaaS stanowi warstwę programową lub sprzętową (komercyjne rozwiązania udostępniają przeważnie oba środowiska jednocześnie) umożliwiającą aplikacjom przez nią wspieranym na działanie jako system wspierający multitenancy, dostępny na żądanie (w formie usług), bez konieczności bezpośredniego implementowania dedykowanej architektury i modelu dystrybucyjnego[49]. W praktyce, podobnie jak w przypadku każdego innego rodzaju platformy, jest to zbiór produktów, narzędzi i usług mających za zadanie ułatwić stworzenie i dostarczenie klientom kompletnej aplikacji. Od standardowych platform odróżnia je przede wszystkim środowisko udostępniania aplikacji (a często i działania samej platformy), czyli chmura. Aplikacje SaaS działają w chmurze, platformy wspierające je muszą więc uwzględnić specyficzny, bardziej skomplikowany model kolejnych warstw takich aplikacji, zapewnić obsługę wielu tenantów, a także dostarczać komponentów, które nie mają zastosowania w przypadku standardowych aplikacji (takich jak na przykład komponent dokonujący pomiarów obciążenia systemu przez poszczególnych tenantów, czy komponent naliczający opłaty). Platformy SaaS często same w sobie działają w chmurze i są dostępne jako usługa na żądanie (w takim przypadku stanowią równocześnie rozwiązania typu PaaS) Rodzaje platform SaaS Ze względu na sposób wykorzystania i charakterystykę komponentów dostarczanych przez platformy SaaS możemy je podzielić na następujące kategorie[50]: Platformy sprzętowe (delivery platforms) - dostarczają platformy uruchomieniowej i zasobów sprzętowych eliminując konieczność tworzenia własnej infrastruktury sprzętowej przez dostawcę aplikacji SaaS. Zasoby te 39

40 obejmują serwery aplikacyjne, bazodanowe, elementy sieciowe, itp. Ze względu na sposób udostępniania takich zasobów klientom sprzętowe platformy SaaS można podzielić na dwa rodzaje: o Zarządzany hosting (managed hosting) - bardzo podobny do standardowego hostingu, dostosowany jednakże do wymogów aplikacji SaaS; polega na zakupie infrastruktury sprzętowej u dostawcy takiej platformy, który zarządza nią i zapewnia odpowiedni poziom usług. Podejście takie umożliwia klientom dowolny wybór komponentów i ich dostosowanie do potrzeb swojej aplikacji. Przykładowi dostawcy: OpSource[51], IBM[52], Savvis[53]. o Przetwarzanie w chmurze (Cloud computing) - gdzie platforma sprzętowa znajduje się w chmurze i jest dostępna jako usługa na żądanie; opiera się na wirtualizacji zasobów, dzięki czemu możliwe jest bardzo szybkie skalowanie w górę i w dół, w zależności od aktualnego obciążenia aplikacji. W porównaniu do zarządzanego hostingu oferuje o wiele łatwiejszy sposób i dużo krótszy czas zestawienia niezbędnych komponentów. Z drugiej strony rozwiązanie to opiera się na współdzieleniu przez aplikacje zasobów sprzętowych, co może nie odpowiadać niektórym klientom, mniejsze są także możliwości dostosowania infrastruktury do niestandardowych wymagań. Najbardziej znanym dostawcą tego rodzaju platform jest Amazon (Amazon EC2)[28]. Platformy deweloperskie (development platforms) - są to platformy dostarczające komponentów do wykorzystania podczas tworzenia aplikacji SaaS. Mogą one również dostarczać narzędzi przydatnych przy integracji z istniejącymi już aplikacjami. Często są zintegrowane z platformami sprzętowymi stanowiąc kompletną infrastrukturę wdrożeniową i udostępniające API pozwalające do korzystania z niej. Generalnie można wyróżnić trzy rodzaje platform deweloperskich: o Tradycyjne środowiska programistyczne - takie, jak JEE, czy.net, nastawiane generalnie na tworzenie aplikacji działających w Internecie, niedostarczające specyficznych dla SaaS narzędzi, jednakże umożliwiające ich stworzenie. o Środowiska programistyczne działające w chmurze - których komponenty dostosowane są do charakterystyki rozwiązań SaaS i tworzą podstawową infrastrukturę programową aplikacji, dzięki czemu deweloperzy nie muszą samodzielnie projektować elementów architekturalnych SaaS - gotowe rozwiązania (na przykład 40

41 zapewniające obsługę wielu tenantów przez pojedynczą aplikację) są wbudowane w platformę. Komponenty te dostępne są jako usługi na żądanie. Wadą takiego podejścia jest uzależnienie aplikacji od danej platformy - przenosiny na inną platformę mogą być bardzo trudne lub wręcz niemożliwe. Przykładowymi firmami oferującymi takie rozwiązania są Bungee Labs[54], Apprenda[26] oraz Google (Google App Engine[14]). o Platformy typu mashup - zasadą działania zbliżone do wspomnianych w poprzednim punkcie, z tą różnicą, że składające się z o wiele bardziej złożonych komponentów, dostarczających nie tylko implementacji typowych dla SaaS mechanizmów, ale także spełniających określone funkcje biznesowe (przykładowo kalendarz). Z takich komponentów można stworzyć kompletną aplikację, często w bardzo prosty sposób (typu przeciągnij-upuść) i bez konieczności bycia programistą. Platformy takie wymuszają jednakże zastosowanie określonego podejścia architekturalnego i nadają się tylko do pewnego typu aplikacji, są mało elastyczne, co w przypadku większych aplikacji jest poważnym ograniczeniem. Przykładem takiej platformy jest Rollbase[23]. Platformy zorientowane na aplikację - udostępniają platformę stworzoną na potrzeby istniejącej już aplikacji SaaS. Platforma taka udostępnia narzędzia (API, języki, edytory GUI) umożliwiające zintegrowanie nowo tworzonych aplikacji z aplikacją centralną, rozszerzając lub dostosowując jej funkcjonalność, lub też stworzenie całkowicie nowych aplikacji działających na platformie. Platformy takie stworzone były w celu umożliwienia bardziej wymagającym klientom centralnej aplikacji SaaS lepszego dostosowania jej do swoich potrzeb i procesów biznesowych, a z czasem rozwinęły się w pełnowymiarowe platformy SaaS. Podejście takie umożliwia twórcom nowych aplikacji dotarcie do istniejącej już bazy klientów dostawcy platformy, zaś klientom oferuje rozszerzone możliwości wykorzystania aplikacji centralnej. Czołowym przedstawicielem tego podejścia jest Salesforce.com ze swoją platformą Force.com[25]. Innymi przykładami są Webex[55] i Netsuite[19] (udostępniają one jedynie API). 41

42 2.8.2 Platforma SaaS a PaaS i IaaS Powyższa kategoryzacja jako przykłady podawała rozwiązania wspomniane już przy okazji PaaS (Platform as a Service), czy IaaS (Infrastructure as a Service). Można więc na tej podstawie wyciągnąć wnioski, że PaaS, IaaS i platformy SaaS nie są pojęciami całkowicie rozdzielnymi. W pewnym stopniu pokrywają się one - rozwiązanie w modelu PaaS, czy IaaS może być jednocześnie platformą SaaS; wśród rozwiązań dostępnych na rynku jest to bardzo częste zjawisko. Czym więc różni się platforma SaaS od PaaS? Oba te modele dostarczają platform wspomagających tworzenie lub działanie aplikacji, oba są również powiązane z SaaS, jednakże platforma SaaS wspomaga wyłącznie aplikacje typu SaaS, zaś PaaS może stanowić platformę dla dowolnego typu aplikacji. Drugą główną różnicą jest sposób udostępniania komponentów platformy - PaaS, podobnie jak SaaS, działa w chmurze i udostępniany jest jako usługa na żądanie, zaś platforma SaaS nie specyfikuje sposobu dostępu do swoich komponentów (przy czym w praktyce często działają one w chmurze, stanowiąc rodzaj PaaS - dlatego też te dwa pojęcia są często używane zamiennie). Do PaaS często można zaliczyć deweloperskie i zorientowane na aplikację platformy SaaS. Różnice pomiędzy (sprzętową) platformą SaaS a IaaS są analogiczne, jak w przypadku PaaS. Sprzętowe platformy SaaS służą zawsze do wspomagania aplikacji typu SaaS, niekoniecznie działając w chmurze, zaś główną charakterystyką IaaS jest właśnie działanie w chmurze i udostępnianie architektury sprzętowej na żądanie. Jest to jedynie teoria - istniejące w praktyce platformy SaaS działają prawie zawsze w chmurze, opierając się na mechanizmach wirtualizacji i stanowiąc tym samym podzbiór IaaS. 42

43 3 MEF założenia i analiza Rozdział ten stanowi analizę dziedziny MEF Multitenancy Enablement Framework. Przed przystąpieniem do implementacji zidentyfikowanych zostało wiele potencjalnych problemów mogących wystąpić przy adaptacji aplikacji JEE na model SaaS. Większość tych problemów przedstawiona została w niniejszym rozdziale; pozostałe zostały odrzucone jako wykraczające poza zakres pracy ze względu na prezentowaną trudność lub czasochłonność (takimi zagadnieniami są przykładowo problemy związane z równoważeniem obciążenia, czy identyfikacją tenanta w aplikacjach asynchronicznie przetwarzających żądania użytkownika). Niektóre z prezentowanych problemów posiadają więcej niż jedno rozwiązanie wszystkie z nich są opisane, po czym dokonywany jest i uzasadniany wybór jednego z nich. 3.1 Założenia Przed przystąpieniem do implementacji poczynione zostały pewne założenia określające zakres odpowiedzialności frameworku, nakreślające ograniczenia rozwiązania, a także wybory technologiczne. Ustanawiają one obszar analizowanych w dalszej części problemów i stanowią jednocześnie wysokopoziomowe założenia dla MEF. W podrozdziale tym przedstawione zostały główne z nich Java Językiem implementacyjnym i jednocześnie platformą, dla jakiej przeznaczony jest MEF jest Java. Jest to podyktowane głównie dostępnością technologii (szeroki wybór, open source), a także przenośnością aplikacji napisanych w Javie i popularnością platformy JEE. 43

44 3.1.2 Framework Stworzone w ramach niniejszej pracy rozwiązanie może być scharakteryzowane jako framework (w odróżnieniu od platformy różnice pomiędzy tymi dwoma pojęciami nakreślone zostały w rozdziale 2.1 Framework a platforma ). Stanowi więc zbiór komponentów dołączanych do kodu na podobnych zasadach jak biblioteka. Komponenty te muszą zostać wykorzystane w ramach aplikacji, aby MEF mógł spełniać swoją rolę. Nie jest to platforma, a więc nie dostarcza środowiska uruchomieniowego dla aplikacji integrację z frameworkiem należy wykonać samodzielnie, a następnie wdrożyć i uruchomić aplikację na standardowym serwerze aplikacji Multitenancy W technicznej części termin multitenancy używany jest zawsze w odniesieniu do architektury aplikacji typu multitenant (w odróżnieniu od multitenancy na poziomie całego systemu komputerowego, które może być zapewnione także przez wirtualizację, jak to nakreślono w rozdziale Architektury multitenant ). Jest to główna charakterystyka tworzonego rozwiązania. Ma ono przede wszystkim udostępniać aplikacji mechanizmy zapewniające przeźroczystą obsługę wielu tenantów. Mimo że dojrzałe aplikacje SaaS charakteryzują się wieloma cechami (multitenancy, konfigurowalność, skalowalność, bezpieczeństwo, możliwość integracji z innymi rozwiązaniami, itp.), multitenancy stanowi z nich największe wyzwanie. Inne elementy zależą w dużej mierze od samej aplikacji, zaś celem niniejszej pracy nie jest implementacja aplikacji SaaS, a jedynie frameworku ułatwiającego jej zbudowanie z istniejącego standardowego rozwiązania typu singletenant. Z tego wynika również kolejne założenie Nieinwazyjność Założenie to polega przede wszystkim na próbie uniknięcia konieczności wprowadzenia zmian w istniejącej aplikacji. Oczywiście wątpliwe jest by możliwe było ich całkowite uniknięcie (szczególnie, że, jak to zaznaczono wcześniej, tworzony jest framework, nie platforma), ale przynajmniej ograniczenie ich do 44

45 niezbędnego minimum i to w zakresie konfiguracji, nie zaś implementacji. Może to być trudne, szczególnie w przypadku, gdy mechanizmy zapewniające multitenancy muszą być wstrzyknięte na poziomie logiki biznesowej. I to również pociąga za sobą kolejne z założeń Wykorzystanie Inversion of Control Inversion of Control (IoC) jest wzorcem projektowym opisującym architekturę systemu, w którym następuje odwrócenie kontroli przepływu w porównaniu do standardowego programowania proceduralnego. Przy zastosowaniu IoC to nie aplikacja wywołuje mechanizmy frameworku, a framework obejmuje kontrolę nad komponentami aplikacji. W praktyce podejście to przyjmuje formę Dependency Injection (DI), które polega na wstrzykiwaniu do komponentów aplikacji niezbędnych zależności i zasobów w czasie uruchomienia. Pozwala to na znaczne uniezależnienie logiki aplikacji od konkretnych implementacji interfejsów i przerzucenie decyzji implementacyjnych z kodu do konfiguracji. W kontekście MEF wykorzystanie techniki IoC pozwoli na łatwe wykorzystanie stworzonych komponentów poprzez uniknięcie wielu rozproszonych zmian w kodzie aplikacji i przeniesienie ich do centralnej konfiguracji. Najbardziej dojrzałym i rozpowszechnionym frameworkiem typu IoC jest Spring[5] (opisany w rozdziale Spring ), na którym będzie bazowało tworzone rozwiązanie Mapowanie obiektowo-relacyjne W aplikacjach typu JEE powszechne jest wykorzystanie frameworków udostępniających mechanizmy mapowania obiektowo-relacyjnego (ORM Object- Relational Mapping). Frameworki te mają za zadanie przystosowanie danych przechowywanych w modelu relacyjnym (a więc standardowym modelu wykorzystywanym przez wszystkie najpopularniejsze bazy danych) na odpowiednią dla aplikacji Java reprezentację obiektową. Znacznie ułatwia to korzystanie z danych, gdyż mechanizmy konwersji są przeźroczyste dla aplikacji i może ona korzystać z obiektów persystentnych w taki sam sposób, w jaki korzystałaby ze zwykłych obiektów przechowywanych w pamięci. Oprócz mapowania między modelami, frameworki ORM często udostępniają także bardziej zaawansowane techniki poprawiające wydajność komunikacji z bazą 45

46 danych. Jednym z przykładów jest wykorzystanie pamięci podręcznej (cache) do przechowywania obiektów już odczytanych z bazy (dzięki czemu przy odczycie można odwołać się do lokalnych danych nie tworząc kosztownych połączeń do bazy). Przykładowymi frameworkami ORM są Hibernate[56] i ibatis[57]. Mapowanie obiektowo-relacyjne zapewnione jest również przez JPA[58] (Java Persistence API). MEF zakłada (ale nie wymusza) wykorzystanie przez aplikację mechanizmów ORM i udostępnia komponenty specyficzne dla tego typu rozwiązań (przykładowo klasy wykorzystujące API Hibernate). 3.2 Problemy w warstwie dostępu do danych Zbudowanie rozwiązania typu multitenant może pociągać za sobą całkiem odmienne wyzwania w zależności od dziedziny danej aplikacji. Jednakże wspólnym problemem dla praktycznie wszystkich systemów SaaS jest zapewnienie multitenancy w warstwie dostępu do danych; często zaadresowanie problemów w tej warstwie rozwiązuje kwestie zapewnienia obsługi wielu tenantów w warstwach wyższych. Dlatego też w niniejszej pracy analizie warstwy dostępu do danych poświęcone jest najwięcej uwagi. Podstawowym zagadnieniem, jakie należy na tym poziomie zaadresować jest zapewnienie przeźroczystego z punktu widzenia wyższych warstw aplikacji dostępu do zasobów wielu tenantów. Mimo fizycznego współdzielenia przez nie tej samej lokalizacji (jedna baza danych, jeden serwer aplikacji), zapewniona powinna być jednocześnie logiczna separacja pomiędzy nimi, tak, jak gdyby znajdowały się one na oddzielnych serwerach. Poza właściwym miejscem przechowywania danych (najczęściej baza danych), głównym elementem warstwy dostępu do danych jest komponent DataSource, który powinien przede wszystkim umożliwiać dynamiczną, transparentną dla użytkownika, zmianę kontekstu. Innymi problemami, które należało rozważyć jest utrzymywanie puli połączeń do bazy oraz cache owanie. 46

47 3.2.1 Baza danych Przetwarzanie danych biznesowych to główne zadanie aplikacji typu JEE, zaś podstawowym mechanizmem przechowywania takich danych jest baza danych. Wśród współcześnie spotykanych rozwiązań wciąż dominuje podejście relacyjne, dlatego jedynie taki rodzaj baz rozważany jest w niniejszym rozdziale Problem Model on-premises udostępniania oprogramowania zakłada istnienie dedykowanej organizacji bazy danych, do której aplikacja ma technicznie (pomijając wynikające z logiki biznesowej przypadki ograniczonych uprawnień odczytu/zapisu) nieograniczony dostęp. W przypadku jednak aplikacji typu multitenant jedna instancja aplikacji musi korzystać z wielu różnych logicznych baz (abstrahując od ich faktycznej implementacji), gdyż obsługuje jednocześnie wielu różnych tenantów. Nie może więc korzystać z podlegającego jej źródła danych w sposób nieograniczony, dane muszą być rozdzielone na partycje i udostępniane tylko z obszaru podlegającemu aktualnemu tenantowi. Dodatkowym wymogiem stawianym przez niektóre z aplikacji SaaS podlegającej im bazie danych jest elastyczność modelu danych - pomimo tego, że każdy z tenantów prowadzi podobną działalność, ich zapotrzebowanie na treść przechowywanych danych może się różnić, gdyż różnią się ich procesy biznesowe. Dlatego też źródło danych powinno umożliwiać rozszerzenie modelu o zdefiniowane przez tenanta obiekty, zaś modyfikacja taka nie powinna mieć wpływu na działanie aplikacji z punktu widzenia pozostałych tenantów Możliwe rozwiązania Dedykowane bazy danych Jednym z podejść do przedstawionego problemu jest utrzymywanie fizycznie odseparowanej, dedykowanej bazy danych dla każdego tenanta. Rozwiązanie takie pozwala na dowolne dopasowanie struktury bazy do potrzeb danej organizacji nie tylko na tworzenie nowych pól, ale także na konstrukcję całych tabel. Dużą zaletą tego podejścia jest prosta implementacja oraz wysoka izolacja danych 47

48 pomiędzy instancjami aplikacji, co może mieć istotne znaczenie w niektórych przypadkach (np. bankowość). Innym plusem jest łatwość przywracania danych tenanta z kopii zapasowej. Proces przywracania danych nie wpływa na działanie aplikacji innych tenantów, wystarczy przywrócić całą bazę z najnowszej kopii zapasowej. Przy integracji zaś istniejącej już aplikacji podejście to pozwala na uniknięcie poważnych zmian w kodzie źródłowym. Sporą wadą podejścia jest wysokie zapotrzebowanie na zasoby wynikające z fizycznego ograniczenia ilości baz danych na pojedynczym serwerze. Wzrastająca liczba tenantów szybko powoduje wzrost liczby serwerów, co skutkuje podwyższonymi kosztami utrzymania systemu. Tenant 1 Tenant 2 Tenant 3 Baza Danych Tenanta 1 Baza Danych Tenanta 2 Baza Danych Tenanta 3 Rys. 7. Warstwa dostępu do danych dedykowane bazy danych Współdzielona baza danych W podejściu ze współdzieloną bazą danych, wszyscy tenanci korzystają z tej samej bazy danych. W zależności od przyjętej techniki przechowywania danych, istnieje kilka możliwości postępowania: zastosowanie oddzielnych schematów lub współdzielonego schematu z predefiniowanym lub konfigurowalnym zestawem pól dodatkowych Oddzielne schematy Każdy z tenantów dysponuje własnym schematem bazy, dane każdego z nich są więc przechowywane w odrębnych tabelach. Bezpieczeństwo danych można 48

49 zapewnić już na poziomie bazy danych, ustalając odpowiednie prawa dostępu danego tenanta do schematu, jednak izolacja danych w tym podejściu jest mniejsza niż w przypadku odrębnych baz. Wykorzystanie domyślnego schematu pozwala na stosowanie tych samych, ogólnych zapytań SQL dla każdego z tenantów. Podejście to jest podobne do podejścia z dedykowanymi bazami danych pod względem prostoty implementacji oraz elastyczności modelu danych. Dodatkowo pozwala na umieszczenie większej liczby tenantów na pojedynczym serwerze baz danych. To obniża z kolei koszty modelu, dlatego rozwiązanie to jest odpowiednie dla organizacji, które mogą zaakceptować mniejszą izolację i bezpieczeństwo danych w zamian za niższe koszty utrzymania. Tenant 2 Tenant 1 Tenant 1 Schema Tenant 3 Tenant 2 Schema Baza Danych Tenant 3 Schema Rys. 8. Warstwa dostępu do danych dedykowane schematy Współdzielony schemat W przypadku tym do czynienia mamy z jednym schematem bazy danych, dzielonym pomiędzy wszystkich tenantów. W tabelach utrzymywana jest dodatkowa kolumna zawierająca identyfikator tenanta. Wiersze danego tenanta identyfikowane są po jego identyfikatorze. Rozwiązanie to cechuje najmniejsze zapotrzebowanie na zasoby sprzętowe, a więc najlepszy współczynnik ilości obsługiwanych tenantów do wydajności serwera bazy danych. Wymaga jednak dodatkowego nakładu programistycznego w celu zapewnienia odpowiedniej 49

50 izolacji danych różnych tenantów, nawet w przypadku nieprzewidzianych błędów lub ataków. Przywracanie danych w tym modelu jest bardziej problematyczne niż w przypadku poprzednich podejść. Wymaga usunięcia wszystkich wierszy danego tenanta z serwera produkcyjnego, a następnie skopiowania ich z tymczasowego serwera pomocniczego. W przypadku dużej ilości danych tenanta, proces ten wpływa negatywnie na czas działania bazy dla wszystkich pozostałych tenantów. Model ten jest najbardziej przydatny, gdy wymagana jest możliwość obsłużenia dużej liczby tenantów przy wykorzystaniu małej ilości serwerów. Tenanci jednak muszą zrezygnować z wysokiego poziomu izolacji danych w zamian za niski koszt rozwiązania. Dodatkowo rozwiązanie to jest praktycznie nierealizowalne w przypadku już istniejących aplikacji, gdyż wymagałoby wielu zmian w kodzie aplikacji wymuszonych przez nowy schemat bazy danych. Tenant 1 Tenant 2 Tenant 3 Baza Danych Rys. 9. Warstwa dostępu do danych współdzielony schemat Wybrane rozwiązanie Przy wyborze rozwiązania kierowano się dwoma czynnikami: oferowanym poziomem izolacji, który pośrednio przekłada się na oferowane bezpieczeństwo, 50

51 oraz prostotą implementacji. Podejściem stanowiącym kompromis pomiędzy nimi jest zastosowanie współdzielonej bazy z oddzielnymi schematami. Rozwiązanie to pozwala uniknąć konieczności zmiany oryginalnego schematu bazy (do tabel należałoby dodać kolumnę zawierającą informację o tenancie, do którego należy dany rekord), co byłoby konieczne w przypadku zastosowania schematu współdzielonego. Modyfikacja oryginalnego schematu stanowiłaby zbyt radykalną ingerencję w istniejącą aplikację i pociągałaby za sobą wiele trudności implementacyjnych związanych z zapewnieniem odpowiedniego poziomu izolacji danych. Dedykowane schematy (lub bazy) pozwalają na zachowanie oryginalnego modelu danych (wszystkie zapytania SQL mogą pozostać niezmienione) i oferują wysoki poziom izolacji danych poszczególnych tenantów. Umożliwiają także wykorzystanie dedykowanych obiektów DataSource (których znaczenie opisane zostało w kolejnym rozdziale), oferują większą skalowalność i są łatwiejsze w utrzymaniu pod względem administracyjnym DataSource DataSource jest standardowym elementem charakteryzującym bazodanowe aplikacje JEE i wykorzystywany jest jako centralny komponent warstwy dostępu do danych, stanowiący fabrykę połączeń (obiektów Connection) do fizycznego źródła danych, które reprezentuje. Spełnia więc dla aplikacji rolę sterownika udostępniającego mechanizmy dostępu do danych. Najczęściej spotykane implementacje umożliwiają dynamiczne pozyskiwanie i zwalnianie połączeń do bazy danych. DataSource posiada właściwości opisujące fizyczne źródło danych, ustawiane przez użytkownika. W zależności od implementacji może udostępniać bardziej zaawansowane mechanizmy, takie jak pule połączeń czy wsparcie dla rozproszonych transakcji. Pulowanie połączeń może w znacznym stopniu zwiększyć wydajność aplikacji, gdyż zamiast tworzenia i niszczenia połączenia przy każdorazowym dostępie do danych, ponownie wykorzystywane są i zwalniane już istniejące połączenia, utrzymywane w puli Problem W przypadku standardowych aplikacji obsługujących pojedynczego tenanta komponent DataSource reprezentuje pojedyncze źródło danych. Gdy z aplikacji 51

52 ma korzystać wielu tenantów jednocześnie DataSource musi posiadać wiedzę o sposobie organizacji danych (który przedyskutowany był w poprzednim punkcie Baza danych ) i zapewniać stosowną separację. W przeciwnym wypadku zwracane byłyby albo wszystkie dane (gdy zastosowany byłby model ze współdzielonym schematem), albo dane pochodzące z bazy/schematu należącego do innego tenanta (gdy zastosowany byłby model ze współdzieloną bazą/schematem); w zależności od konfiguracji DataSource mogły też po prostu nie zwrócić żadnych danych. Jest to oczywiście sytuacja niepożądana. Aby tego uniknąć odpowiednie filtrowanie danych musiałoby odbyć się na poziomie wyższych warstw aplikacji - logiki lub prezentacji. Jednakże powodowałoby to konieczność zmiany kodu samej aplikacji, czego, zgodnie z założeniami MEF, należy uniknąć. Aplikacja byłaby również bardziej podatna na ataki zewnętrzne i błędy implementacyjne. Dlatego najlepszym sposobem na zapewnienie bezpiecznego dostępu selektywnego do danych różnych tenantów jest zastosowanie odpowiednich mechanizmów na jak najniższym poziomie - poziomie DataSource Możliwe rozwiązania Dedykowane obiekty DataSource Podejście to zakłada wykorzystanie wielu obiektów DataSource, które tworzone są dynamicznie dla każdego tenanta. Obiekty te przechowywane byłby przez jeden nadrzędny DataSource (DelegatingDataSource) i z poziomu aplikacji byłyby niewidoczne (aplikacja korzystałaby bezpośrednio jedynie z DelegatingDataSource). To DelegatingDataSource zajmowałby się wyborem odpowiedniego podrzędnego DataSource w zależności od kontekstu (aktualnego tenanta). Po wybraniu (lub też utworzeniu) odpowiedniego DataSource DelegatingDataSource oddelegowywałby do niego wszystkie operacje dostępu do danych. Każdy DataSource dysponowałby oddzielnymi danymi uwierzytelniającymi w bazie danych (odpowiadającymi danym tenanta), dzięki czemu podejście takie jest bezpieczne - tenant nie jest w stanie uzyskać dostępu do danych innych tenantów z poziomu swojego DataSource, gdyż nie posiada on odpowiednich uprawnień, gwarantowana jest więc odpowiednia izolacja danych. Podejście to oferuje również elastyczność w przypadku, gdy niektórzy z tenantów dysponowaliby dedykowanymi bazami danych, niektórzy zaś współdzieliliby tą samą bazę różne obiekty DataSource mogłyby wskazywać na różne schematy w 52

53 niezależnych bazach danych, a zmiany w modelu przechowywania danych pociągałby za sobą jedynie modyfikacje na poziomie konfiguracji. Do wad tego rozwiązania należy przede wszystkim brak współdzielonej puli połączeń do bazy - każdy z komponentów DataSource implementowałby i wykorzystywał własną pulę. W przypadku stosowania zaawansowanych frameworków typu ORM problemem byłaby również pamięć podręczna (cache) przechowywująca obiekty już odczytane z bazy. Istniejące rozwiązania ORM (Hibernate, ibatis) tworzą pojedynczy cache związany z danym DataSource (z poziomu aplikacji widoczny byłby jeden DataSource - DelegatingDataSource) - dane różnych tenantów byłyby więc wymieszane w jednym obszarze cache, co może potencjalnie powodować błędy i dostęp do danych osób nieupoważnionych, gdyż odczytywane z pamięci podręcznej obiekty nie podlegałyby odpowiedniej selekcji i naruszona zostałaby izolacja danych. Baza Danych Dedykowany DataSource 1 Dane Tenanta 1 Aplikacja Delegating DataSource Dedykowany DataSource 2 Dane Tenanta 2 Dedykowany DataSource 3 Dane Tenanta 3 Rys. 10. Warstwa dostępu do danych dedykowane DataSource Współdzielony obiekt DataSource Rozwiązanie to opiera się na wykorzystaniu pojedynczego obiektu DataSource dla wszystkich tenantów. Taki współdzielony DataSource dokonywałby odpowiedniej konfiguracji dostępu do bazy danych przed każdym żądaniem. W ten sposób możliwa byłaby dynamiczna selekcja fizycznego źródła danych w zależności od aktualnego kontekstu (tenanta). W praktyce można to zrealizować odpowiednio parametryzując obiekt połączenia do bazy (Connection) lub też przefiltrowując zbiór wynikowy tak, aby do aplikacji zwrócone były tylko te dane, które należą do tenanta. Od zastosowanego modelu rozmieszczenia danych w bazie zależy to, którą metodę należy wybrać. Drugie podejście jest charakterystyczne w przypadku zastosowania schematu współdzielonego przez 53

54 wszystkich tenantów, jednakże w przypadku istniejących aplikacji jest nierealizowalne praktycznie, gdyż wymagałoby zastosowania odpowiednich klauzul na poziomie zapytań SQL, co silnie zależałoby od samych zapytań, które z kolei są już elementem danej aplikacji. W przypadku wybranego podejścia z dedykowanymi schematami, przed zwróceniem obiektu Connection należy wybrać odpowiedni schemat w bazie ("use tenant_schema"). Wszystkie zapytania, do schematów różnych tenantów, odbywają się wtedy z poziomu tego samego użytkownika bazy danych, za pomocą tych samych danych autoryzacyjnych (użytkownik ten musi posiadać więc domyślnie uprawnienia do wszystkich danych w bazie). Rozwiązanie to nie zapewnia takiego bezpieczeństwa jak rozwiązanie z dedykowanymi obiektami DataSource, dlatego należy upewnić się, że sama aplikacja nie umożliwia tworzenia użytkownikowi własnych zapytań do bazy lub robi to w sposób bezpieczny (tak by uniknąć możliwości wyboru przez użytkownika schematu poprzez wywołanie "use schema" lub zapisu "schema.table"). Z drugiej strony rozwiązanie to umożliwia współdzielenie puli połączeń, gdyż wszystkie połączenia odbywają się z poziomu jednego DataSource. Problem z cache pozostaje aktualny. Baza Danych Dane Tenanta 1 Aplikacja Współdzielony DataSource Dane Tenanta 2 Dane Tenanta 3 Rys. 11. Warstwa dostępu do danych współdzielony DataSource Rozwiązanie hybrydowe Rozwiązanie hybrydowe pozwala połączyć zalety obydwu wymienionych wyżej podejść. Polega ono na stworzeniu obiektu dostępu do bazy danych, w którym możliwa jest konfiguracja zarówno dedykowanych obiektów DataSource, wykorzystywanych przez pojedynczych tenantów, jak i DataSource współdzielonych przez wielu tenantów. Jeśli tenantowi zależy na dodatkowym 54

55 bezpieczeństwie, przy procesie provisioningu tworzony jest dla niego osobny DataSource, z oddzielnymi danymi dostępowymi do bazy i oddzielną pulą połączeń, jeśli nie - dołączany jest on do jednego z istniejących już obiektów DataSource, wykorzystujących domyślne dane dostępowe, i korzysta z niego razem z innymi tenantami, współdzieląc pulę połączeń. Jest to rozwiązanie dynamiczne, lepiej zaspokajające wymagania różnych tenantów mają oni możliwość wyboru pomiędzy bardziej kosztownym, bezpieczniejszym rozwiązaniem a tańszą, mniej bezpieczną opcją, w której zasoby współdzielone są pomiędzy wielu tenantów. Model hybrydowy ułatwia także skalowanie dostarcza naturalnych mechanizmów klasteryzacji baz danych bez potrzeby replikacji. Baza Danych Współdzielony DataSource Dane Tenanta 1 Dane Tenanta 2 Aplikacja Delegating DataSource Dedykowany DataSource 1 Dane Tenanta 3 Dane Tenanta 4 Dedykowany DataSource 2 Dane Tenanta 5 Rys. 12. Warstwa dostępu do danych DataSource - podejście hybrydowe Wybrane rozwiązanie Wybranym do implementacji rozwiązaniem jest, ostatnie z wymienionych, podejście hybrydowe. Jest to podyktowane oferowaną przez nie elastycznością i skalowalnością, a także największą, z punktu widzenia niniejszej pracy, wartością edukacyjną. Umożliwia łatwą zmianę podejścia do sposobu przechowywania danych i wybór pomiędzy oddzielnym schematem a dedykowaną bazą danych, a więc bardziej ekonomicznym a bezpieczniejszym rozwiązaniem, co w praktyce pozwala na zaadresowanie potrzeb szerszego grona potencjalnych klientów rozwiązania SaaS. Podejście to wciąż nie adresuje problemu cache został on rozwiązany na innym poziomie, opisanym w kolejnym rozdziale. 55

56 3.2.3 Cache W przypadku aplikacji opartych o framework ORM Object-Relational Mapping (JPA, Hibernate) szeroko wykorzystywana jest oferowana przez takie rozwiązania technologia pamięci podręcznej cache. Dzięki zastosowaniu techniki cache'owania można znacznie poprawić wydajność aplikacji opartych na bazach danych. Cache przechowuje lokalnie obiekty persystentne, dzięki czemu redukuje konieczność każdorazowej komunikacji z bazą danych. Zastosowanie cache'u jest niezbędne w większych aplikacjach charakteryzujących się intensywnym ruchem między bazą danych a serwerem aplikacji, do których niewątpliwie należą aplikacje typu SaaS. Cache w kontekście frameworków mapowania obiektowo-relacyjnego można podzielić na dwa rodzaje[59]: 1. Cache poziomu pierwszego (first-level cache) - jest to cache działający na poziomie pojedynczej sesji. Dzięki niemu możliwe jest zredukowanie ilości niezbędnych do wykonania na bazie zapytań SQL (na przykład w przypadku aktualizowania różnych atrybutów tego samego obiektu), co znacznie poprawia wydajność. 2. Cache poziomu drugiego (second-level cache) - jest to cache globalny, działający na poziomie klastra lub JVM (przykładowo w Hibernate jest to poziom fabryki sesji - komponentu SessionFactory). Przechowuje on lokalnie obiekty już pobrane z bazy danych, dzięki czemu aplikacja, na podstawie kluczy głównych, może uzyskać dostęp do danych bez komunikacji z bazą. W przeciwieństwie do cache'u poziomu pierwszego obiekty te dostępne są pomiędzy sesjami. Przedstawione poniżej rozważania na temat problemu i możliwych rozwiązań przy wykorzystaniu cache u stosują się jedynie do aplikacji opartych na technologiach ORM; w przypadku aplikacji korzystających ze standardowego API JDBC problem ten nie występuje. Rozważania mają charakter ogólny, niezależny od konkretnej implementacji frameworku ORM, jednak wykorzystana terminologia w dużej mierze opiera się na terminologii stosowanej przez Hibernate, jako że jest to najbardziej rozwinięty i zaawansowany framework mapowania obiektowo-relacyjnego, zaś jego API znane jest najszerszemu gronu czytelników. 56

57 Problem Wykorzystanie cache u poziomu pierwszego w aplikacji typu multitenant nie prezentuje sobą żadnych problemów, gdyż jest on zaimplementowany na poziomie sesji, które są powiązane z pojedynczym użytkownikiem, a więc tym samym odseparowane dla poszczególnych tenantów. W przypadku jednak cache u poziomu drugiego sytuacja jest trudniejsza, gdyż jest on współdzielony pomiędzy sesjami różnych użytkowników należących do odrębnych tenantów. Cache ten operuje w oparciu o klucze główne obiektów; klucze te nie muszą być unikalne dla danych należących do różnych tenantów, co może doprowadzić do kolizji pomiędzy obiektami przechowywanymi w pamięci podręcznej. Sytuacja taka może mieć miejsce, gdy każdy z tenantów ma do dyspozycji własny schemat w bazie danych. W przypadku, gdy w cache u znajduje się już obiekt o poszukiwanym kluczu głównym zostanie on zwrócony do aplikacji, niezależnie od tego, z jakiego schematu pochodził. Może to więc doprowadzić do nieuprawnionego dostępu do danych i naruszenia ich spójności. Mechanizmy cache'owania są bezpośrednio wbudowane we framework mapowania obiektowo-relacyjnego, dlatego ich wykorzystanie zależy od zastosowanej technologii. Utrudnia to znalezienie jednolitego rozwiązania dla problemu cache'u poziomu drugiego i wymusza rozpatrzenie sposobu implementacji rozwiązania w kontekście wykorzystywanego frameworku Możliwe rozwiązania SessionFactory SessionFactory jest to obiekt fabryki, odpowiedzialny za tworzenie nowych sesji dla użytkowników, a także za utrzymywanie cache'u poziomu drugiego. Możliwym rozwiązaniem problemu kolizji cache'u w przypadku aplikacji typu multitenant jest utrzymywanie osobnych komponentów SessionFactory dla każdego z tenantów. Odpowiedni SessionFactory wybierany byłby przez globalny DelegatingSessionFactory na podstawie identyfikatora aktualnego tenanta (analogicznie do rozwiązania zaproponowanego w przypadku dedykowanych obiektów DataSource). Dzięki temu każdy z tenantów miałby dostęp do własnego cache'u, co pozwoliłoby na uniknięcie kolizji i ujawnienia danych. Rozwiązanie takie jest intuicyjne i stosunkowo łatwe w implementacji. Dodatkowo możliwe jest 57

58 wykorzystanie tego samego obiektu DataSource przez wiele komponentów SessionFactory. Komponenty te jednak są najczęściej bardzo kosztowne w tworzeniu i utrzymywaniu, gdyż wczytują i utrzymują one w pamięci całą konfigurację mapowania i dostępu do źródła danych; dlatego też, w przypadku obsługi przez aplikację wielu tenantów, wydajność przy zastosowaniu tego podejścia mogłaby znacząco spaść[60][61][62]. Framework ORM Session Factory1 Cache Provider1 Cache1 Aplikacja Delegating Session Factory Session Factory2 Cache Provider2 Cache2 Session Factory3 Cache Provider3 Cache3 Rys. 13. Warstwa dostępu do danych Cache DelegatingSessionFactory CacheProvider CacheProvider jest to komponent posiadający bezpośrednią kontrolę nad cachem, z interfejsem pozwalającym na dostęp do cache'owanych obiektów lub dostarczającym pośrednio implementacji cache'u. Komponent taki wykorzystywany jest przez SessionFactory. Frameworki mapowania obiektoworelacyjnego dostarczają przeważnie kilku implementacji CacheProvider pozwalając na wybór użytkownikowi. Najczęściej też obok takiej funkcjonalności możliwe jest dostarczenie własnej implementacji CacheProvider. Pozwala to na zaprojektowanie cache'u tak, aby był on świadomy przynależności cache'owanych obiektów do poszczególnych tenantów. Może to się odbywać za pomocą komponentu DelegatingCacheProvider, który enkapsulowałby osobne instancje obiektów CacheProvider dla poszczególnych tenantów lub, w zależności od rozwiązania zastosowanego we frameworku, obiektów bezpośrednio reprezentujących cache. Wybór odpowiedniego CacheProvider następowałby w zależności od identyfikatora aktualnego tenanta, analogicznie jak w przypadku rozwiązania DelegatingSessionFactory czy DelegatingDataSource. Rozwiązanie 58

59 takie ma więc bardzo podobny charakter do zaproponowanego wcześniej DelegatingSessionFactory, jednakże potencjalnie zapewnia większą wydajność, ponieważ powielane są o wiele mniejsze obiekty, odpowiedzialne bezpośrednio za cache'owanie, nie zaś duże, wielozadaniowe komponenty, jakimi są SessionFactory. Z drugiej strony rozwiązanie to jest silnie zależne od wykorzystywanej technologii i trudniejsze do implementacji (lub też niemożliwe, w zależności od tego, jaką kontrolę nad komponentami cache'ującymi udostępnia framework). Framework ORM Cache Provider1 Cache1 Aplikacja Session Factory Delegating Cache Provider Cache Provider2 Cache2 Cache Provider3 Cache3 Rys. 14. Warstwa dostępu do danych Cache - DelegatingCacheProvider Prefiksowane regiony cache'u Rozwiązanie to opiera się na zastosowaniu osobnych regionów cache'u dla poszczególnych tenantów. Segmentację taką można uzyskać za pomocą prefiksów zastosowanych przed obiektami przechowywanymi w cache'u. Każdy z obiektów wstawianych do cache'u oznacza się odpowiednim prefiksem wskazującym jednoznacznie na tenanta, do którego dany obiekt należy (na przykład identyfikatorem tenanta). Zastosowanie takiego podejścia wymaga implementacji obiektu opakowującego CacheProvider. Obiekt taki przechwytywałby wszystkie wywołania dodające i pobierające obiekt z cache'u i odpowiednio nadpisywałby klucz nowym kluczem prefiksowanym identyfikatorem aktualnego tenanta, a następnie przekazywałby tak zmodyfikowany klucz oryginalnemu obiektowi cache'u. Dzięki temu obiekty różnych tenantów umieszczane byłyby w różnych regionach cache'u, co pozwoliłoby uniknąć kolizji. Rozwiązanie to nie wymaga tworzenia i utrzymywania osobnych obiektów cache'u dla każdego z tenantów; 59

60 niezbędny jest jedynie dodatkowy obiekt opakowujący zgodny z interfejsem CacheProvider. Framework ORM Cache Aplikacja Session Factory Object Tenant Aware Cache Provider TenantX Object Cache Provider TenantX Object Tenant1 Region Tenant2 Region Tenant3 Region Rys. 15. Warstwa dostępu do danych Cache prefiksowane regiony cache u Globalne klucze główne Podejście to polega na zapewnieniu, że obiekty tych samych klas, niezależnie od tenanta, do którego należą, będą miały unikalne identyfikatory. Innymi słowy generowanie kluczy głównych dla obiektów persystentnych powinno odbywać się globalnie dla wszystkich tenantów. W przypadku zastosowania podejścia ze schematem współdzielonym dla wszystkich tenantów takie zachowanie zapewnione jest domyślnie przez bazę danych, gdyż dane wszystkich tenantów przechowywane są w jednej tabeli, a więc generowane klucze główne są unikalne. Oczywiście założenie to przestaje obowiązywać w przypadku partycjonowania poziomego bazy danych. Wówczas, aby zapewnić unikalność, w skład klucza głównego można włączyć identyfikator tenanta, do którego należą poszczególne obiekty i taki klucz złożony pozostaje unikalny globalnie (przy założeniu, że wszystkie obiekty tego samego typu dla danego tenanta znajdują się w pojedynczej tabeli, co w przypadku bardzo dużych zbiorów może być trudne do spełnienia). W przypadku zastosowania podejścia z oddzielnymi schematami dla poszczególnych tenantów zadanie bardzo się komplikuje. W tabeli nie są dostępne identyfikatory tenantów, a więc nie jest możliwe stworzenie z nich klucza złożonego, zaś wbudowane mechanizmy generowania unikalnych kluczy ograniczają się do pojedynczych tabel. Można więc zaimplementować zewnętrzne mechanizmy generujące globalnie unikalne klucze główne dla obiektów różnych tenantów, czy 60

61 to w postaci triggera bazy danych, czy części logicznej aplikacji. Generator taki musi jednakże być globalny dla bazy danych, gdyż z bazy najprawdopodobniej korzystać będzie wielu użytkowników, zaś dane generowane mogą być przez wiele instancji aplikacji. Jak widać rozwiązanie takie może okazać się bardzo skomplikowane w realizacji praktycznej Wybrane rozwiązanie Wybierając optymalne rozwiązanie dla problemu cache kierowano się przede wszystkim narzutami pamięciowymi, zapewnieniem odpowiedniej izolacji danych oraz trudnościami implementacyjnymi podejścia. Odpowiednia izolacja zapewniona jest przez wszystkie z przedstawionych metod. Rozwiązanie zakładające powielanie obiektów odpowiedzialnych za tworzenie sesji (SessionFactory) jest zbyt obciążające pamięciowo w porównaniu do rozwiązania zakładającego powielanie tylko obiektów odpowiedzialnych za obsługę cache. Poza tym, nie wprowadza żadnych udogodnień związanych z powielaniem funkcjonalności innych niż obsługa cache. Rozwiązanie zakładające obsługę kluczy globalnych z kolei jest trudne w realizacji implementacja mechanizmu kluczy globalnych po stronie systemu zarządzania bazą danych zależna jest od wykorzystanego systemu, natomiast implementacja po stronie aplikacji wymaga sporo wysiłku w celu synchronizacji poszczególnych instancji. Rozwiązanie zakładające prefiksowanie kluczy jest rozwiązaniem dobrym. Implementacyjnie porównywalne jest do rozwiązania zakładającego powielanie obiektów CacheProvider - DelegatingCacheProvider. Z jednej strony prefiksowanie kluczy prowadzi do zwiększenia wielkości samych kluczy, oraz do przechowywania większej liczby obiektów w pojedynczym obiekcie cache (co wpływa na jego wydajność), z drugiej jednak wprowadzanie dodatkowych obiektów cache również powoduje niewielkie nakłady pamięciowe. DelegatingCacheProvider daje jednakże większą dozę elastyczności w wyborze implementacji cache różni tenanci mogą wykorzystywać różne implementacje niezależnie - w MEF wybrano więc właśnie to podejście. 61

62 3.2.4 System plików Mimo że specyfikacja JEE stanowczo odradza korzystanie z bezpośredniego dostępu do systemu plików przez komponenty biznesowe (zalecane jest wykorzystanie API odpowiednich managerów zasobów, takich jak przykładowo JCA Java EE Connector Architecture, czy standardowe JDBC), wiele aplikacji wciąż wykorzystuje pliki do przechowywania danych, przykładowo konfiguracji[63]. W przypadku projektu aplikacji multitenant od podstaw warto było by rozważyć więc zastąpienie danych przechowywanych w postaci plików bazą danych, jednakże zgodnie z założeniami MEF ingerencja w aplikację powinna być jak najmniejsza, dlatego dostęp do systemu plików rozważany jest tu jako problem, który powinien być niezależnie zaadresowany przez MEF. W aplikacjach Java dostęp do plików odbywa się za pomocą klas pakietu java.io; przykładowo plik reprezentowany jest przez obiekt java.io.file Problem Jeśli aplikacja podczas swego działania wykorzystuje dostęp do systemu plików, po przeniesieniu jej na platformę multitenant wystąpią liczne konflikty związane z próbami zapisu do i odczytu z tych samych plików przez różnych tenantów. Jest to problem trudny do rozwiązania, gdyż lokalizacje plików są przeważnie trwale związane z lokalizacją aplikacji. Powstaje również kwestia rozróżnienia rodzaju plików niektóre pliki powinny być współdzielone pomiędzy wszystkich tenantów, na przykład w przypadku plików globalnej konfiguracji aplikacji, podczas gdy inne zawierają wrażliwe dane lub też konfiguracje specyficzne dla pojedynczego tenanta i powinny pozostać niewidoczne dla pozostałych tenantów Rozwiązanie Rozwiązaniem tego problemu jest zapewnienie wszystkim tenantom przeźroczystego dostępu do osobnych obszarów lokalnego systemu plików. W tym celu, przede wszystkim, należy utworzyć osobną strukturę katalogową w ramach procesu provisioningu nowego tenanta. W ramach frameworku należy także zaimplementować własną warstwę dostępu do systemu plików, nadpisującą 62

63 mechanizmy z pakietu java.io. Niestety nie ma łatwego sposobu na wstrzyknięcie własnych implementacji dla klas z pakietu java.io, dlatego framework powinien eksponować własny interfejs dostępu do plików, który aplikacja musiałaby wykorzystywać. Nie odbyłoby się to zapewne bez zmian w kodzie oryginalnej aplikacji. Nowa warstwa dostępu do systemu plików musiałaby posiadać wiedzę na temat aktualnego tenanta, tak by wiedzieć, z którego obszaru systemu plików skorzystać. Wiedza ta byłaby dostępna przez globalny kontekst. Kontekst dostarczałby ID aktualnego tenanta, które następnie mapowane byłoby na nazwę odpowiedniego, przeznaczonego dla danego tenanta, katalogu. Plik do odczytania byłby dopiero wtedy odszukany w obszarze katalogu i udostępniony aplikacji do zapisu/odczytu. Ważne byłoby również zabezpieczenie przed dostępem do plików użytkowników do tego nieuprawnionych, np. należących do innego tenanta. Dostęp do plików globalnych dla aplikacji, współdzielonych przez wszystkich tenantów, odbywałby się bez zmian w stosunku do pierwotnej implementacji; także ich lokalizacja może pozostać niezmieniona LDAP Lightweight Directory Access Protocol (LDAP) jest protokołem komunikacyjnym do kontroli danych udostępnianych w ramach usług katalogowych. W praktyce usługi te zaimplementowane są jako rodzaj bazy danych przechowującej obiekty i opisujące je atrybuty w sposób logiczny i zhierarchizowany, za pomocą struktur drzewiastych. Charakterystyki te sprawiają, że katalogi LDAP są zorientowane na udostępnianie przede wszystkim danych identyfikacyjnych (przykładowo pracowników firmy pogrupowanych zgodnie ze, składającymi się na strukturę firmy, jednostkami organizacyjnymi, opisanych przez ich dane osobowe, dane dostępowe do systemów firmowych, itp.). Dodatkową zaletą są optymalizacje szybkości odczytu, stanowiącego znaczącą większość operacji wykonywanych na tego rodzaju danych. 63

64 Problem Wiele aplikacji korzysta z katalogów LDAP do uwierzytelniania i autoryzacji swoich użytkowników. Jeśli aplikacja taka ma obsługiwać wielu tenantów, niezbędne jest odpowiednie przystosowanie struktury katalogu LDAP. Rozważany będzie jedynie przypadek, kiedy stosowany jest scentralizowany model uwierzytelniania. W modelu rozproszonym, bowiem, każdy z tenantów dysponuje swoim serwerem LDAP, niezależnie od pozostałych tenantów, co przenosi problem do warstwy modułu uwierzytelniania i nie wpływa na strukturę danych LDAP. W scentralizowanym modelu uwierzytelniania dostępna jest jedna logiczna baza LDAP (w praktyce może ona być oczywiście fizycznie partycjonowana), która powinna obsługiwać wszystkich tenantów, co oznacza, że z poziomu aplikacji tenant powinien mieć możliwość zapisu nowych danych do katalogu LDAP, a także odczytu, jednakże jedynie tych danych, które należą do niego Możliwe rozwiązania Dedykowane poddrzewa W podejściu tym użytkownicy należący do różnych tenantów rozróżniani są już na poziomie Distinguished Name (DN). Przykładowo, podział na poddrzewa mógłby być zapewniony poprzez zastosowanie oddzielnych Domain Component (DC) dla różnych tenantów: dc=tenant1, dc=mef, dc=org i dc=tenant2, dc=mef, dc=org. Wykorzystanie dedykowanych poddrzew dla każdego z tenantów umożliwiałoby zaimportowanie dowolnego schematu, wykorzystywanego wcześniej przez tenanta, bez konieczności dokonywania w nim zmian. Jest to niewątpliwa zaleta, gdy zmiany w kodzie oryginalnej aplikacji należy zredukować do minimum, zaś potencjalni tenanci aplikacji dysponują już własnymi, rozbudowanymi bazami LDAP, których nie chcieliby modyfikować. Z drugiej jednak strony niezbędny byłyby dodatkowy komponent, który na podstawie identyfikatora tenanta określałby, według jakiego schematu uporządkowane są dane i jak je odszukać. 64

65 Współdzielony schemat Drugim rozwiązaniem jest współdzielenie przez wszystkich tenantów tego samego drzewa. Dane różnych tenantów rozmieszczone byłyby w obrębie jednego schematu, co wymuszałoby zachowanie unikalności nazw użytkowników na poziomie całej aplikacji, nie zaś jedynie poszczególnych tenantów. Efekt taki można uzyskać poprzez kombinację nazwy użytkownika z identyfikatorem tenanta. Wykorzystanie pojedynczego schematu jest zarówno zaletą, jak i wadą tego podejścia. Z jednej strony uprościłoby to komponent korzystający z LDAP, gdyż dane wszystkich tenantów odczytywane byłyby w ten sam sposób, z drugiej jednak strony małe jest prawdopodobieństwo, że struktury danych pochodzących od różnych tenantów byłyby takie same, istniałaby więc dodatkowa konieczność ich ujednolicenia i importu danych do centralnego katalogu LDAP. W praktyce może to być kłopotliwe, dlatego podejście to jest bardziej przydatne w przypadku, gdy tworzony jest od podstaw nowy katalog LDAP Wybrane rozwiązanie Rozwiązanie stosujące dedykowane poddrzewa wydaje się być lepszym podejściem, gdyż nie wymusza na tenantach stosowania określonego schematu danych, dzięki czemu możliwe jest wykorzystanie istniejącej już, korporacyjnej bazy LDAP i dowolne modyfikacje i rozszerzenia zgodne z nowymi wymaganiami. Rozwiązanie to z drugiej strony wymusza o wiele większy poziom elastyczności na samej aplikacji i stanowi większe wyzwanie z punktu widzenia MEF. 3.3 Problemy w warstwie logiki biznesowej i aplikacji Zapewnienie obsługi wielu tenantów w warstwie logiki aplikacji/biznesowej jest zadaniem bardziej wymagającym, niż w przypadku warstwy dostępu do danych. Budowa i wykorzystane w tej warstwie techniki są w dużym stopniu uzależnione od domeny konkretnej aplikacji, co uniemożliwia praktycznie zaprojektowanie komponentów mogących zaadresować w sposób uniwersalny wszystkie ewentualne wymogi. Warstwy dostępu do danych w większości aplikacji mają 65

66 bardzo zbliżoną architekturę, zadanie i zachowanie odczyt i zapis danych z zewnętrznego źródła, przy czym semantyka tych danych nie ma tu przeważnie większego znaczenia, dlatego łatwo jest opakować ten proces za pomocą dodatkowych mechanizmów. Inaczej jest w przypadku warstwy biznesowej, gdzie dane nabierają znaczenia, a różni tenanci mogą operować zgodnie z różnymi procesami. W przypadku standardowych aplikacji wdrażanych w modelu onpremises wystarczające jest odpowiednio zmodyfikować kod, tak, aby przetwarzanie odbywało się zgodnie z procesem biznesowym organizacji. W przypadku jednak aplikacji multitenant przetwarzanie musi być kierowane za pomocą pewnego rodzaju statycznych reguł wybieranych i stosowanych dynamicznie na podstawie identyfikatora aktualnego tenanta. Procesy te mogą mieć bardzo zróżnicowane postacie i dotyczyć wielu odmiennych elementów w zależności od domeny aplikacji, dlatego też zagadnienia tego typu są poza zakresem niniejszego opracowania. Przeanalizowane są jedynie problemy ogólne, charakteryzujące wszystkie aplikacje JEE i mogące zostać zaadresowane w sposób uniwersalny Provisioning Provisioning tenanta jest to proces obejmujący całość cyklu zarządzania kontem tenanta - od utworzenia, wprowadzania zmian, aż do zakończenia korzystania z usługi przez tenanta. Innymi słowy jest to przystosowanie aplikacji do obsługi tenanta. Oznacza to między innymi zarezerwowanie odpowiednich zasobów, utworzenia w systemie obiektów charakterystycznych dla danego tenanta (danych, katalogów), udostępnienie mu usług oferowanych przez system (w zależności od domeny, w której działa aplikacja) i możliwości ich konfiguracji Problem W kontekście SaaS najważniejszym aspektem provisioningu jest automatyzacja rejestracji nowego tenanta w systemie i dynamiczna alokacja zasobów - po subskrypcji usług SaaS tenant powinien mieć możliwość natychmiastowego zalogowania się i korzystania z aplikacji, bez żadnej zewnętrznej interwencji w działanie systemu. Niezbędne są więc odpowiednie mechanizmy tworzące lub 66

67 usuwające dane administracyjne, alokujące zasoby i uruchamiające procedury inicjalizacyjne lub finalizacyjne Rozwiązanie Mechanizmy provisioningu z reguły obejmują większość głównych komponentów składających się na aplikację SaaS. Poniżej przedstawione są podstawowe elementy, które powinny wchodzić w skład zautomatyzowanych procedur provisioningu. Nie są to wszystkie elementy, gdyż zależą one przede wszystkim od danej aplikacji. Niektóre z wymienionych elementów mogą być wywoływane na zasadzie leniwej inicjalizacji tworzone byłyby dopiero przy pierwszym wykorzystaniu. Provisioning może być więc procesem dynamicznym i niejednolitym Provisioning warstwy danych Provisioning warstwy danych obejmuje przede wszystkim zmiany, jakie należy dokonać w bazie danych, by umożliwić tenantowi korzystanie z niej. Dedykowane bazy danych - w przypadku tego podejścia należy dla każdego nowego tenanta utworzyć nową bazę danych z domyślnym schematem danych, a także utworzyć nowy wpis w danych konfiguracyjnych wskazujący danego tenanta jako użytkownika tej bazy. Współdzielona baza danych, dedykowane schematy - w tym przypadku pierwszym krokiem jest stworzenie w bazie schematu dla nowego tenanta, a następnie wypełnienie go domyślnymi tabelami. Następnym krokiem może być również dodanie tabel lub kolumn specyficznych jedynie dla danego tenanta. Wprowadzenie danych domyślnych - niezależnie, który z powyżej rozważonych schematów jest wykorzystywany, proces provisioningu danych najprawdopodobniej będzie wymagał również wprowadzenia do bazy pewnych domyślnych danych, by ułatwić tenantowi korzystanie z aplikacji i uprościć proces wstępnej konfiguracji. Alokacja miejsca w systemie plików jeśli aplikacja korzysta z plików niezbędne jest utworzenie odpowiedniej struktury na dysku twardym, tak aby odizolować dane tenanta w przypadku plików niewspółdzielonych. 67

68 Zaktualizowanie tabeli administracyjnej (metadane) - najprawdopodobniej w aplikacji, oprócz standardowych danych, przechowywane będą także metadane dotyczące konfiguracji aplikacji dla poszczególnych tenantów - w przypadku procesu provisioningu należy je zaktualizować dodając wpisy dotyczące nowego tenanta Provisioning dostępu do danych Provisioning dostępu do danych obejmuje utworzenie niezbędnych komponentów w warstwie dostępu do danych, czyli przykładowo DataSource utworzenie oddzielnej instancji (przydzielenie tenantowi własnej puli połączeń) lub też dodanie tenanta do istniejącej (współdzielenie puli przez tenantów) w zależności od stosowanego podejścia. Innym przykładem może być cache niezbędne jest utworzenie osobnej partycji dla nowego tenanta Provisioning serwera webowego/aplikacji Provisioning serwera dotyczy struktur, jakie trzeba utworzyć lokalnie na serwerze, by umożliwić tenantowi korzystanie z aplikacji, a więc przykładowo katalogów wirtualnych na serwerze webowym, katalogów fizycznych, czy plików konfiguracyjnych - w zależności od sposobu działania aplikacji Udzielenie dostępu i bezpieczeństwo Jest to krok umożliwiający użytkownikom zalogowanie się i bezpieczne korzystanie z usług aplikacji. Wpis w katalogu użytkowników - dodanie nowego tenanta do struktur mechanizmów uwierzytelniania. Przykładowo, jeśli wykorzystywany jest LDAP, może to polegać na stworzeniu nowej jednostki organizacyjnej - OU (organizational unit). Następnym standardowym krokiem jest utworzenie konta administratora dla danego tenanta (oczywiście z uprawnieniami ograniczonymi jedynie do pewnego obszaru) i przydzielenie mu hasła, tak by mógł on samodzielnie konfigurować i zarządzać aplikacją. Dostęp do bazy danych - w zależności od zastosowanego scenariusza zapewnienia bezpieczeństwa może polegać np. na przydzieleniu odpowiednich uprawnień za pomocą komendy SQL GRANT, stworzeniu odpowiednich widoków dla tenanta, itp. 68

69 3.3.2 Identyfikacja tenanta Identyfikacja tenanta polega na jednoznacznym określeniu, od którego tenanta nadeszło dane żądanie. Wiedza ta, w aplikacjach typu multitenant, stanowi element kontekstu, w jakim operuje dany proces i jest elementem krytycznym przy dostępie do zasobów aplikacji Problem Izolacja jest najważniejszym czynnikiem w aplikacjach typu multitenant. Mimo że tenanci współdzielą tą samą infrastrukturę i instancję aplikacji, dostęp do zasobów musi charakteryzować się odpowiednią selektywnością. Aplikacja powinna rozpoznać aktualnego tenanta i zastosować odpowiednie mechanizmy selekcji tak, by wykorzystane zostały prawidłowe zasoby. Wybór zasobu musi odbywać się w sposób bezbłędny, w innym bowiem przypadku mogłoby dojść do naruszenia spójności i prywatności danych tenantów, co jest sytuacją niedopuszczalną. Do takich zasobów mogą należeć między innymi: dane w bazie danych, pliki, połączenia do bazy danych, cache, obiekty Java, czy konfiguracje interfejsu użytkownika. Jak widać więc, izolacja ta musi być zapewniona na wielu poziomach aplikacji. W tym celu niezbędny jest centralny mechanizm identyfikacji aktualnego tenanta, z którego korzystałyby komponenty dostępu do zasobów Rozwiązanie Mechanizm taki zapewniony byłby przez komponent TenantContext. Kontekst przechowywałby listę identyfikatorów tenantów powiązanych z konkretnymi wątkami aplikacji. W zależności od tego, który wątek żądałby takiej informacji, kontekst zwracałby identyfikator tenanta, do którego należy. Dzięki temu komponenty korzystające z poszczególnych zasobów w każdej chwili miałyby dostęp do informacji o aktualnym tenancie i na tej podstawie możliwa byłaby selekcja odpowiedniego zasobu. Pozostaje kwestia przypisania poszczególnych wątków do tenantów. Identyfikacja ta musi odbywać się na początku życia wątku tak, by nie dopuścić do sytuacji, w której przy dostępie do zasobu nie jest znany 69

70 aktualny tenant. W zależności od rodzaju aplikacji przypisanie wątku do tenanta może odbywać się na podstawie różnych informacji, przykładowo: danych uwierzytelniających użytkownika; bezpośredniego wskazania przez użytkownika; adresu URL, za pomocą którego następuje dostęp do aplikacji. W przypadku rozważanej klasy aplikacji webowych rozwiązań JEE najbardziej naturalnym podejściem jest wykorzystanie adresu URL. Zapewnienie jego unikalności dla różnych tenantów jest stosunkowo proste. Z drugiej strony byłaby to najprawdopodobniej funkcjonalność wymuszona przez samych klientów życzyliby sobie oni, by oferowane przez nich usługi były dostępne pod różnymi domenami, zgodnymi z marką, czy standardami korporacyjnymi. Centralny obiekt TenantContext jest rozwiązaniem w miarę prostym w implementacji w przypadku aplikacji synchronicznych, w których jeden wątek (i ewentualnie jego wątki potomne) obsługują dane żądanie. Sytuacja komplikuje się, gdy należy dostosować aplikację asynchroniczną, w której poszczególne żądania mogą być obsługiwane przez wiele niepowiązanych ze sobą wątków (na przykład, gdy żądania dostępu do zasobu przesyłane są jako wiadomości i umieszczane w kolejkach, a następnie obsługiwane przez losowe wątki z puli). Niezbędna jest wtedy implementacja takich mechanizmów wykonywania zadań, które potrafiłyby propagować kontekst pomiędzy odpowiednimi wątkami (ustawiać odpowiedni kontekst dla wątku, który "podejmuje się" wykonania danego żądania, tak by dysponował poprawną informacją na temat tenanta, dla którego wykonuje zadanie). Proponowane rozwiązanie zawężone zostało więc jedynie do aplikacji przetwarzających żądania synchronicznie; zaadresowanie problemów charakteryzujących aplikacje asynchroniczne byłoby zbyt skomplikowane i pociągałoby za sobą zapewne wiele innych implikacji i trudności implementacyjnych, nie wchodzi więc w zakres niniejszej pracy Obiekty globalne Gdy stan aplikacji musi być widoczny i współdzielony przez wiele obiektów najczęstszym podejściem w aplikacjach Java jest udostępnianie go w postaci obiektów globalnych. Obiekty takie implementowane są przeważnie za pomocą wzorca Singleton lub zmiennych statycznych. Zmienne takie istnieją tylko w jednej 70

71 instancji i ich modyfikacja jest widoczna dla wszystkich komponentów, które mają dostęp do danego obiektu globalnego Problem W momencie migracji aplikacji do modelu multitenant, może okazać się, że nie wszystkie z dotychczasowych zmiennych statycznych/obiektów Singleton powinny pozostać globalne na poziomie aplikacji, a zamiast tego być widoczne jedynie na poziomach poszczególnych tenantów. Problem taki jest trudny do rozwiązania bez ingerencji w kod, gdyż zmienne globalne tworzone są często za pomocą mechanizmów dostarczanych przez sam język programowania (np. słowo kluczowe static). Zmiany w kodzie są możliwe do uniknięcia w przypadku, gdy zmienne globalne zarządzane są z poziomu frameworku aplikacji (przykładowo Spring) Rozwiązanie Rozwiązanie tego problemu zależy od sposobu, w jaki zmienna globalna została stworzona i zarządzana przez aplikację. Poniżej wymienione są trzy z takich sposobów wraz z propozycjami rozwiązań, dzięki którym można ograniczyć widoczność tych zmiennych do poziomu pojedynczego tenanta, nie zaś całej aplikacji Atrybuty statyczne Są one zapewnione przez mechanizmy języka, pociągają więc za sobą konieczność modyfikacji kodu aplikacji. Przede wszystkim należy wyodrębnić statyczne atrybuty lub metody, które mają być globalne na poziomie tenanta i zmienić je ze statycznych na atrybuty i metody instancji. Następnie ogólne podejście opiera się na zastosowaniu kontenerów udostępniających różne instancje atrybutów w zależności od kontekstu, w jakim znajduje się aplikacja. Dzięki temu stają się one dedykowane i widoczne jedynie z poziomu aktualnego tenanta. Możliwe są dwa różne podejścia przy implementacji tego rozwiązania: Obiekt udostępniający atrybuty statyczne sam bierze odpowiedzialność za rozpoznawanie kontekstu i udostępnianie odpowiedniej instancji 71

72 atrybutu. Należy więc zamiast pojedynczego atrybutu zastosować kontener odwzorowujący identyfikator tenanta na odpowiednią instancję oraz upewnić się, że obiekt przy każdym dostępie do atrybutu udostępnia odpowiednią jego instancję, w zależności od aktualnego kontekstu. Jeśli atrybutów statycznych jest dużo w obrębie danej klasy, można wyodrębnić z nich oddzielną klasę, reprezentującą stan obiektu, a następnie zastosować pojedynczy kontener przechowujący takie obiekty-stany i delegować do nich wywołania metod odczytu stanu. Generalnie, podejście takie wymaga znacznej ingerencji w kod obiektu, powodując, że staje się on "świadomy" istnienia różnych tenantów, a także zyskuje nową odpowiedzialność (rozpoznawanie kontekstu aplikacji multitenant), co nie jest pożądaną sytuacją. Zastosowany jest generyczny kontener, który przechowuje wszystkie obiekty udostępniające atrybuty statyczne i bierze odpowiedzialność za udostępnianie odpowiedniej instancji w zależności od kontekstu. Kontener taki nie jest świadomy zadań, jakie spełniają poszczególne obiekty, jakie atrybuty są przez nie udostępniane i jaką pełnią rolę. Kontener ten wykorzystywany jest przy inicjalizacji (i tylko wtedy) obiektu przechowującego (byłe) statyczne atrybuty, zwracając odpowiednią instancję, która następnie wykorzystywana jest w danej metodzie (obiekt taki musi być obiektem lokalnym, gdyż w przeciwnym wypadku, wątki należące do innych tenantów mogłyby uzyskać dostęp do danych nienależących do nich). Zaletą tego podejścia jest mała ilość zmian, jakie trzeba dokonać w aplikacji - zmianie ulega jedynie kod inicjalizujący dany obiekt (oczywiście oprócz modyfikacji związanych ze zmianą deklaracji atrybutów klasowych na atrybutów instancji). Używanie atrybutów statycznych jest generalnie złym zwyczajem programistycznym; kod opierający się na takich zmiennych jest trudny w utrzymaniu, a ewentualne modyfikacje kłopotliwe. Dlatego proponowane rozwiązanie ma charakter bardziej teoretyczny w praktyce najodpowiedniejszym podejściem byłoby zadbanie o lepszy projekt i implementację aplikacji, tak, aby propagacja informacji globalnych nie opierała się ona na wykorzystaniu zmiennych statycznych, a przykładowo odpowiednim zastosowaniu wstrzykiwanych zależności. 72

73 Obiekty typu Singleton Są to obiekty klas napisanych według wzorca projektowego Singleton, a więc umożliwiające stworzenie tylko jednej instancji w obrębie aplikacji. Wzorzec ten w przypadku aplikacji Java realizuje się najczęściej poprzez zastosowanie prywatnego konstruktora i zmiennej statycznej przechowującej jedyną instancję klasy. Sytuacja w przypadku takich obiektów jest bardzo podobna do opisanych wyżej zmiennych statycznych. Najpierw należy dokonać analizy wykorzystania obiektów Singleton, tak aby odseparować obiekty, które powinny pozostać współdzielone na poziomie aplikacji (na przykład klasy logujące, klasy reprezentujące zewnętrzne usługi) od tych, które powinny zostać odizolowane na poziomie tenanta. W przypadku obiektów współdzielonych żadne zmiany nie są wymagane. W przypadku obiektów zakresu tenanta ponownie ogólnym podejściem jest zastosowanie kontenerów przechowujących dedykowane poszczególnym tenantom instancje. I również możliwe są dwa analogiczne podejścia do implementacji tego rozwiązania: Obiekt Singleton sam przejmuje obowiązki kontenera określającego aktualny kontekst i odwzorowującego go na odpowiednią instancję obiektu. Cechą charakterystyczną klas typu Singleton jest statyczna metoda zwracająca ich instancję (za każdym razem tą samą). Przy przenoszeniu takiej klasy na wersję multitenant metoda ta musiałaby odczytywać aktualny kontekst aplikacji i mapować go na odpowiednią instancję należącą do danego tenanta. Podejście to ma swoją zaletę - nie jest konieczna modyfikacja kodu korzystającego z klas Singleton, gdyż ich interfejs pozostałby niezmieniony. Jeśli chodzi o wady, to są one podobne, jak w przypadku zmiennych statycznych obiekt Singleton staje się "świadomy" istnienia wielu tenantów i staje się zależny od API dostarczanego przez framework. W przypadku istnienia wielu klas typu Singleton wymagane jest wprowadzenie zmian w każdej z nich i duplikacja kodu. Lepsza sytuacja następuje, gdy aplikacja stosuje fabrykę do obiektów Singleton. Można wtedy utworzyć jej, implementującą ten sam interfejs, wersję multitenant będącą jednocześnie kontenerem dla dedykowanych instancji. Podejście takie jest już bardzo bliskie drugiemu możliwemu sposobowi implementacji kontenera. Zastosowanie zewnętrznego, generycznego kontenera pełniącego obowiązki fabryki obiektów. Kontener taki może przechowywać dowolne obiekty i zapewnia ich zasięg na poziomie pojedynczego tenanta. Jego założenia i zachowanie jest podobne, jak w przypadku opisanym dla zmiennych statycznych. Podejście to wymaga jednak 73

74 zmian w istniejącym kodzie klas Singleton; przestają one być bowiem zgodne ze wzorcem Singleton i stają się zwykłymi klasami (z publicznym konstruktorem), tak by kontener był w stanie sam je utworzyć Zasięg singleton w Springu Spring, przy tworzeniu Beanów i wstrzykiwaniu zależności w aplikacji, domyślnie wykorzystuje zasięg typu singleton (singleton scope). Powoduje to, że stworzony Bean zarządzany jest w jednej, tej samej instancji (raz stworzony Bean jest zapisywany w cache u i udostępniany komponentom przy każdym odwołaniu). Istnieją również inne typy zasięgów: prototype, który powoduje utworzenie nowej instancji obiektu Beana przy każdej referencji, oraz request, session i globalsession dostępne jedynie dla aplikacji webowych. Zasięg request ogranicza widoczność Beana jedynie w obrębie danego żądania HTTP, session na czas trwania sesji HTTP, zaś globalsession globalnej sesji HTTP. W przypadku standardowej aplikacji webowej globalna sesja HTTP jest tożsama z normalną sesją HTTP. Jak można zauważyć, jedynym zasięgiem, który należałoby rozważyć z punktu widzenia MEF jest zasięg singleton pozostałe zasięgi zamykają się w obrębie sesji użytkownika, co tym samym oznacza, że widoczność Beanów jest ograniczona do kontekstu pojedynczego tenanta. Spring pozwala na implementację własnych typów zasięgów, co stanowi rozwiązanie dla problemu zasięgu singleton. Możliwe jest stworzenie zasięgu typu tenant, który tworzyłby i udostępniał istniejące Beany na poziomie pojedynczego tenanta. W tym celu należy zaimplementować dostarczany przez Spring interfejs Scope, zarejestrować nowy zasięg we frameworku i zmienić deklaracje Beanów tak, by uzyskały nowy, ograniczony zasięg. Nowy obiekt Scope TenantScope operowałby na podstawie aktualnego kontekstu; w przypadku, gdy Bean nie byłby dostępny dla danego tenanta, pierwsza referencja powodowałaby jego utworzenie i inicjalizację, zaś każda następna zwrócenie odwołania do już istniejącego Beana Dostęp zdalny Aplikacje klasy enterprise często eksponują swoją funkcjonalność w postaci dostępnych zdalnie usług. Z usług takich korzysta się z poziomu kodu aplikacji klienckich, łącząc się ze znanym adresem usługi i wywołując na obiekcie zdalnym 74

75 odpowiednią metodę. Istnieją różne technologie takiego dostępu, przykładowo: Remote Method Ivocation (RMI), Common Object Request Broker Architecture (CORBA), czy Web Services (WS). Największą popularność zdobyły Web Service y, dlatego problem przedstawiony został na ich przykładzie. W Web Service ach komunikacja klienta z dostawcą operacji odbywa się kanałem HTTP, najczęściej protokołem SOAP (Simple Object Access Protocol), opartym na XML. Informacje na temat operacji, takie jak nazwa operacji, typy parametrów oraz typ zwracany uzyskać można z pliku WSDL (Web Services Description Language). Plik ten oprócz dokładnego opisu dostępnej operacji zawiera jej lokalizację i jest dostępny poprzez HTTP Problem Dostęp do Web Service u odbywa się za pomocą połączenia z odpowiednim adresem końcowym endpoint, wyspecyfikowanym w pliku WSDL powiązanym z danym Web Servicem - plik ten musi być więc dostępny dla klienta usługi. Dany Web Service poprzez definicję WSDL związany może być z jednym tylko adresem endpoint, co ogranicza możliwość zastosowania bardziej ogólnego adresu endpoint - czyli takiego, który obejmowałby kilka różnych adresów. Gdyby takie rozwiązanie było dostępne, pozwalałoby to na identyfikację tenanta na podstawie wybranego adresu. W przypadku jednak oryginalnej implementacji Web Service u, po połączeniu do usługi nie jest dostępna informacja o aktualnym tenancie, w związku z czym aplikacja nie jest w stanie dokonać odpowiedniej selekcji przy dostępie do danych. Należy zaopatrzyć więc aplikację w mechanizmy rozróżniania wywołań usługi zdalnej pochodzących od różnych tenantów Możliwe rozwiązania Dedykowane usługi zdalne Możliwe jest generowanie pliku WSDL (a co za tym idzie adresu endpoint ) dynamicznie, podczas uruchamiania Web Service u. Jeśli podejście to zastosować do systemu typu multitenant, to dla każdego tenanta zainteresowanego wykorzystaniem usługi należałoby uruchomić osobny Web Service. Dzięki temu każdy z tenantów dysponowałby własną instancją usługi zdalnej i mógł z niej 75

76 korzystać niezależnie od innych tenantów. Usługa z kolei rozpoznawałaby tenanta na podstawie własnego adresu endpoint i wykorzystywałaby dostęp selektywny do danych zwracając tenantowi poprawną odpowiedź. Jednakże obsługa przez aplikację wielu tenantów skutkowałaby wieloma uruchomionymi równolegle Web Service ami. Nie jest to niestety rozwiązanie oczekiwane od tego typu systemu, gdzie nacisk kładzie się na zmniejszenie średniego wykorzystania zasobów, poprzez dzielenie instancji pojedynczych aplikacji pomiędzy tenantów Współdzielona usługa zdalna tenant ID w zapytaniu W podejściu tym Web Service uruchomiony jest w pojedynczej instancji i obsługuje wszystkich tenantów. Model wdrożenia nie zmienia się więc w porównaniu z oryginalną aplikacją. Podejście to wymaga jednakże pochodzącej z zewnątrz informacji o tenancie zgłaszającym żądanie. Informacja ta musi być dostarczana każdorazowo przy próbie skorzystania z usług zdalnych. Pociąga to za sobą dwie konsekwencje: klient usługi musi być świadomy, z aplikacją jakiego tenanta chce się połączyć oraz musi informację tą dodawać do wiadomości przesyłanych przy łączeniu się z usługą. W konsekwencji poważnie zmienić się może kod aplikacji klienckiej, a także kod samej usługi, gdyż musi ona przetworzyć dodatkowy argument, jakim jest identyfikator tenanta oraz, podobnie jak w poprzednim rozwiązaniu, poprawnie ustawić kontekst aplikacji, aby móc skorzystać z odpowiednich filtrów przy dostępie do zasobów Współdzielona usługa zdalna dynamicznie generowany WSDL W podejściu tym WSDL generowany jest dynamicznie, podobnie jak odpowiedź na zapytanie. Na zastosowanie tego podejścia pozwala przykładowo Web Service framework Axis[64]. Adres endpoint jest wtedy uzależniony od adresu URL, na jakie skierowane było zapytanie. Jako że tenanci korzystają z różnych adresów w celu pobrania pliku WSDL, możliwe jest zastosowanie filtrów dokonujących selekcji tenanta na podstawie adresu dostępowego URL. Na zapytania o WSDL odpowiada jedna instancja, jednakże same pliki WSDL uzależnione byłyby od adresu żądania, co umożliwia przypisanie różnym tenantom różnych adresów usługi. Dzięki temu możliwe jest odpowiednie ustawienie kontekstu aplikacji przed dostępem do zasobów. Podejście to nie wymaga zmian w implementacji aplikacji, jedynie niewielkich zmian w konfiguracji. 76

77 Wybrane rozwiązanie Z przedstawionych opcji najmniej ingerującym w aplikację jest podejście z dynamicznie generowanymi plikami WSDL. W przeciwieństwie do rozwiązania drugiego, nie wymaga ono żadnych zmian implementacyjnych w aplikacji. Z drugiej strony wymaga mniej dodatkowej konfiguracji od rozwiązania pierwszego oraz jest od niego dużo wydajniejsze z uwagi na udostępnione usługi (jedna usługa w wersji multitenant zamiast wielu usług, po jednej dla każdego tenanta) Logowanie Logowanie informacji z aplikacji jest bardzo istotnym elementem jej działania. Pozwala na prześledzenie operacji wykonywanych przez aplikację i identyfikację ewentualnych błędnych zachowań. Proces ten nabiera szczególnego znaczenia w przypadku dużych, wielowątkowych aplikacji, z których korzysta wielu użytkowników. Takimi aplikacjami są niewątpliwie aplikacje multitenant Problem Standardowe logowanie do pojedynczego pliku może nie spełniać w przypadku aplikacji typu multitenant swojej roli, gdyż informacje pochodzące od różnych tenantów mieszałyby się ze sobą, bardzo trudno byłoby je od siebie odróżnić i tym samym zdiagnozować ewentualny problem. Dlatego istotne jest dostarczenie takich mechanizmów logowania, które pozwoliłyby na łatwe rozróżnienie informacji pochodzących od poszczególnych tenantów, a także wiadomości ogólnych, nie dotyczących żadnego kontekstu Możliwe rozwiązania Identyfikacja wpisów Rozwiązanie to polega na prostym uzupełnieniu komunikatów logowanych podczas przetwarzania danych tenanta o jego identyfikator. Dzięki temu każdy 77

78 wpis w pliku logowania mógłby być jednoznacznie zidentyfikowany. Dla komunikatów pochodzących z ogólnego, nie związanego z żadnym konkretnym tenantem przetwarzania identyfikator zostałby pominięty podczas logowania. W praktyce byłyby to sytuacje, w których tenant nie może jeszcze zostać zidentyfikowany, czyli przykładowo: start aplikacji, akceptowanie połączenia od nieznanego jeszcze tenanta, czy proces provisioningu. Informacje o działaniu aplikacji dla danego tenanta można by było uzyskać nakładając odpowiedni filtr z interesującym nas identyfikatorem na plik logowania. Taki sposób logowania można uzyskać bardzo prosto - poprzez rozszerzenie odpowiedniej implementacji odpowiedzialnej za formatowanie komunikatów logowania Dedykowane pliki logowania Innym podejściem jest przekierowanie komunikatów danego tenanta do odpowiedniego, dedykowanego mu pliku. Każdy z tenantów byłby wtedy związany z plikiem, przy czym każdy z plików służyłby do zapisywania informacji jednego tylko tenanta. Pliki mogłyby zawierać identyfikator tenanta w nazwie, tak, aby ich nazwy były niepowtarzalne w obrębie katalogu, lub mogłyby być zapisywane do różnych katalogów/lokalizacji. Komunikaty związane z ogólnym przetwarzaniem logowane byłyby do oryginalnego pliku logu aplikacji. Podejście to wydaje się być wygodniejsze jeśli chodzi o późniejszą analizę logów wszystkie komunikaty dotyczącego danego tenanta zebrane są w jednym pliku, co ułatwia ich czytanie i zauważenie problemu Wybrane rozwiązanie Oba z zaproponowanych rozwiązań są stosunkowo łatwe do implementacji, przy czym podejście drugie jest bardziej wymagające ze względu na konieczność zapisu logów do różnych plików. Z drugiej strony wydaje się, że drugie rozwiązanie oferuje lepszą czytelność i wygodę w zarządzaniu logami, dlatego też to ono zostało wybrane do implementacji (jakkolwiek w celach prezentacyjnych MEF dostarcza również komponentu umożliwiającego zastosowanie pierwszego z wymienionych podejść). 78

79 3.4 Problemy w warstwie prezentacji Warstwa prezentacji ma krytyczne znaczenie w przypadku aplikacji typu SaaS, gdyż stanowi ona czynnik bardzo istotny z punktu widzenia marketingowego, przyciągający (lub wręcz przeciwnie) potencjalnych klientów i decydujący o funkcjonalności oprogramowania. W kontekście SaaS najważniejszą cechą, którą warstwa ta powinna się charakteryzować jest konfigurowalność możliwość dostosowania jej do indywidualnych wymogów tenanta. Jednakże z punktu widzenia zagadnienia multitenancy warstwa ta nie prezentuje praktycznie żadnych problemów, które mogłyby zostać zaadresowane przez MEF. Dlatego też rozdział ten skupia się przede wszystkim na kwestii wykorzystania zmiennych kontekstu aplikacji. Pokrótce nadmienione są również konsekwencje, które pociągałaby za sobą obsługa konfigurowalnego interfejsu użytkownika Interfejs użytkownika (oznaczenia firmowe) Aplikacja typu SaaS ma docelowo obsługiwać wiele różnych organizacji, z których każda posiada własne znaki firmowe, logo, obrazy, kolorystykę identyfikujące firmę. Stanowią one istotne elementy marketingowe, dzięki którym organizacja jest rozpoznawana przez klientów. Naturalnym jest, że tenanci wymagają, by strona internetowa zawierała te elementy, udostępniała znajomy dla klientów/użytkowników tenanta look&feel Problem Zwykłe aplikacje można dostosować zgodnie z życzeniami klienta już na poziomie kodu i tak każdy z nich może posiadać własną kopię z odpowiednio skonfigurowanym interfejsem użytkownika. Jednakże w modelu SaaS, w którym wszyscy tenanci powinni być obsługiwani przez jedną instancję aplikacji, należy udostępnić możliwość własnoręcznego dostosowania aplikacji. Dlatego podczas procesu provisioningu tenanta jednym z elementów podlegającym konfiguracji powinien być, przynajmniej w podstawowym stopniu, wygląd strony. Tenant powinien mieć możliwość załadownia własnego loga, CSS, itp. 79

80 Rozwiązanie Implementacja takiego mechanizmu w standardowym podejściu zakłada wykorzystanie metadanych. Do metadanych należą między innymi informacje generowane przez szablony konfiguracji, a więc wszystkie preferencje i ustawienia użytkowników. Są one następnie wykorzystywane przez środowisko wykonania aplikacji w celu jej dynamicznej konfiguracji dla danego tenanta. Metadane najlepiej zorganizować w sposób hierarchiczny - najwyższy poziom odpowiadałby ustawieniom domyślnym, z których następne poziomy mogą dziedziczyć lub je nadpisywać. Kolejnym poziomem byłyby więc dane konfiguracyjne dla poszczególnych tenantów. W razie potrzeby tenanci mieliby możliwość utworzenia kolejnych podpoziomów, przykładowo dla konkretnych działów firmy, a nawet dla pojedynczych użytkowników końcowych. Metadane przechowywane mogłyby być w specjalnie do tego przeznaczonej tabeli administracyjnej w bazie danych lub też w postaci plików właściwości. Zadaniem MEF byłoby wtedy poprawne ich udostępnienie komponentom dostosowującym interfejs aplikacji. Można zauważyć, że problem ten został już zaadresowany w ramach warstwy dostępu do danych dostęp do metadanych w praktyce niczym się nie różni od dostępu do standardowych danych biznesowych tenanta. Jeśli tylko zostały wykorzystane mechanizmy multitenancy obsługi bazy danych i systemu plików, nie są wymagane żadne inne zmiany na poziomie warstwy prezentacji. Tyczy się to również wykorzystania ustawień domyślnych konfiguracji ich zastosowanie dla nowego tenanta pokryte byłoby przez proces provisioningu (poprzez proste skopiowanie ich do nowo utworzonych wpisów w tabeli metadanych) Zmienne kontekstu aplikacji Aplikacje webowe charakteryzują się różnymi zakresami widoczności zmiennych zarządzanymi przez kontener Servletów. Można wyróżnić następujące zasięgi: strony (page), żądania (request), sesji (session) i aplikacji (servlet context, application context). 80

81 Problem Podczas, gdy zmienne o zasięgu strony, żądania i sesji przynależą zawsze do pojedynczego tenanta, zasięg aplikacji jest globalny, a więc współdzielony przez wszystkich tenantów. Może to powodować kolizje, gdy oryginalna aplikacja korzystała z kontekstu aplikacji do przechowywania danych, które powinny być charakterystyczne dla tenanta. Jak można zaobserwować, zaistniały problem jest bardzo podobny do problemu ze zmiennymi statycznymi (globalnymi), jednakże tu rozpatrywany jest z perspektywy aplikacji webowej, a dokładniej jej warstwy prezentacji Rozwiązanie Rolę kontekstu (zasięgu) aplikacji mogą pełnić różne obiekty, w zależności od wykorzystywanego frameworku webowego ServletContext Jest to komponent pochodzący z oryginalnej specyfikacji JEE. Jest on wstrzykiwany Servletowi podczas jego inicjalizacji przez kontener webowy. Kontener ten odpowiada za dostarczenie implementacji i zarządzanie ServletContext, co sprawia, że niemożliwa staje się nieinwazyjna z punktu widzenia aplikacji modyfikacja tego zachowania. Wprowadzając w aplikacji wsparcie dla wielu tenantów niezbędne jest więc wykrycie wszystkich użyć ServletContext i analiza przechowywanych przez niego obiektów wraz z ewentualnymi zmianami w kodzie, mającymi na celu ograniczenie ich widoczności. Rozwiązaniem jest, ponownie, opisany już w przypadku zmiennych globalnych, kontener stosujący odpowiednie filtry przy wyszukiwaniu obiektów. Rozpoznawałby on aktualnego tenanta i na tej podstawie wyszukiwałby odpowiedni obiekt. Taki kontener przechowywany byłby jako jeden z atrybutów ServletContext, zaś wszelkie operacje dostępu do zmiennych globalnych, które do tej pory odwoływały się do ServletContext musiałyby odwoływać się do pobranego z ServletContext kontenera obiektów. 81

82 Zmienne JSP Składnia JSP udostępnia możliwość użycia w kodzie bloku deklaracji. Zadeklarowane w tym bloku zmienne, po wygenerowaniu z JSP obiektu Servleta, stają się zmiennymi globalnymi, o zasięgu aplikacji. Jest to spowodowane mechanizmem generacji Servletów po ich stworzeniu pojedyncza instancja obsługuje wszystkie żądania skierowane do danej strony JSP. Każdy z tenantów będzie więc miał dostęp do zmiennej zadeklarowanej w ten sposób. Kompilacją JSP zajmuje się przeważnie serwer aplikacji, dlatego, ponownie, by uniknąć zmian w kodzie samej aplikacji, niezbędna byłaby ingerencja w kontener webowy. W przeciwnym razie należałoby usunąć deklaracje z kodu JSP lub zastąpić standardowe zmienne dostępem do kontenerów wspomnianych w poprzednim podrozdziale. Tag jsp:usebean może również powodować wadliwe zachowanie aplikacji multitenant w przypadku, gdy poszukiwany Bean ma zasięg aplikacji (w przypadku innych zasięgów nie wystąpią żadne konflikty). Jest on wtedy, po utworzeniu, przechowywany przez ServletContext ma więc zasięg globalny i jest dostępny dla wszystkich tenantów. Ponownie następuje więc sytuacja opisana w podrozdziale poświęconym ServletContext, podobne jest również rozwiązanie: zamiast pobierać obiekt bezpośrednio z ServletContext należałoby pobrać najpierw kontener obiektów tenanta, a następnie dopiero szukanego Beana. Funkcjonalność tego typu można by było zamknąć we własnym tagu JSP, co pozwoliłoby ograniczyć ilość zmian w kodzie do modyfikacji nazwy wykorzystanego taga WebApplicationContext Jest to obiekt charakterystyczny dla frameworku Spring. Rozszerza on ApplicationContext (stanowiący centralny komponent przechowujący konfigurację aplikacji) o metodę pozwalająca na dostęp do standardowego ServletContext. Z perspektywy aplikacji webowej WebApplicationContext spełnia bardzo podobne zadanie, co ServletContext. W tym przypadku jednakże rozwiązanie problemu jest dużo łatwiejsze. Spring pozwala bowiem na dostarczenie własnej implementacji WebApplicationContext, co umożliwia bezpośrednie wbudowanie obsługi wspomnianego już kontenera obiektów należących do poszczególnych tenantów. Dzięki takiemu podejściu nie byłyby wymagane żadne zmiany w kodzie aplikacji, a dostęp do obiektów kontekstu tenanta odbywałby się w ten sam sposób, jak do obiektów kontekstu aplikacji. Kontekst tenanta byłby więc przeźroczysty z poziomu aplikacji. Przeźroczystość ta z jednej strony stanowi niewątpliwą zaletę 82

83 takiego rozwiązania (brak konieczności wprowadzania jakichkolwiek zmian w kodzie), z drugiej - jest jednocześnie jego wadą. Nie jest bowiem możliwe z poziomu aplikacji rozróżnienie dwóch zakresów, które powinny być rozróżnialne - tenanta i aplikacji (globalnego). Konieczność wprowadzania zmian w kodzie przy dostępie do obiektów globalnych ma swoją zaletę w postaci kontroli, jaką uzyskujemy mogąc zdecydować, którym obiektom należy ograniczyć widoczność do kontekstu tenanta, a które pozostawić widoczne globalnie. Przy zaproponowanym powyżej rozwiązaniu odpowiedzialność za to rozróżnienie przesuwana jest do WebApplicationContext. By obiekt ten był w stanie go dokonać, należy wprowadzić dodatkowe mechanizmy pozwalające na odpowiednią konfigurację komponentu, na podstawie której mógłby on rozpoznawać obiekty należące do kontekstu aplikacji i tenanta Identyfikacja nadchodzącego żądania Wszystkie opisane mechanizmy multitenancy opierają się o aktualny kontekst aplikacji i na jego postawie dokonują filtrowania zasobów. Identyfikacja nadchodzącego żądania to mechanizm pozwalający na automatyczne rozpoznanie aktualnego kontekstu. Powinien być on pierwszym krokiem podczas przetwarzania żądania użytkownika, gdyż w aplikacjach multitenant nie jest dopuszczona sytuacja, w której użytkownik operuje bez kontekstu Problem W celu poprawnej obsługi wielu tenantów aplikacja musi być wyposażona w mechanizm identyfikujący tenanta, do którego nadchodzi żądanie, tak aby kontekst aplikacji mógł zostać poprawnie ustalony jeszcze zanim nastąpią odwołania do współdzielonych zasobów. Musi się to więc odbywać w najwyższej z warstw warstwie prezentacji, w której jako pierwszej odbywa się przetwarzanie żądania. Jako że w zakresie rozważań znajdują się aplikacje rozproszone, w których interakcja z użytkownikiem końcowym odbywa się za pomocą interfejsu webowego stron HTML (rozważana wcześniej komunikacja za pomocą Web Service jest potraktowana jako wyjątek), mechanizm ten należy oprzeć na parametrach żądania HTTP lub parametrach sesji. 83

84 Możliwe rozwiązania Podział przestrzeni użytkowników Jednym z możliwych rozwiązań jest przypisanie użytkownikom serwisu tenanta, z którego usług korzystają. W ten sposób użytkownik zostaje skojarzony z konkretnym tenantem i identyfikacja odbywa się bezpośrednio na podstawie danych uwierzytelniających. Aby korzystać z usług innego tenanta, konieczne jest posiadanie innego konta użytkownika przypisanego danemu tenantowi. Podejście to jest nierealne w przypadku rzeczywistych aplikacji posiada dwie podstawowe wady. Po pierwsze wymaga utrzymywania pojedynczej bazy użytkowników, co w praktyce oznacza, że nazwy użytkowników muszą być unikalne na poziomie całej aplikacji, nie zaś tylko danego tenanta. Nie jest to realizowalne w przypadku, gdy do aplikacji dodawany jest tenant z istniejącą już bazą użytkowników. Podejście to zakłada także, iż cała funkcjonalność aplikacji dostępna jest po uwierzytelnieniu użytkownika, co niekoniecznie ma miejsce w przypadku wszystkich serwisów. Różnego typu aplikacje pozwalają przeglądać zawartość anonimowo, zalogowania się natomiast wymagają dopiero, gdy użytkownik decyduje się skorzystać z konkretnych usług Identyfikacja nazwą tenanta Innym podejściem jest wymaganie od użytkownika, oprócz danych do jego uwierzytelnienia, podania także bezpośrednio nazwy tenanta, w obrębie którego chce on operować. Podejście to jest elastyczne - jeden użytkownik może korzystać z aplikacji wielu tenantów. Minusem natomiast to, iż musi on znać oraz podać nazwę tenanta danego serwisu, przez co multitenancy zaczyna być widoczne z poziomu użytkownika końcowego, co jest często niedopuszczalne z punktu widzenia tenanta. Podejście to, podobnie jak powyższe, zastosowanie ma tam, gdzie cała funkcjonalność aplikacji dostępna jest po uwierzytelnieniu URL żądania W podejściu tym tenanta identyfikuje się na podstawie adresu URL żądania klienta (np. nazwy domeny lub ścieżki kontekstu). Aplikacja musi być wtedy 84

85 dostępna pod wieloma adresami. Dany adres jest na stałe powiązany z tenantem, dzięki czemu użytkownicy różnych tenantów mogą korzystać z różnych punktów wejściowych. Podejście to jest niewidoczne z poziomu użytkownika końcowego i ma istotne znaczenie z marketingowego punktu widzenia różni tenanci mogą udostępniać aplikację pod różnymi domenami Wybrane rozwiązanie Z przedstawionych rozwiązań najmniej inwazyjnym dla przestrzeni użytkowników oraz ich wygody jest rozwiązanie trzecie. Jest to rozwiązanie przeźroczyste dla klienta. Nie wymaga dużych nakładów implementacyjnych. Ponadto rozpoznawanie tenanta po domenie prezentuje bardzo naturalne rozwiązanie, w którym do aplikacji każdego z tenantów dostać się można za pomocą innego, specyficznego dla danego tenanta adresu. 85

86 4 MEF - implementacja Rozdział ten szczegółowo opisuje wybrane rozwiązania implementacyjne stanowiące odpowiedź na wymienione w rozdziale 3 MEF założenia i analiza kwestie. Podrozdział 4.1 Technologie skupia się na bibliotekach i frameworkach wykorzystanych w ramach projektu, krótko opisując najważniejsze z nich. Kolejny, Komponenty frameworku, stanowi opis głównych komponentów wchodzących w skład frameworku, uwzględniając ich szczegóły implementacyjne i sposób wykorzystania z punktu widzenia programisty. 4.1 Technologie Wybór technologii wykorzystanych w ramach projektu opierał się przede wszystkim na dostępności rozwiązań (open source), ale po części podyktowany był także technologiami już wykorzystywanymi przez przykładowe aplikacje JEE. Rozdział ten skupia się najpierw na przestawieniu technologii wchodzących w skład samej platformy JEE i tworzących jej oficjalne API. Następnie opisane zostały pokrótce najważniejsze z zastosowanych zewnętrznych frameworków i bibliotek Java Enterprise Edition Platforma JEE została już opisana w rozdziale Platforma Java Enterprise Edition, jednakże było to wprowadzenie wysykopoziomowe, skupiające się raczej na architekturze aplikacji. Rozdział ten skupia się przede wszystkim na programistycznych aspektach platformy przedstawione tu zostały API zdefiniowane w ramach frameworku JEE, a także technologie pochodzące z J2SE aktywnie wykorzystywane przez komponenty JEE. API te podzielone zostały na dwie kategorie ze względu na ich przeznaczenie. 86

87 Usługi W skład usług oferowanych przez JEE wchodzą technologie tworzące razem środowisko wspierające aplikację (i jako takie przeważnie nie wchodzące w skład samej aplikacji, a jedynie dostarczające jej pewnych mechanizmów pomocniczych), dlatego też deweloperzy przeważnie nie rozszerzają ich, a jedynie korzystają z istniejących API. Do usług oferowanych w ramach platformy JEE należą: Java DataBase Connectivity (JDBC) - pozwala na dostęp do baz danych opartych o SQL - dostęp ten jest niezależny od platformy i dostawcy bazy danych, co pozwala na tworzenie zapytań, odczyt i modyfikację danych w praktycznie każdej relacyjnej bazie danych; Java Message Service (JMS) - dostarcza API dla komunikacji opartej na kolejkach wiadomości, w modelu producent-konsument (publishsubscribe); pozwala to na komunikację asynchroniczną pomiędzy komponentami rozproszonymi; Java Transaction API (JTA) - API do zarządzania transakcjami w środowisku rozproszonym; pozwala na rozpoczynanie, kończenie i cofanie transakcji, składa się z wysokopoziomowego interfejsu do demarkacji transakcji aplikacji, wysokopoziomowego interfejsu managera transakcji przeznaczonego dla serwera aplikacyjnego oraz mapowania standardowego protokołu X/Open XA przeznaczonego dla transakcyjnego managera zasobów; JavaMail - jest to API stanowiące niezależny od platformy i protokołu framework do budowy aplikacji Javowych wykorzystujących ; Java Authentication an Authorization Service (JAAS) - dostarcza mechanizmów do uwierzytelniania i autoryzacji użytkowników; może być przykładowo wykorzystywany do przyznania uprawnień do wykonania danego fragmentu kodu na podstawie zalogowanego użytkownika; Java Naming and Directory Interface API (JNDI) - pozwala na dostęp do usług katalogowych różnego typu; wyszukiwanie i odkrywanie obiektów odbywa się na podstawie ich nazw; jest to właściwie część specyfikacji J2SE, jednakże jest wykorzystywany przez technologie wchodzące w skład JEE. 87

88 Integracja W skład tej grupy wchodzą technologie mające za zadanie ułatwić integrację JEE z innymi platformami. Technologie te to: Java API for XML (JAXP) - umożliwia parsowanie i walidację dokumentów XML; do interfejsów parsujących wchodzących w skład JAXP należą: interfejs Document Object Model (DOM), Simple API for XML (SAX), Streaming API for XML (StAX); dodatkowo JAXP dostarcza także interfejs XSLT do transformacji zarówno struktury, jak i danych dokumentu XML; Java Connector Architecture (JCA) - technologia umożliwiająca integrację komponentów JEE z systemami odziedziczonymi (legacy systems), dzięki którym możliwe jest korzystanie w aplikacji z funkcjonalności takiego systemu bez konieczności znania szczegółów jego implementacji; Java Interface Definition Language API (IDL) - stanowi implementację specyfikacji CORBA pozwalającej na komunikację pomiędzy obiektami pochodzącymi z różnych środowisk (np. obiektami C++ i Java) Spring Spring[5] jest frameworkiem ułatwiającym tworzenie aplikacji JEE. Na cały framework składa się wiele niezależnych szablonów, na przykład kontener IoC (pozwalający na elastyczne tworzenie obiektów oraz wstrzyknięcie zależności), szablon programowania aspektowego (pozwalający na fizyczne oddzielenie kodu różnych zagadnień - aspektów - oraz logiczne zdefiniowanie punktów interakcji między nimi), szablon dostępu do danych (dostarczający komponentów do integracji aplikacji z frameworkami ORM oraz unifikujący błędy dostępu), szablon MVC (Model-View-Controller, pozwalający na oddzielenie modelu danych od ich widoku), itd. Użycie tych szablonów redukuje czas potrzebny zarówno na stworzenie aplikacji (wykorzystanie dobrze działających, istniejących mechanizmów tworzenia oprogramowania), jak i na jej utrzymanie (oddzielenie poszczególnych elementów aplikacji, tzn. warstwy dostępu do danych, warstwy widoku i konfiguracji aplikacji od kodu aplikacji, co ułatwia wprowadzanie zmian). 88

89 I tak kontroler IoC może być wykorzystany do utworzenia obiektów oraz określenia zależności między nimi, np. utworzenia kontekstu aplikacji JEE, wstrzyknięcia odpowiednich obiektów dostępu do danych (Data Access Object - DAO) do tego kontekstu, a dla samych obiektów DAO - określenie i wstrzyknięcie fabryki sesji, specyficznej dla warstwy dostępu do danych. Fabryka sesji z kolei potrzebuje referencji do DataSource. Kontroler IoC pozwala na zdefiniowanie i wstrzyknięcie wszystkich tych zależności. Od programisty wymagana jest tylko odpowiednia definicja w pliku XML. Spring jest technologią, na której opiera się praktycznie cała implementacja MEF. Dzięki temu możliwe jest uniknięcie praktycznie jakichkolwiek zmian w kodzie samej aplikacji JEE oczywiście możliwe jest wykorzystanie większości komponentów z frameworku bez używania samego Springa, jest to jednak utrudnione. Kilka komponentów zaś stworzonych jest z bezpośrednim wykorzystaniem interfejsu Springa, nie są one więc dostępne dla aplikacji nie opierających się na Springu Hibernate Hibernate[56] to framework dla warstwy dostępu do danych. Zapewnia translację danych pomiędzy relacyjną bazą danych, a obiektami Java. Pobranie obiektu bazy danych uzyskuje się w prosty sposób przy odpowiednio przygotowanym środowisku sprowadza się do wywołania pojedynczej metody. Przygotowanie Hibernate do użycia sprowadza się do zdefiniowania (implementacji) odpowiednich obiektów DAO (Data Access Object obiekty dostępu do danych) oraz konfiguracji (DataSource, typ bazy danych, itd.). Jako że Hibernate udostępnia mechanizmy mapowania obiektowo-relacyjnego, konieczne jest określenie schematu mapowania tabel bazy danych na obiekty Java Beans. Mapowanie to można określić w pliku XML lub korzystając z mechanizmu adnotacji. Sam framework udostępnia sporo dodatkowych mechanizmów wspomagających korzystanie z baz danych, np. automatycznie tworzenie schematów, uaktualnianie schematu, cache owanie zapytań oraz odpowiedzi. 89

90 4.1.4 ibatis ibatis[57] podobnie jak Hibernate jest frameworkiem dostępu do danych. Zapewnia mapowanie obiektowo-relacyjne, zgodnie z konfiguracją zapisaną w plikach XML. Podobnie w plikach XML definiować można zapytania SQL. ibatis nie wspiera aktywnej kontroli nad schematem bazy danych, tzn. nie tworzy oraz nie aktualizuje schematu. Minusem korzystania ze środowiska jest konieczność definicji dużej liczby zapytań SQL, w miarę rozwoju aplikacji oraz brak pełnego wsparcia dla mapowania typów użytkownika. 4.2 Komponenty frameworku Na implementację MEF składa się zestaw komponentów, z których każdy adresuje pewien problem opisany w rozdziale 3 MEF założenia i analiza. Każdy komponent odpowiada pakietowi kodu źródłowego; struktura kodu prezentuje się więc następująco: pl.edu.agh.mef.cache.hibernate komponent cache w implementacji dla Hibernate pl.edu.agh.mef.cache.ibatis komponent cache w implementacji dla ibatis pl.edu.agh.mef.config komponent konfiguracji elementów zapewniających multitenancy pl.edu.agh.mef.context komponent kontekstu aplikacji pl.edu.agh.mef.dao komponenty dostępu do danych (DAO) pl.edu.agh.mef.datasource komponent DataSource reprezentujący źródło danych typu multitenant pl.edu.agh.mef.file komponent File izolujący pliki tenantów pl.edu.agh.mef.global komponent zarządzający zmiennymi globalnymi aplikacji pl.edu.agh.mef.logging komponent logujący pl.edu.agh.mef.spring.scope komponent zasięgu tenanta dla Spring Kolejne podrozdziały opisują implementację najważniejszych z nich. 90

91 4.2.1 Kontekst aplikacji Aplikacje JEE charakteryzują się szeroką niejednorodnością wykorzystywanych mechanizmów tworzenia, konfigurowania oraz zarządzania komponentami. Niejednorodność ta sprawia, iż bardzo problematyczne staje się wstrzykiwanie potrzebnych (do udostępnienia aplikacji w modelu SaaS) narzędzi do komponentów. O ile łatwo jest utworzyć oraz przekazać takie obiekty korzystając z mechanizmu wstrzykiwania zależności w Spring, o tyle w konfiguracji Hibernate lub ibatis jest to bardzo utrudnione. Aby umożliwić jednolity dostęp do niezbędnych z punktu widzenia aplikacji multitenant informacji, zaimplementowany został mechanizm globalnego kontekstu - MultiTenantContext. Komponent MultiTenantContext udostępnia mechanizmy: identyfikacji tenanta, dla którego pracuje dany wątek, przechowywania oraz udostępniania zmiennych zakresu tenanta, dostępu do danych administracyjnych tenanta oraz obiektów DataSource, za pomocą odpowiednich komponentów, udostępniania konfiguracji systemu, tzn. konfiguracji DataSource poszczególnych tenantów oraz konfiguracji właściwości specyficznych dla tenanta, np. nazwy czy domeny. Kontekst jest centralną częścią systemu, dostępną we wszystkich miejscach, które zaadaptowane musiały być do postaci multitenant. Jest to możliwe dzięki implementacji MultiTenantContext według wzorca projektowego Singleton. U podstaw MultiTenantContext leży obiekt ThreadLocal, dostarczany przez standardową bibliotekę Javy. Obiekt ten umożliwia przechowywanie zmiennej dla wątku - każdy z wątków dysponuje jej własną kopią. Zmienną tą jest TenantID, jednoznacznie identyfikujący tenanta w systemie. Ze względu na wielowątkową naturę aplikacji JEE, oprócz dostępności aktualnego TenantID dla wątku głównego, MultiTenantContext powinien propagować tą informację do wątków potomnych. Dlatego do przechowywania TenantID wykorzystana została implementacja InheritableThreadLocal. InheritableThreadLocal rozszerza ThreadLocal wprowadzając dziedziczenie wartości zmiennej dla wątków potomnych. TenantID jest ustawiany zaraz po przyjściu żądania do Servletu, na podstawie adresu URL strony internetowej. Implementacja taka pokrywa proponowane rozwiązanie dla aplikacji działających synchronicznie (w których 91

92 żądanie w całości obsługiwane jest przez pojedynczy wątek oraz ewentualnie jego wątki potomne). public class MultiTenantContext {... private final ThreadLocal<TenantId> currenttenant;... protected MultiTenantContext() { currenttenant = new InheritableThreadLocal<TenantId>();... }... } Dodatkowo kontekst udostępnia obiekty DAO (Data Access Object) dla konfiguracji tenanta oraz DataSource. Obiekty DAO odpowiedzialne są za reprezentację danych (konfiguracja tenanta oraz DataSource) w postaci obiektowej. DAO służą do pobierania konfiguracji tenanta oraz DataSource z poziomu aplikacji, np. pobieranie konfiguracji tenanta na podstawie jego domeny w filtrze. Obiekty te wykorzystywane są również przy zapisie konfiguracji nowych tenantów oraz obiektów DataSource z poziomu narzędzia do udostępniania systemu nowym tenantom (provisioning). Przykład definicji obiektu MultiTenantContext z poziomu konfiguracji Spring dostępny jest w rozdziale opisującym dostosowanie MEF do przykładowej aplikacji JEE. 92

93 4.2.2 DataSource pl.edu.agh.mef.datasource pl.edu.agh.mef.context SchemaSwitchingDataSource MultiTenantContext BasicDataSource +getconnection() * * 1 1 DelegatingDataSource +gettenantdao() +settenantid() +getdatasourcedao() +getcurrenttenantid() +gettenantscopeobjects() Rys. 16. Diagram klas DataSource Problem korzystania z odpowiednich DataSource przez odpowiednich tenantów został rozwiązany przez system centralnego obiektu opakowującego DataSource. W implementacji zastosowano rozwiązanie hybrydowe, łączące w sobie oszczędność zasobów z jednej strony, oraz bezpieczeństwo i wysoką wydajność z drugiej. Zaimplementowany został nowy DataSource DelegatingDataSource. Obiekt odpowiedzialny jest za delegację wywołania metody zwracającej obiekt połączenia Connection getconnection() - do obiektów SchemaSwitchingDataSource lub BasicDataSource, w zależności od konfiguracji DataSource danego tenanta. Dla tenantów z własnym DataSource (określonym w konfiguracji administracyjnej) używany jest BasicDataSource (standardowa implementacja DataSource dostarczana w ramach biblioteki Apache Commons[65]). W przypadku, gdy tenant korzysta ze współdzielonego DataSource, używany jest SchemaSwitchingDataSource (rozszerzający BasicDataSource). Obiekt ten dokonuje wyboru schematu danego tenanta przed zwróceniem obiektu Connection. W ten sposób ten sam obiekt SchemaSwitchingDataSource używany może być przez wielu tenantów. W celu jego wykorzystania należy podmienić konfigurację DataSource zastanej aplikacji na DelegatingDataSource, na przykład konfigurację: <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource" destroymethod="close"> <property name="driverclassname" value="${jdbc.driverclassname}"/> 93

94 <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> na: <bean id="datasource" class="pl.edu.agh.saas.datasource.delegatingdatasource" destroy-method="close"> <property name="driverclassname" value="${jdbc.driverclassname}"/> <property name="url" value="${jdbc.url}"/> <property name="multitenantcontext" ref="multitenantcontext"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> Dodatkowo należy przekazać obiekt kontekstu aplikacji poprzez parametr multitenantcontext Cache Dodatkowo dla frameworków ibatis oraz Hibernate zaimplementowano odpowiednie mechanizmy zapobiegające nieprawidłowemu funkcjonowaniu cache przy wykorzystaniu współdzielonych DataSource. 94

95 ibatis * CacheController +getobject() +putobject() +removeobject() +flush() pl.edu.agh.mef.cache.ibatis 1 DelegatingCacheController pl.edu.agh.mef.context MultiTenantContext +gettenantdao() +settenantid() +getdatasourcedao() +getcurrenttenantid() +gettenantscopeobjects() CacheModel Rys. 17. Diagram klas komponentu ibatis Cache W ibatis nad cachem kontrolę sprawuje CacheController. Aby rozdzielić cache różnych tenantów, wprowadzona została nowa implementacja, DelegatingCacheController. DelegatingCacheController utrzymuje mapowanie ID tenanta na oddzielne obiekty CacheController. Implementację podrzędnych obiektów CacheController określa się w konfiguracji (parametr underlying-cachecontroller). Można wyspecyfikować kwalifikowaną pakietem nazwę klasy, lub alias do jednej ze standardowych implementacji ibatis (FIFO, LRU, MEMORY, OSCACHE). Zamiast przykładowej konfiguracji: <cachemodel id="onedaycategory" type="memory"> <flushinterval hours="24"/> <property name="reference-type" value="weak"/> </cachemodel> wykorzystać więc należy DelegatingCacheController: <cachemodel id="onedaycategory" type="pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller"> <flushinterval hours="24"/> <property name="reference-type" value="weak"/> <property name="underlying-cache-controller" value="memory"/> </cachemodel> 95

96 Hibernate pl.edu.agh.mef.cache.hibernate CacheProvider DelegatingCacheProvider pl.edu.agh.mef.context +buildcache() MultiTenantContext Cache +put() +get() +update() * 1 1 DelegatingCache +gettenantdao() +settenantid() +getdatasourcedao() +getcurrenttenantid() +gettenantscopeobjects() Rys. 18. Diagram klas komponentu Hibernate Cache Dla Hibernate zastosowano podobne rozwiązanie, to znaczy delegację cache drugiego poziomu do standardowych implementacji dostarczanych z frameworkiem. Implementacja tego mechanizmu jest jednak nieco bardziej skomplikowana niż w przypadku ibatis. W Hibernate za obsługę cache drugiego poziomu odpowiedzialne są komponenty CacheProvider oraz Cache. CacheProvider odpowiedzialny jest za budowę obiektów typu Cache, które zajmują się właściwymi operacjami cache owania. Wprowadzona w MEF implementacja, DelegatingCacheProvider, tworzy i zwraca nową implementację Cache - DelegatingCache. DelegatingCache z kolei przechowuje mapowanie oryginalnych implementacji Cache na poszczególnych tenantów i deleguje do nich operacje na podstawie aktualnego TenantID. Podrzędne obiekty Cache tworzone są za pośrednictwem obiektu CacheProvider, którego implementację określić można w konfiguracji (parametr hibernate.cache.underlying_provider_class). <prop key="hibernate.cache.provider_class"> pl.edu.agh.saas.cache.hibernate.delegatingcacheprovider </prop> <prop key="hibernate.cache.underlying_provider_class"> org.hibernate.cache.hashtablecacheprovider</prop> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.use_query_cache">true</prop> 96

97 4.2.4 System plików File pl.edu.agh.mef.file TenantIsolatingFile pl.edu.agh.mef.context MultiTenantContext TenantIsolatingFileFactory +convertpathtotenantisolated() +gettenantdao() +settenantid() +getdatasourcedao() +getcurrenttenantid() +gettenantscopeobjects() Rys. 19. Diagram klas komponentu File W rozwiązaniu kwestii dostępu do plików zastosowano własną implementację rozszerzającą klasę File ze standardowego pakietu Java java.io. Przy dostępie do plików wspólnych, współdzielonych między tenantami na poziomie aplikacji, wykorzystywać należy standardową klasę java.io.file (jakkolwiek dostarczany przez MEF komponent dostępu do plików potrafi rozróżnić pliki współdzielone od dedykowanych, co umożliwia jego zastosowanie w każdej sytuacji, niezależnie od rodzaju pliku). Natomiast w celu dostępu do plików chronionych, specyficznych dla danego tenanta i mapowanych po jego ID, skorzystać należy z udostępnianej przez MEF implementacji TenantIsolatingFile. Wymaga to dokonania zmian w kodzie aplikacji udostępnianej w modelu SaaS. Aby skorzystać z mechanizmu konieczna jest konfiguracja fabryki TenantIsolatingFileFactory. Konfiguracja ta polega na wyspecyfikowaniu ścieżki do odpowiedniej lokalizacji, w której przechowywane będą dane specyficzne dla tenantów: <bean id="filefactory" class="pl.edu.agh.saas.file.tenantisolatingfilefactory" factory-method="getinstance"> <property name="tenantdatadirectory" value="c:\saastest"/> </bean> Parametr tenantdatadirectory określa, do której lokalizacji zastosowane będzie rozgałęzienie danych dla tenantów. W przykładzie powyżej katalogiem tym jest c:\saastest. W katalogu tym utworzone zostaną odpowiednie podkatalogi, reprezentowane przez TenantID i przechowujące pliki prywatne, do których inni tenanci nie powinni mieć dostępu. 97

98 Algorytm działania komponentu jest następujący: 1. Próba dostępu do pliku spoza określonej lokalizacji, na przykład: final File file = new TenantIsolatingFile("c:\test.txt"); powoduje przekazanie nadrzędnemu obiektowi File niezmienionej ścieżki, tj. c:\test.txt. 2. Próba dostępu do pliku z określonej lokalizacji, na przykład: final File file = new TenantIsolatingFile("c:\saastest\test.txt"); powoduje przekazanie obiektowi File zmienionej ścieżki, mianowicie c:\saastest\$tenantid\test.txt, gdzie tenantid określa ID tenanta, dla którego plik jest tworzony, a więc przykładowo dla tenanta z ID=1 będzie to c:\saastest\1\test.txt. 3. Próba dostępu do danych innego tenanta traktowana jest jak zwykła próba dostępu do własnych danych, dlatego też ścieżka wskazywać będzie na katalog obecnego tenanta, czyli na przykład: final File file = new TenantIsolatingFile("c:\saastest\1\test.txt"); wywołane przez tenanta z ID=2 powoduje dostęp do ścieżki c:\saastest\2\1\test.txt (a więc lokalizacji nie istniejącej wywołanie zakończy się więc odmową dostępu zapobiegając nieupoważnionemu odczytowi). 4. Podobnie próba dostępu do lokalizacji: final File file = new TenantIsolatingFile("c:\saastest\1\test.txt"); dokonywana przez tenanta z ID=1 zakończy się próbą dostępu do ścieżki c:\saastest\1\1\test.txt Logowanie Przystosowanie mechanizmu logowania do aplikacji multitenant uzyskuje się poprzez stworzenie możliwości oddzielenia danych logowanych przez różnych tenantów, tak, aby łatwiejsze było śledzenie przetwarzania każdego z nich. W projekcie zastosowane zostały dwa rozwiązania problemu, implementacja nowego Layout oraz implementacja Appender. 98

99 Layout Layout jest interfejsem z pakietu Log4j, implementacje którego określają sposób formatowania zdarzeń logowania, tzn. sposób generowania łańcuchów znakowych dla zdarzeń typu format: public String format(loggingevent event); Na przykład następująca konfiguracja standardowego PatternLayout: log4j.appender.console.layout=org.apache.log4j.patternlayout log4j.appender.console.layout.conversionpattern=%d{hh:mm:ss.sss} [%t] %p %c{2} - %m%n powoduje wypisywanie komunikatów do logów w postaci: 19:25: [main] WARN log4j.patternstest - message Dostarczana przez MEF nowa implementacja Layout - PatternLayoutWTenant, rozszerzająca PatternLayout, umożliwia dodanie do logowanego łańcucha ID tenanta, dla którego dane logowanie zachodzi. Uzyskuje się to poprzez wykorzystanie specjalnego znacznika %T. Na przykład zastosowanie następującej konfiguracji Layout: log4j.appender.console=org.apache.log4j.consoleappender log4j.appender.console.layout=pl.edu.agh.saas.logging.patternlayoutwtenant log4j.appender.console.layout.conversionpattern=%d{hh:mm:ss.sss} [%t] (%T) %p %c{2} - %m%n formatuje komunikat (wraz z nowym parametrem ID tenanta), produkując przykładowy wynik: 19:29: [main] (17) WARN log4j.patternstest - message lub 19:29: [main] (-) WARN log4j.patternstest message gdy wykonywany kod nie dotyczy konkretnego tenanta Appender Appender jest interfejsem z pakietu Log4j, implementacje którego określają miejsce, w którym pojawi się zarejestrowane zdarzenie. Przykładowo 99

100 ConsoleAppender przekierowuje logowane wiadomości na standardowe wyjście, zaś FileAppender do określonego pliku. Stworzona implementacja PerTenantFileAppender rozszerza klasę FileAppender. Konfiguracja obiektu umożliwia logowanie do różnych plików, w zależności od tenanta, dla którego zachodzi dane wydarzenie logowania. Specjalny znacznik $t w nazwie pliku zostaje zastąpiony przez ID aktualnego tenanta. Przykładowo, konfiguracja: log4j.appender.file=pl.edu.agh.saas.logging.pertenantfileappender log4j.appender.file.file=logs/log_$t.txt log4j.appender.file.appenderscount=10 log4j.appender.file.layout=pl.edu.agh.saas.logging.patternlayoutwtenant log4j.appender.file.layout.conversionpattern=%d{hh:mm:ss.sss} [%t] %p %c{2} - %m%n powoduje logowanie w plikach logs/log_18.txt, logs/log_23.txt, itd., w zależności od ID tenanta, dla którego logowanie zachodzi. Implementacja wykorzystuje obiekty FileAppender. Utworzenie dla każdego tenanta osobnego FileAppender powodowałoby konieczność utrzymywania zbyt dużej ilości obiektów, nie wspominając już o ilości otwartych deskryptorów plików. Z drugiej strony tworzenie nowych obiektów FileAppender przy każdym żądaniu logowania nie jest konieczne, gdyż możliwe jest wykorzystanie istniejącego obiektu FileAppender - należy zmienić nazwę pliku i zażądać jego rekonfiguracji (co jest bardziej oszczędne pod względem ilości tworzonych obiektów). Jednakże utrzymywanie jednego obiektu Appender byłoby z kolei nieefektywne z powodu koniecznych operacji wejścia/wyjścia, gdyż wymagałoby rekonfiguracji obiektu (zmiana nazwy pliku, tj. zamknięcie starego i otworzenie nowego) przy prawie każdym żądaniu logowania (gdy wielu tenantów działałoby jednocześnie). Optymalnym rozwiązaniem wydaje się więc utrzymywanie kilku obiektów FileAppender związanych z plikami różnych tenantów. Przy żądaniu logowania pochodzącym od tenanta, który nie jest związany z żadnym obiektem Appender następuje rekonfiguracja jednego ze związanych obiektów Appender (tego, który był skonfigurowany najwcześniej) i związanie go z nowym tenantem. Parametr konfiguracji appenderscount określa, ile obiektów FileAppender będzie wykorzystywanych. Wartość powinna być odpowiednio dobrana, w zależności od intensywności logowania aplikacji, ilości obsługiwanych tenantów oraz ruchu, jaki generują, tak, aby z jednej strony nie utrzymywać wielu otwartych deskryptorów plików, a z drugiej nie przeprowadzać zbyt często rekonfiguracji obiektów FileAppender. 100

101 4.2.6 Provisioning W celu umożliwienia łatwego zarządzania tenantami i ich provisioningu został zaimplementowany webowy interfejs administracyjny. Interfejs ten umożliwia dokonania konfiguracji podstawowych elementów aplikacji: provisioning nowego tenanta i zarządzanie obiektami DataSource. Poniższy zrzut ekranu prezentuje widok Home aplikacji: Rys. 20. Konsola administracyjna MEF - Home Poniżej przedstawiono operacje udostępniane przez konsolę: 1. Register Tenant: rejestracja nowego tenanta. Dla nowego tenanta ustawić można nazwę, jego domenę oraz DataSource, z którego będzie korzystał. Możliwy jest wybór DataSource współdzielonego pomiędzy wielu tenantów lub utworzenie DataSource dedykowanego rejestrowanemu tenantowi. 101

102 Rys. 21. Konsola administracyjna MEF - Register Tenant Po naciśnięciu Register następuje proces właściwego provisioningu: a. Zapisanie konfiguracji odpowiedniego DataSource w administracyjnej bazie danych, jeśli wybrany został dedykowany DataSource. b. Zapisanie konfiguracji odpowiedniego tenanta w administracyjnej bazie danych. c. Utworzenie nowego schematu danych dla tenanta. d. Opcjonalne utworzenie struktury bazy danych dla tenanta wraz z opcjonalnym wypełnieniem tabel danymi początkowymi/domyślnymi (wywoływane są skrypty SQL z katalogu podanego jako element konfiguracji komponentu SchemaCreator). e. Utworzenie struktury katalogów w obszarze danych specyficznych dla tenanta. Po tym etapie aplikacja przygotowana jest do przyjęcia nowego tenanta. 2. Current Configuration: widok aktualnej konfiguracji. W widoku tym wyświetleni są wszyscy zarejestrowani tenanci wraz z obiektami DataSource, z których korzystają i ich konfiguracją. 102

103 Rys. 22. Konsola administracyjna MEF - Current Configuration 3. Manage Tenants & DataSources: zarządzanie tenantami i obiektami DataSource Widok ten umożliwia zarządzanie aktualną konfiguracją tenantów i przypisanych do nich obiektów DataSource: możliwe jest przesunięcie tenanta do innego DataSource, usunięcie tenanta, usunięcie DataSource i wreszcie dodanie nowego współdzielonego DataSource. Dodanie DataSource wymaga wyspecyfikowania jego parametrów: maksymalnej liczby aktywnych połączeń, maksymalnej oraz minimalnej liczby oczekujących połączeń oraz jego nazwy. 103

104 Rys. 23. Konsola administracyjna MEF - Manage Tenants & DataSources Rys. 24. Konsola administracyjna MEF - Add shared DataSource 104

105 Poniższy diagram (Rys. 25) przedstawia podstawowy diagram klas warstwy logicznej aplikacji konsoli administracyjnej: pl.edu.agh.mef.dao pl.edu.agh.mef.service SchemaCreator AbstractDao «interface» TenantDataSourceService +setcurrenttenant() +addtenantconfig() +adddatasourceconfig() +createschema() +executesqls() +findbyproperty() +saveorupdate() TenantDataSourceServiceImpl DataSourceConfigDao TenantConfigDao pl.edu.agh.mef.context pl.edu.agh.mef.file MultiTenantContext TenantIsolatingFileFactory +convertpathtotenantisolated() +createstructurefortenant() +gettenantdao() +settenantid() +getdatasourcedao() +getcurrenttenantid() +gettenantscopeobjects() Rys. 25 Diagram klas wykorzystywanych przy provisioningu Obiektem nadzorującym proces provisioningu jest TenantDataSourceService. Wywołuje on specjalizowane komponenty odpowiedzialne za provisioning poszczególnych elementów środowiska. I tak przykładowo wywoływany jest TenantIsolatingFileFactory odpowiedzialny za stworzenie odrębnej struktury katalogowej przypisanej tenantowi, obiekty DAO zapisujące odpowiednie metadane dotyczące konfiguracji aplikacji do administracyjnej bazy danych, czy SchemaCreator, który przygotowuje główną bazę danych i wypełnia ją danymi domyślnymi dostarczonymi przez tenanta. 105

106 4.2.7 Identyfikacja nadchodzącego żądania Najważniejszym zagadnieniem działania aplikacji w modelu multitenant, jest określenie tenanta, dla którego odbywa się przetwarzanie. W MEF odbywa się to na podstawie domeny, dla której generowanie jest zapytanie, i tak np. to dwa odniesienia, obydwa do tej samej podstrony, jednak różnych sklepów (np. domain1 związana jest z tenantem tenant1, podczas gdy domain2 związana jest z tenantem tenant2). Domeny wskazywać mogą na tą samą lokalizację (ten sam adres IP), a więc zapytanie skierowane może być do tej samej instancji aplikacji. Określeniem obecnego tenanta zajmuje się TenantResolutionFilter, rozszerzenie standardowej klasy filtra javax.servlet.filter. Filtr jest mechanizmem JEE odpowiedzialnym za wstępne przetwarzanie zapytania klienta, wywoływanym przed przekazaniem żądania do Servletu. TenantResolutionFilter wywoływany jest przed każdym Servletem, powodując ustawienie odpowiedniego identyfikatora tenanta w MultiTenantContext. W przypadku braku odpowiedniego mapowania domena -> tenant (czyli w przypadku braków w bazie administracyjnej lub dostępu z nieakceptowanej domeny), wyświetlana jest strona informująca, iż tenant nie został określony. 106

107 5 Testy MEF został przetestowany za pomocą dwóch otwartych aplikacji JEE JPetStore i PetClinic. Testy te obejmowały próbę integracji MEF z aplikacją, wdrożenie jej i wykazania, że możliwe jest obsłużenie przez nią wielu tenantów. Rozdział ten opisuje kroki niezbędne do poprawnej integracji oraz przedstawia przypadki testowe wraz z ich rezultatami dowodzącymi poprawne funkcjonowanie aplikacji. 5.1 JPetStore JPetStore oparty jest na oryginalnej aplikacji PetStore, rozpowszechnianej przez Sun jako przykład możliwości platformy JEE. W praktyce jest to sklep internetowy do sprzedaży zwierząt. Umożliwia przeglądanie listy dostępnych zwierząt, dodawanie ich do koszyka oraz końcowy zakup. Aplikacja zbudowana została z wykorzystaniem frameworku Spring. Za dostęp do warstwy danych odpowiedzialny jest ibatis Integracja z MEF W celu udostępnienia przykładowej aplikacji w modelu multitenant należy wykonać kilka kroków konfiguracyjnych, integrujących MEF z aplikacją Dodanie bibliotek Pierwszym krokiem migracji aplikacji do modelu SaaS jest zadbanie o dostępność odpowiednich klas. Konieczne jest dołączenie bibliotek frameworku 107

108 saas-tools.jat oraz saas-web.jar, oraz zależności: log4j, hibernate, dom4j, slf4-api, slf4j-log4j12, commons-io Konfiguracja komponentów Należy dołączyć konfigurację MultiTenantContext oraz pozostałych komponentów frameworku: 1. Zmiany w web.xml (dodanie /WEB-INF/saasConfiguration.xml): <context-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/saasconfiguration.xml /WEB-INF/dataAccessContext-local.xml /WEB-INF/applicationContext.xml </param-value> </context-param> 2. Dodanie pliku konfiguracyjnego saasconfiguration.xml, zawierającego definicje Beanów sessionfactory, saasdatasource, datasourceconfigdao, tenantconfigdao, multitenantcontext, filefactory (zał. 1.). 3. Dodanie konfiguracji dla Hibernate mapping.hbm.xml (mapowanie O/R dla bazy administracyjnej) (zał. 2.) 4. Utworzenie administracyjnej bazy danych na serwerze bazy danych (localhost), zgodnie z ustaloną konfiguracją: CREATE DATABASE tenantsadministration; GRANT ALL ON tenantsadministration.* TO IDENTIFIED BY 'saas123'; Rekonfiguracja DataSource DataSource aplikacji musi być zrekonfigurowany tak, aby korzystał z implementacji DelegatingDataSource, otrzymał referencję do MultiTenantContext w parametrze multitenantcontext, oraz aby adres dostępowy URL nie zawierał nazwy schematu: <bean id="datasource" class="pl.edu.agh.saas.datasource.delegatingdatasource" destroy-method="close"> <property name="driverclassname" value="${jdbc.driverclassname}"/> <property name="url" value="${jdbc.url}"/> <property name="multitenantcontext" ref="multitenantcontext"/> <property name="username" value="${jdbc.username}"/> 108

109 <property name="password" value="${jdbc.password}"/> </bean> Plik jdbc.properties: jdbc.driverclassname=com.mysql.jdbc.driver jdbc.url=jdbc:mysql://localhost:3306/ jdbc.username=saastest jdbc.password=saastest Hibernate/iBATIS cache Podmienić należy implementację cache drugiego poziomu w Hibernate lub implementację cache w ibatis. W JPetStore (który korzysta z ibatis) należy dokonać zmian w plikach Category.xml, Item.xml, Product.xml. Jako typ cache użyć należy pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller, a typ pierwotnego cache ustawić korzystając z parametru underlying-cache-controller: Category.xml: <cachemodel id="onedaycategory" type="pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller"> <flushinterval hours="24"/> <property name="reference-type" value="weak"/> <property name="underlying-cache-controller" value="memory"/> </cachemodel> Item.xml: <cachemodel id="onedayitem" type="pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller"> <flushinterval hours="24"/> <property name="reference-type" value="weak"/> <property name="underlying-cache-controller" value="memory"/> </cachemodel> <cachemodel id="onedayquantity" type="pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller"> <flushinterval hours="24"/> <flushonexecute statement="updateinventoryquantity"/> <property name="reference-type" value="weak"/> <property name="underlying-cache-controller" value="memory"/> </cachemodel> Product.xml: <cachemodel id="onedayproduct" type="pl.edu.agh.saas.cache.ibatis.delegatingcachecontroller"> <flushinterval hours="24"/> 109

110 <property name="reference-type" value="weak"/> <property name="underlying-cache-controller" value="memory"/> </cachemodel> TenantResolutionFilter dla Servletów Należy ustawić odpowiedni filtr (TenantResolutionFilter odpowiedzialny za identyfikację tenanta) w web.xml dla wszystkich Servletów, tak, aby w czasie wykonywania kodu Servletu znany był aktualny tenant: <filter> <filter-name>tenantresolution</filter-name> <filter-class>filter.tenantresolutionfilter</filter-class> <init-param> <param-name>redirect</param-name> <param-value>../notenant.html</param-value> </init-param> </filter> <filter-mapping> <filter-name>tenantresolution</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> Web Service JPetStore korzysta z frameworku Axis. Zaletą Axis jest dynamiczna generacja WSDL. W tak wygenerowanym pliu WSDL enpoint zależny jest od adresu URL, z którgo korzysta klient. Pierwszym krokiem jest ujednolicenie Namespace dla serwisu. Właściwość Namespace również ustalana jest na podstawie adresu, jednak jednokrotnie, przy pierwszej próbie dostępu, co powoduje problemy ustalenia parametru targetnamespace po stronie klienta. Należy więc w pliku server-config.wsdd ustalić jakąś wartość dla parametru namespace, np. jpetstore/orderservice: <service name="orderservice" provider="java:rpc"> <namespace>jpetstore/orderservice</namespace> </service> Kolejnym krokiem jest ustalenie filtra dla Web Service, w pliku web.xml: 110

111 <filter-mapping> <filter-name>tenantresolution</filter-name> <url-pattern>/axis/*</url-pattern> </filter-mapping> Separacja danych logowania W celu możliwości odseparowania wiadomości logowanych przez różnych tenantów, należy zastosować jedną z zaimplementowanych metod separacji (dodanie ID tenanta do komunikatu lub logowania do różnych plików). W JPetStore ustawić należy nowy Layout w pliku komfiguracyjnym Log4j (war/web- INF/log4j.properties): log4j.appender.logfile.layout=pl.edu.agh.saas.logging.patternlayoutwtenant log4j.appender.logfile.layout.conversionpattern=%d %p [%c] [%T] - %m%n W miejscu %T podstawione zostanie ID tenanta. Jeśli korzystamy z serwera innego niż JBoss, należy odkomentować Listener Log4j w pliku web.xml: <listener> <listener-class> org.springframework.web.util.log4jconfiglistener </listener-class> </listener> Konfiguracja saas-web dla aplikacji Dodatkowo, aby umożliwić dodawanie nowych tentów, należy skonfigurować (a następnie wdrożyć i uruchomić na serwerze webowym) narzędzie saas-web. W pliku konfiguracyjnym saasconfiguration.xml należy zadbać o odpowiednie ustawienie administracyjnego DataSource, ścieżki dla systemu plików tenantaware oraz ścieżki, w której zajdują się pliki SQL z definicjami tabel (zał. 1.). Dla JPetStore umieszczono w katalogu określonym w konfiguracji komponentu SchemaCreator plik SQL z definicjami do tworzenia tabel (dostępny w katalogu db projektu JPetStore). 111

112 Użycie nowej implementacji File Jeśli aplikacja podczas działania korzysta z plików dyskowych odwołując się do nich poprzez obiekty klasy File, należy dokonać odpowiednich zmian w kodzie tak, aby różni tenanci nie mieli dostępu do tych samych plików. Zamiast standardowego obiektu File, użyć należy TenantIsolatingFile, na przykład: File file = new TenantIsolatingFile("c:\\saastest\\aa.txt"); JPetStore nie korzysta jednakże z plików dyskowych, nie są wymagane więc żadne zmiany Przypadki testowe Po uruchomieniu aplikacji w środowisku multitenant, aplikacja poddana jest testom w celu zweryfikowania izolacji transakcji oraz danych tenantów. Przy pomocy narzędzia saas-web dodawane są konta dla 3 tenantów. Każdy z nich charakteryzuje się odrębnymi wartościami dla właściwości domeny, nazwy czy też schematu bazy danych. Tenant nr 1 korzysta z własnego DataSource, podczas gdy tenanci nr 2 oraz 3 korzystają ze współdzielonego DataSource: Id Name Schemaname Domain datasourceconfigid 1 tenant1 jpetstore1 domain1 1 2 tenant2 jpetstore2 domain2 2 3 tenant3 jpetstore3 domain3 2 Tab. 4. Testy - konfiguracja danych testowych tenantów Id Name Username Password Minidle Maxidle Maxactive Shared 1 ds1 saastest saastest false 2 ds2 saastest saastest true Tab. 5. Testy - konfiguracja danych testowych DataSource 112

113 Dane w tabelach wypełnione są przykładowymi danymi, różnymi dla różnych tenantów. Dodatkowo, stworzone zostały aliasy dla domen domain1, domain2, domain3 wskazujące na adres lokalnej maszyny ( ) Przypadek testowy 1 weryfikacja dostępu do aplikacji Przypadek ten testuje, czy możliwy jest dostęp do aplikacji z domeny, dla której istnieje zarejestrowany tenant oraz wykazuje, że dostęp z domeny zarejestrowanej nie jest możliwy. Wchodząc do sklepu poprzez domenę domain1, uzyskuje się widok sklepu internetowego: Rys. 26. Testy - strona startowa JPetStore dla zarejestrowanego tenanta 113

114 podczas gdy po wejściu przez domenę domain4 (niezarejestrowaną) pokazuje się komunikat o braku tenanta. Podczas dostępu do sklepu z zarejestrowanej domeny, wywoływany przez każdym Servletem TenantResolutionFilter identyfikuje tenanta. Pojawienie się strony sklepu dla zarejestrowanego tenanta dowodzi poprawności działania filtra Przypadek testowy 2 weryfikacja poprawności danych sklepu Pod weryfikację poddaje się w tym scenariuszu zawartość tabel z produktami danego tenanta. Dla tenanta tenant1, witryna powinna udostępniać produkty tenanta tenant1, podczas, gdy dla tenanta tenant2, produkty tenanta tenant2: Rys. 27. Testy przykładowe dane tenanta tenant1 w JPetStore 114

115 Rys. 28. Testy - przykładowe dane tenanta tenant2 w JPetStore Poprawne wyniki testu pokazują poprawne działanie TenantResolutionFilter, poprawne działanie nowych implementacji DataSource oraz poprawny dostęp do schematu danego tenanta Przypadek testowy 3 separacja logowania Celem tego scenariusza jest weryfikacja izolacji danych logowanych dla różnych tenantów. Po zalogowaniu się do sklepu przez użytkownika z domeny tenanta nr 1, a następnie użytkownika z domeny tenanta nr 2, można zaobserwować, że w pliku z logami (WEB-INF/petstore.log) pojawiają się wpisy kwalifikowane identyfikatorem tenanta, np.: :37:58,109 INFO [pl.edu.agh.saas.datasource.delegatingdatasource] [1] - Creating data source ds1 (1) 115

116 :37:58,125 INFO [pl.edu.agh.saas.datasource.delegatingdatasource] [1] - Tenant 1 using data source ds1 (1) :47:05,328 INFO [pl.edu.agh.saas.datasource.delegatingdatasource] [2] - Creating data source ds2 (2) :47:05,343 INFO [pl.edu.agh.saas.datasource.delegatingdatasource] [2] - Tenant 2 using data source ds2 (2) Poprawne wyniki testu ponownie dowodzą poprawności zachowania filtra oraz działania nowej implementacji Layout dla Log4j Przypadek testowy 4 weryfikacja izolacji sesji użytkownika Celem tego scenariusza jest upewnienie się, iż sesja użytkownika nie jest dzielona w sklepie internetowym pomiędzy różnych tenantów (chociaż sesje powinny być oddzielne już na etapie cookie różne sklepy dostępne są pod różnymi domenami). Przygotowanie testu polega na zarejestrowaniu dwóch użytkowników o tym samym loginie dla dwóch różnych tenantów (1 i 2). Kolejnym krokiem jest zalogowanie się w sklepie tenanta nr 1, a następnie wejściu do sklepu tenanta nr 2. W sklepie tenanta nr 2 użytkownik powinien być niezalogowany, a u góry powinno widnieć Sign in (nie Sign out!). Poprawny przebieg testu gwarantuje izolację sesji użytkownika pomiędzy sklepami różnych tenantów Przypadek testowy 5 dostęp za pomocą Web Service Celem tego scenariusza jest upewnienie się, iż dostęp do usługi getorder udostępnionej jako Web Service, daje odpowiednie rezultaty dla różnych tenantów. Najpierw przygotowane zostały 2 zamówienia o tym samym identyfikatorze. Poprzez witrynę internetową tenanta nr 1 zamówiono jeden z oferowanych towarów, natomiast poprzez witrynę tenanta nr 2 inny. Jako, że jest to pierwsze zamówienie w obydwóch witrynach, otrzymało ten sam identyfikator:

117 Weryfikacja działania serwisu została wykonana poprzez dostarczony razem z JPetStore program kliencki do wywołań zdalnych. W konfiguracji programu (clientcontext.xml) zmieniono namespaceuri na taki sam, jaki podano w konfiguracji Web Service dla JPetStore, czyli jpetstore/orderservice: <bean id="jaxrpcproxy" class="org.springframework.remoting.jaxrpc.jaxrpcportproxyfactorybean">... <property name="namespaceuri"> <value>jpetstore/orderservice</value> </property>... </bean> Następnie program kliencki uruchomiono dla sklepów dwóch różnych tenantów (zmiana ustawienia servername w client.properties na domenę odpowiedniego tenanta):./client.bat 1000 Uzyskanie odpowiednich przedmiotów poprzez zapytanie serwisów odpowiednich tenantów dowiodło poprawności działania wywołania zdalnego. 5.2 PetClinic Drugą z aplikacji, na których został przetestowany MEF jest PetClinic. Aplikacja ta stanowi system obsługujący przychodnię weterynaryjną dla zwierząt. Pozwala na zarządzanie danymi związanymi z weterynarzami, właścicielami zwierząt, ich zwierzętami oraz wizytami u weterynarzy. Podobnie jak w przypadku JPetStore, aplikacja oparta została na frameworku Spring. Za dostęp do warstwy danych odpowiedzialny jest Hibernate Integracja z MEF W celu udostępnienia przykładowej aplikacji w modelu multitenant należy wykonać kilka kroków konfiguracyjnych, integrujących MEF z aplikacją. 117

118 Dodanie bibliotek Pierwszym krokiem migracji aplikacji do modelu SaaS jest zadbanie o dostępność odpowiednich klas. Konieczne jest dołączenie bibliotek frameworku saas-tools.jar oraz saas-web.jar, oraz zależności: log4j, hibernate, dom4j, slf4-api, slf4j-log4j12, commons-io Konfiguracja komponentów Należy dołączyć konfigurację MultiTenantContext oraz pozostałych komponentów frameworku, wybrać konfigurację Hibernate dla dostępu do danych, oraz wybrać MySQL jako system baz danych: 1. Zmiany w web.xml (dodanie /WEB-INF/saasConfiguration.xml, wybór applicationcontext-hibernate.xml jako konfiguracji warstwy dostępu do danych): <context-param> <param-name>contextconfiglocation</param-name> <param-value> /WEB-INF/applicationContext-hibernate.xml /WEB-INF/saasConfiguration.xml </param-value> </context-param> 2. Dodanie pliku konfiguracyjnego saasconfiguration.xml, zawierającego definicje Beanów sessionfactory, saasdatasource, datasourceconfigdao, tenantconfigdao, multitenantcontext, filefactory (zał. 1.). 3. Dodanie konfiguracji dla Hibernate mapping.hbm.xml (mapowanie O/R dla bazy administracyjnej) (zał. 2.) 4. Utworzenie administracyjnej bazy danych na serwerze bazy danych (localhost), zgodnie z ustaloną konfiguracją: CREATE DATABASE tenantsadministration; GRANT ALL ON tenantsadministration.* TO IDENTIFIED BY 'saas123'; 118

119 Rekonfiguracja DataSource DataSource aplikacji musi być przekonfigurowany tak, aby korzystał z implementacji DelegatingDataSource, otrzymał referencję do MultiTenantContext w parametrze multitenantcontext oraz aby adres dostępowy URL nie zawierał nazwy schematu: <bean id="datasource" class="pl.edu.agh.saas.datasource.delegatingdatasource" destroy-method="close"> <property name="driverclassname" value="${jdbc.driverclassname}"/> <property name="url" value="${jdbc.url}"/> <property name="multitenantcontext" ref="multitenantcontext"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> Plik jdbc.properties: jdbc.driverclassname=com.mysql.jdbc.driver jdbc.url=jdbc:mysql://localhost:3306/ jdbc.username=saastest jdbc.password=saastest Second level cache/query cache Aby skorzystać z możliwości cache owania, jaką daje Hibernate, wykonać należy poniższe kroki. Są one jednak opcjonalne. Dla wszystkich bytów zdefiniowanych w mapowaniu Hibernate załączyć należy cache drugiego poziomu, poprzez dodanie wewnątrz beanów: <cache usage="read-write"/> Aby zapewnić izolację cache owanych danych, dodatkowo w pliku applicationcontext-hibernate.xml określić należy konfigurację cache: <prop key="hibernate.cache.provider_class"> pl.edu.agh.saas.cache.hibernate.delegatingcacheprovider </prop> <prop key="hibernate.cache.underlying_provider_class"> org.hibernate.cache.hashtablecacheprovider </prop> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.use_query_cache">true</prop> 119

120 TenantResolutionFilter dla Servletów Należy ustawić odpowiedni filtr (TenantResolutionFilter, odpowiedzialny za identyfikację tenanta) dla wszystkich Servletów, tak, aby w czasie wykonywania kodu Servletu znany był tenant. Dodatkowo należy zmienić ustawienia wersji aplikacji internetowej, na 2.5: <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee <filter> <filter-name>tenantresolution</filter-name> <filter-class>filter.tenantresolutionfilter</filter-class> <init-param> <param-name>redirect</param-name> <param-value>../notenant.html</param-value> </init-param> </filter> <filter-mapping> <filter-name>tenantresolution</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> Poprawić należy też ścieżkę do JSTL w includes.jsp: taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> Separacja danych logowania W celu możliwości odseparowania danych logowanych przez różnych tenantów, należy wprowadzić jedną z zaimplementowanych metod separacji (dodanie Id tenanta do komunikatu lub logowania do różnych plików). W PetClinic ustawić należy nowy Appender w pliku konfiguracyjnym Log4j (war/web-inf/log4j.properties): log4j.appender.logfile=pl.edu.agh.saas.logging.pertenantfileappender log4j.appender.logfile.file=c:\\saastest2\\$t\\log.txt log4j.appender.logfile.appenderscount=10 log4j.appender.logfile.layout=org.apache.log4j.patternlayout log4j.appender.logfile.layout.conversionpattern=%d %p [%c] - %m%n 120

121 W miejscu $t podstawione zostanie Id tenanta. Plik z logami dla każdego z tenantów trafi do innego katalogu. Jeśli korzystamy z serwera innego niż Jboss, należy odkomentować Listener Log4j w pliku web.xml: <listener> <listener-class> org.springframework.web.util.log4jconfiglistener </listener-class> </listener> Konfiguracja saas-web dla aplikacji Dodatkowo, aby umożliwić dodawanie nowych tenantów, należy skonfigurować (a następnie wdrożyć i uruchomić na serwerze webowym) narzędzie saas-web. W pliku konfiguracyjnym saasconfiguration.xml należy zadbać o odpowiednie ustawienie administracyjnego DataSource, ścieżki dla systemu plików z katalogami tenantów oraz ścieżki, w której znajdują się pliki SQL z definicjami tabel (zał. 1.). Dla PetClinic umieszczono w katalogu określonym w konfiguracji komponentu SchemaCreator plik SQL z definicjami do tworzenia tabel (dostępny w katalogu db projektu PetClinic) Przypadki testowe Konfiguracja aplikacji do testu jest analogiczna, jak w przypadku testów aplikacji JPetStore Przypadek testowy 1 weryfikacja dostępu do aplikacji Przypadek ten testuje, czy możliwy jest dostęp do aplikacji z domeny, dla której istnieje zarejestrowany tenant oraz, że dostęp z domeny zarejestrowanej nie jest możliwy. Wchodząc do kliniki poprzez domenę domain1, uzyskuje się widok witryny: 121

122 Rys. 29. Testy - strona startowa PetClinic dla zarejestrowanego tenanta podczas, gdy po wejściu przez domenę domain4 (niezarejestrowaną) pokazuje się komunikat o braku tenanta. Podczas dostępu do witryny z zarejestrowanej domeny, wywoływany przez każdym Servletem TenantResolutionFilter identyfikuje tenanta. Pojawienie się witryny dla zarejestrowanego tenanta dowodzi poprawności działania filtra Przypadek testowy 2 weryfikacja poprawności danych sklepu Weryfikacji poddaje się w tym scenariuszu zawartość tabel z danymi tenanta. Dla tenanta tenant1, witryna powinna udostępniać dane tenanta tenant1, podczas, gdy dla tenanta tenant2, dane tenanta tenant2: 122

123 Rys. 30. Testy przykładowe dane tenanta tenant1 w PetClinic Rys. 31. Testy przykładowe dane tenanta tenant2 w PetClinic 123

Mateusz Kurleto NEOTERIC. Analiza projektu B2B Kielce, 18 października 2012

Mateusz Kurleto NEOTERIC. Analiza projektu B2B Kielce, 18 października 2012 2012 Pierwsze przymiarki do zakresu informatyzacji (rodzaj oprogramowania: pudełkowe, SaaS, Iaas, CC, PaaS. Zalety i wady: dostępność, koszty, narzędzia, ludzie, utrzymanie, bezpieczeństwo, aspekty prawne)

Bardziej szczegółowo

CLOUD COMPUTING CHMURA OBLICZENIOWA I PLATFORMA WINDOWS AZURE

CLOUD COMPUTING CHMURA OBLICZENIOWA I PLATFORMA WINDOWS AZURE CLOUD COMPUTING CHMURA OBLICZENIOWA I PLATFORMA WINDOWS AZURE Chmura obliczeniowa (ang. cloud computing) Termin chmura obliczeniowa powstał na początku XXI w., ale sam pomysł pojawił się już w XX w. Nazwa

Bardziej szczegółowo

Grzegorz Ruciński. Warszawska Wyższa Szkoła Informatyki 2011. Promotor dr inż. Paweł Figat

Grzegorz Ruciński. Warszawska Wyższa Szkoła Informatyki 2011. Promotor dr inż. Paweł Figat Grzegorz Ruciński Warszawska Wyższa Szkoła Informatyki 2011 Promotor dr inż. Paweł Figat Cel i hipoteza pracy Wprowadzenie do tematu Przedstawienie porównywanych rozwiązań Przedstawienie zalet i wad porównywanych

Bardziej szczegółowo

Cloud Computing - Wprowadzenie. Bogusław Kaczałek Kon-dor GIS Konsulting

Cloud Computing - Wprowadzenie. Bogusław Kaczałek Kon-dor GIS Konsulting Cloud Computing - Wprowadzenie Bogusław Kaczałek Kon-dor GIS Konsulting Rola służby GiK w tworzeniu polskiej IIP Wisła 8-10 września 2010 Cloud computing Cloud computing (ang. "przetwarzanie w chmurze,

Bardziej szczegółowo

HP Service Anywhere Uproszczenie zarządzania usługami IT

HP Service Anywhere Uproszczenie zarządzania usługami IT HP Service Anywhere Uproszczenie zarządzania usługami IT Robert Nowak Architekt rozwiązań HP Software Dlaczego Software as a Service? Najważniejsze powody za SaaS UZUPEŁNIENIE IT 2 Brak zasobów IT Ograniczone

Bardziej szczegółowo

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych PAŃSTWOWA WYŻSZA SZKOŁA ZAWODOWA W ELBLĄGU INSTYTUT INFORMATYKI STOSOWANEJ Sprawozdanie z Seminarium Dyplomowego Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Bardziej szczegółowo

Klient SmartMedia Sp. z o.o., Dziennikus Sp. z o.o. Branża. IT, software. Okres realizacji. Lipiec 2015 - nadal. Rodzaj usługi:

Klient SmartMedia Sp. z o.o., Dziennikus Sp. z o.o. Branża. IT, software. Okres realizacji. Lipiec 2015 - nadal. Rodzaj usługi: Klient SmartMedia Sp. z o.o., Dziennikus Sp. z o.o. Branża IT, software Okres realizacji Lipiec 2015 - nadal Rodzaj usługi: Projekt i wdrożenie infrastruktury opartej o chmurę obliczeniową AWS, doradztwo,

Bardziej szczegółowo

LANDINGI.COM. Case Study. Klient Landingi.com. Branża IT, marketing i PR. Okres realizacji od grudnia 2013 do chwili obecnej.

LANDINGI.COM. Case Study. Klient Landingi.com. Branża IT, marketing i PR. Okres realizacji od grudnia 2013 do chwili obecnej. Klient Landingi.com Branża IT, marketing i PR Okres realizacji od grudnia 2013 do chwili obecnej Rodzaj usługi doradztwo, hosting, Cloud Computing Amazon Web Services, zarządzanie serwerami Doradztwo Hosting

Bardziej szczegółowo

Piotr Bubacz Cloud Computing

Piotr Bubacz Cloud Computing Cloud Computing ITA-112 Wersja 0.9 Warszawa, Czerwiec 2011 Spis treści Wprowadzenie i-4 Moduł 1 Wprowadzenie do Cloud Computing 1-1 Moduł 2 Wprowadzenie do Windows 2-1 Moduł 3 Storage Tabele 3-1 Moduł

Bardziej szczegółowo

SiR_13 Systemy SCADA: sterowanie nadrzędne; wizualizacja procesów. MES - Manufacturing Execution System System Realizacji Produkcji

SiR_13 Systemy SCADA: sterowanie nadrzędne; wizualizacja procesów. MES - Manufacturing Execution System System Realizacji Produkcji System informatyczny na produkcji: Umożliwi stopniowe, ale jednocześnie ekonomiczne i bezpieczne wdrażanie i rozwój aplikacji przemysłowych w miarę zmiany potrzeb firmy. Może adoptować się do istniejącej

Bardziej szczegółowo

Referat pracy dyplomowej

Referat pracy dyplomowej Referat pracy dyplomowej Temat pracy: Wdrożenie intranetowej platformy zapewniającej organizację danych w dużej firmie na bazie oprogramowania Microsoft SharePoint Autor: Bartosz Lipiec Promotor: dr inż.

Bardziej szczegółowo

Przepełnienie bufora. SQL Injection Załączenie zewnętrznego kodu XSS. Nabycie uprawnień innego użytkownika/klienta/administratora

Przepełnienie bufora. SQL Injection Załączenie zewnętrznego kodu XSS. Nabycie uprawnień innego użytkownika/klienta/administratora NAUKOWA I AKADEMICKA SIEĆ KOMPUTEROWA Bezpieczeństwo rozwiązań hostingowych Hosting wirtualny - studium przypadku Secure 2008 3 października 2008 Arkadiusz Kalicki, NASK Agenda Zagrożenia Omówienie zabezpieczeń

Bardziej szczegółowo

ul. Pogodna 6 10-647 Olsztyn +48 504 647 030 codeit@codeit.pl http://codeit.pl

ul. Pogodna 6 10-647 Olsztyn +48 504 647 030 codeit@codeit.pl http://codeit.pl Aplikacja 'mcrm' codeit ul. Pogodna 6 10-647 Olsztyn +48 504 647 030 codeit@codeit.pl 1. Idea Aplikacja 'mcrm' to prosty system klasy CRM (Customer Relationship Management) stworzony z myślą o małych i

Bardziej szczegółowo

1 Wprowadzenie do J2EE

1 Wprowadzenie do J2EE Wprowadzenie do J2EE 1 Plan prezentacji 2 Wprowadzenie do Java 2 Enterprise Edition Aplikacje J2EE Serwer aplikacji J2EE Główne cele V Szkoły PLOUG - nowe podejścia do konstrukcji aplikacji J2EE Java 2

Bardziej szczegółowo

Informatyzacja JST z zastosowaniem technologii przetwarzania w chmurze

Informatyzacja JST z zastosowaniem technologii przetwarzania w chmurze Informatyzacja JST z zastosowaniem technologii przetwarzania w chmurze Centrum Projektów Informatycznych Warszawa, 22 kwietnia 2013 r. Agenda 1. Prezentacja ogólnych informacji na temat uruchomionego projektu

Bardziej szczegółowo

Co to jest chmura (Cloud Computing)?

Co to jest chmura (Cloud Computing)? Co to jest chmura (Cloud Computing)? Według jednej z teorii chmura to przeniesienie pewnych zasobów (serwerów, danych, aplikacji) z naszej firmy/serwerowni w inne miejsce. I to bez względu na to czy to

Bardziej szczegółowo

DLA SEKTORA INFORMATYCZNEGO W POLSCE

DLA SEKTORA INFORMATYCZNEGO W POLSCE DLA SEKTORA INFORMATYCZNEGO W POLSCE SRK IT obejmuje kompetencje najważniejsze i specyficzne dla samego IT są: programowanie i zarządzanie systemami informatycznymi. Z rozwiązań IT korzysta się w każdej

Bardziej szczegółowo

Case Study: Migracja 100 serwerów Warsaw Data Center z platformy wirtualizacji OpenSource na platformę Microsoft Hyper-V

Case Study: Migracja 100 serwerów Warsaw Data Center z platformy wirtualizacji OpenSource na platformę Microsoft Hyper-V Case Study: Migracja 100 serwerów Warsaw Data Center z platformy wirtualizacji OpenSource na platformę Microsoft Hyper-V Warszawa, 6 lutego 2014 www.hypermixer.pl 01 1 2 3 4 Rynkowe wyzwania Poszukiwania

Bardziej szczegółowo

Modele sprzedaży i dystrybucji oprogramowania Teoria a praktyka SaaS vs. BOX. Bartosz Marciniak. Actuality Sp. z o.o.

Modele sprzedaży i dystrybucji oprogramowania Teoria a praktyka SaaS vs. BOX. Bartosz Marciniak. Actuality Sp. z o.o. Modele sprzedaży i dystrybucji oprogramowania Teoria a praktyka SaaS vs. BOX Bartosz Marciniak Actuality Sp. z o.o. Prezes Zarządu Społeczeństwo informacyjne społeczeństwo, które znalazło zastosowanie

Bardziej szczegółowo

EJB 3.0 (Enterprise JavaBeans 3.0)

EJB 3.0 (Enterprise JavaBeans 3.0) EJB 3.0 (Enterprise JavaBeans 3.0) Adrian Dudek Wirtualne Przedsiębiorstwo 2 Wrocław, 1 czerwca 2010 Plan prezentacji 1 Wprowadzenie Cel prezentacji Czym jest EJB 3.0? Historia 2 3 Cel prezentacji Wprowadzenie

Bardziej szczegółowo

CloudFerro. Chmury publiczne, chmury prywatne, serwery dedykowane zalety, wady, problemy, ograniczenia, wyzwania.

CloudFerro. Chmury publiczne, chmury prywatne, serwery dedykowane zalety, wady, problemy, ograniczenia, wyzwania. CloudFerro Chmury publiczne, chmury prywatne, serwery dedykowane zalety, wady, problemy, ograniczenia, wyzwania. Stanisław Dałek 2015 Agenda Środowiska do uruchamiania aplikacji internetowych Jakie są

Bardziej szczegółowo

Jednolite zarządzanie użytkownikami systemów Windows i Linux

Jednolite zarządzanie użytkownikami systemów Windows i Linux Uniwersytet Mikołaja Kopernika Wydział Matematyki i Informatyki Wydział Fizyki, Astronomii i Informatyki Stosowanej Paweł Gliwiński Nr albumu: 168470 Praca magisterska na kierunku Informatyka Jednolite

Bardziej szczegółowo

PureSystems zautomatyzowane środowisko aplikacyjne. Emilia Smółko Software IT Architect

PureSystems zautomatyzowane środowisko aplikacyjne. Emilia Smółko Software IT Architect PureSystems zautomatyzowane środowisko aplikacyjne. Emilia Smółko Software IT Architect Wbudowana wiedza specjalistyczna Dopasowane do zadania Optymalizacja do aplikacji transakcyjnych Inteligentne Wzorce

Bardziej szczegółowo

Virtual Grid Resource Management System with Virtualization Technology

Virtual Grid Resource Management System with Virtualization Technology Virtual Grid Resource Management System with Virtualization Technology System zarządzania zasobami wirtualnego Gridu z wykorzystaniem technik wirtualizacji Joanna Kosińska Jacek Kosiński Krzysztof Zieliński

Bardziej szczegółowo

Prawne aspekty wykorzystania chmury obliczeniowej w administracji publicznej. Michał Kluska

Prawne aspekty wykorzystania chmury obliczeniowej w administracji publicznej. Michał Kluska Prawne aspekty wykorzystania chmury obliczeniowej w administracji publicznej Michał Kluska Prawne aspekty wykorzystania chmury obliczeniowej w administracji publicznej Łopuszna, 6-7 lutego 2012 r. Agenda:

Bardziej szczegółowo

Rodzaje pamięci masowych by Silas Mariusz

Rodzaje pamięci masowych by Silas Mariusz Rodzaje pamięci masowych by Silas Mariusz 1. Online Silas Mariusz Administrator TS-x79U 1 GbE Pamięć masowa może być instalowana bezpośrednio w serwerach w postaci dysków tworzących tzw. system DAS (Direct

Bardziej szczegółowo

SYSTEM VILM ZARZĄDZANIE CYKLEM ŻYCIA ŚRODOWISK WIRTUALNYCH. info@prointegra.com.pl tel: +48 (032) 730 00 42

SYSTEM VILM ZARZĄDZANIE CYKLEM ŻYCIA ŚRODOWISK WIRTUALNYCH. info@prointegra.com.pl tel: +48 (032) 730 00 42 SYSTEM VILM ZARZĄDZANIE CYKLEM ŻYCIA ŚRODOWISK WIRTUALNYCH info@prointegra.com.pl tel: +48 (032) 730 00 42 1. WPROWADZENIE... 3 2. KORZYŚCI BIZNESOWE... 4 3. OPIS FUNKCJONALNY VILM... 4 KLUCZOWE FUNKCJE

Bardziej szczegółowo

BCC ECM Autorskie rozwiązanie BCC wspomagające zarządzanie dokumentami oraz procesami biznesowymi

BCC ECM Autorskie rozwiązanie BCC wspomagające zarządzanie dokumentami oraz procesami biznesowymi BCC ECM Autorskie rozwiązanie BCC wspomagające zarządzanie dokumentami oraz procesami biznesowymi Prezentacja rozwiązania Co to jest ECM? ECM (enterprise content management) to strategia świadomego zarządzania

Bardziej szczegółowo

Plan. Wprowadzenie. Co to jest APEX? Wprowadzenie. Administracja obszarem roboczym

Plan. Wprowadzenie. Co to jest APEX? Wprowadzenie. Administracja obszarem roboczym 1 Wprowadzenie do środowiska Oracle APEX, obszary robocze, użytkownicy Wprowadzenie Plan Administracja obszarem roboczym 2 Wprowadzenie Co to jest APEX? Co to jest APEX? Architektura Środowisko Oracle

Bardziej szczegółowo

Koncepcja wirtualnej pracowni GIS w oparciu o oprogramowanie open source

Koncepcja wirtualnej pracowni GIS w oparciu o oprogramowanie open source Koncepcja wirtualnej pracowni GIS w oparciu o oprogramowanie open source Dr inż. Michał Bednarczyk Uniwersytet Warmińsko-Mazurski w Olsztynie Wydział Geodezji i Gospodarki Przestrzennej Katedra Geodezji

Bardziej szczegółowo

SOA Web Services in Java

SOA Web Services in Java Wydział Informatyki i Zarządzania Wrocław,16 marca 2009 Plan prezentacji SOA 1 SOA 2 Usługi Przykłady Jak zacząć SOA Wycinek rzeczywistości Problemy zintegrowanych serwisów : Wycinek Rzeczywistości Zacznijmy

Bardziej szczegółowo

Ekspert MS SQL Server Oferta nr 00/08

Ekspert MS SQL Server Oferta nr 00/08 Ekspert MS SQL Server NAZWA STANOWISKA Ekspert Lokalizacja/ Jednostka organ.: Pion Informatyki, Biuro Hurtowni Danych i Aplikacji Wspierających, Zespół Jakości Oprogramowania i Utrzymania Aplikacji Szczecin,

Bardziej szczegółowo

1. Zakres modernizacji Active Directory

1. Zakres modernizacji Active Directory załącznik nr 1 do umowy 1. Zakres modernizacji Active Directory 1.1 Opracowanie szczegółowego projektu wdrożenia. Określenie fizycznych lokalizacji serwerów oraz liczby lokacji Active Directory Określenie

Bardziej szczegółowo

Prestige MJM Case Study

Prestige MJM Case Study Klient Prestige MJM Branża Wydarzenia artystyczne, opieka menadżerska Okres realizacji 1 luty 19 sierpień 2014 Rodzaj usługi: Zarządzanie serwerami, doradztwo przy tworzeniu architektury, konfiguracja

Bardziej szczegółowo

Zapewnienie dostępu do Chmury

Zapewnienie dostępu do Chmury Zapewnienie dostępu do Chmury O bezpiecznym i sprawnym dostępie do Chmury i danych w Chmurze. Marcin Tynda Business Development Manager Grupa Onet S.A. Warszawa, 24.06.2013 1 Kto jest kim Klient? Kim jest

Bardziej szczegółowo

SERWERY KOMUNIKACYJNE ALCATEL-LUCENT

SERWERY KOMUNIKACYJNE ALCATEL-LUCENT SERWERY KOMUNIKACYJNE ALCATEL-LUCENT OmniPCX Enterprise Serwer komunikacyjny Alcatel-Lucent OmniPCX Enterprise Communication Server (CS) to serwer komunikacyjny dostępny w formie oprogramowania na różne

Bardziej szczegółowo

Licencjonowanie System Center 2012 R2

Licencjonowanie System Center 2012 R2 Licencjonowanie Opis produktu Microsoft zapewnia rozwiązania służące do zarządzania zasobami centrów przetwarzania danych, prywatnymi chmurami obliczeniowymi i urządzeniami klienckimi. Zarządzanie prywatną

Bardziej szczegółowo

Projektowanie architektury systemu rozproszonego. Jarosław Kuchta Projektowanie Aplikacji Internetowych

Projektowanie architektury systemu rozproszonego. Jarosław Kuchta Projektowanie Aplikacji Internetowych Projektowanie architektury systemu rozproszonego Jarosław Kuchta Zagadnienia Typy architektury systemu Rozproszone przetwarzanie obiektowe Problemy globalizacji Problemy ochrony Projektowanie architektury

Bardziej szczegółowo

Uniwersytet Mikołaja Kopernika. Wydział Matematyki i Informatyki Wydział Fizyki, Astronomii i Informatyki Stosowanej

Uniwersytet Mikołaja Kopernika. Wydział Matematyki i Informatyki Wydział Fizyki, Astronomii i Informatyki Stosowanej Uniwersytet Mikołaja Kopernika Wydział Matematyki i Informatyki Wydział Fizyki, Astronomii i Informatyki Stosowanej Marcin HENRYKOWSKI Nr albumu: 158069 Praca magisterska na kierunku Informatyka Archiwizacja

Bardziej szczegółowo

Web frameworks do budowy aplikacji zgodnych z J2EE

Web frameworks do budowy aplikacji zgodnych z J2EE Web frameworks do budowy aplikacji zgodnych z J2EE Jacek Panachida promotor: dr Dariusz Król Przypomnienie Celem pracy jest porównanie wybranych szkieletów programistycznych o otwartym kodzie źródłowym

Bardziej szczegółowo

Problemy niezawodnego przetwarzania w systemach zorientowanych na usługi

Problemy niezawodnego przetwarzania w systemach zorientowanych na usługi Problemy niezawodnego przetwarzania w systemach zorientowanych na usługi Jerzy Brzeziński, Anna Kobusińska, Dariusz Wawrzyniak Instytut Informatyki Politechnika Poznańska Plan prezentacji 1 Architektura

Bardziej szczegółowo

Web frameworks do budowy aplikacji zgodnych z J2EE. Jacek Panachida

Web frameworks do budowy aplikacji zgodnych z J2EE. Jacek Panachida Web frameworks do budowy aplikacji zgodnych z J2EE Jacek Panachida Cel pracy Analiza wybranych ram projektowych dostępnych dla platformy Java Warunki selekcji napisany z wykorzystaniem języka Java oraz

Bardziej szczegółowo

System generacji raportów

System generacji raportów Zalety systemu Czym jest ProReports? prostota instalacji, wieloplatformowość (AIX, Linux, Windows, Solaris), obsługa popularnych formatów (PDF, XLS, RTF, HTML,TXT,XML,CSV), obsługa wielu baz danych, raporty

Bardziej szczegółowo

Wykład 1 Inżynieria Oprogramowania

Wykład 1 Inżynieria Oprogramowania Wykład 1 Inżynieria Oprogramowania Wstęp do inżynierii oprogramowania. Cykle rozwoju oprogramowaniaiteracyjno-rozwojowy cykl oprogramowania Autor: Zofia Kruczkiewicz System Informacyjny =Techniczny SI

Bardziej szczegółowo

Szanse i zagrożenia płynące z nowoczesnych metod świadczenia usług informatycznych (outsourcing, offshoring, SOA, cloud computing) w bankowości

Szanse i zagrożenia płynące z nowoczesnych metod świadczenia usług informatycznych (outsourcing, offshoring, SOA, cloud computing) w bankowości Szanse i zagrożenia płynące z nowoczesnych metod świadczenia usług informatycznych (outsourcing, offshoring, SOA, cloud computing) w bankowości Jakub Syta, CISA, CISSP Warszawa, 14 czerwca 2010 1 Zastrzeżenie

Bardziej szczegółowo

System Kancelaris. Zdalny dostęp do danych

System Kancelaris. Zdalny dostęp do danych Kancelaris krok po kroku System Kancelaris Zdalny dostęp do danych Data modyfikacji: 2008-07-10 Z czego składaj adają się systemy informatyczne? System Kancelaris składa się z dwóch części: danych oprogramowania,

Bardziej szczegółowo

Budowa systemu wspomagającego podejmowanie decyzji. Metodyka projektowo wdrożeniowa

Budowa systemu wspomagającego podejmowanie decyzji. Metodyka projektowo wdrożeniowa Budowa systemu wspomagającego podejmowanie decyzji Metodyka projektowo wdrożeniowa Agenda Systemy wspomagające decyzje Business Intelligence (BI) Rodzaje systemów BI Korzyści z wdrożeń BI Zagrożenia dla

Bardziej szczegółowo

Architektura korporacyjna jako narzędzie koordynacji wdrażania przetwarzania w chmurze

Architektura korporacyjna jako narzędzie koordynacji wdrażania przetwarzania w chmurze Architektura korporacyjna jako narzędzie koordynacji wdrażania przetwarzania w chmurze Prof. SGH, dr hab. Andrzej Sobczak, Kierownik Zakładu Systemów Informacyjnych, Katedra Informatyki Gospodarczej SGH

Bardziej szczegółowo

TECHNOLOGY ADVANTAGE Sky Is The Limit......Czyli jak usługi w chmurze zmieniają małe i średnie firmy

TECHNOLOGY ADVANTAGE Sky Is The Limit......Czyli jak usługi w chmurze zmieniają małe i średnie firmy TECHNOLOGY ADVANTAGE Sky Is The Limit......Czyli jak usługi w chmurze zmieniają małe i średnie firmy Warszawa, marzec 2014 Dotychczas małym i średnim firmom trudno było zyskać dostęp do nowoczesnych rozwiązań

Bardziej szczegółowo

Automatyzacja procesów biznesowych Andrzej Sobecki. ESB Enterprise service bus

Automatyzacja procesów biznesowych Andrzej Sobecki. ESB Enterprise service bus Automatyzacja procesów biznesowych Andrzej Sobecki ESB Enterprise service bus Plan prezentacji Zdefiniowanie problemu Możliwe rozwiązania Cechy ESB JBI Normalizacja wiadomości w JBI Agile ESB Apache ServiceMix

Bardziej szczegółowo

Załącznik nr 1. Specyfikacja techniczna portalu internetowego Łódź, 15.10.2012 r.

Załącznik nr 1. Specyfikacja techniczna portalu internetowego Łódź, 15.10.2012 r. Załącznik nr 1. Specyfikacja techniczna portalu internetowego Łódź, 15.10.2012 r. Stworzenie platformy internetowej na potrzeby projektu. 1 Wykonanie portalu internetowego na potrzeby e-usługi, obejmującego

Bardziej szczegółowo

Instalacja SQL Server Express. Logowanie na stronie Microsoftu

Instalacja SQL Server Express. Logowanie na stronie Microsoftu Instalacja SQL Server Express Logowanie na stronie Microsoftu Wybór wersji do pobrania Pobieranie startuje, przechodzimy do strony z poradami. Wypakowujemy pobrany plik. Otwiera się okno instalacji. Wybieramy

Bardziej szczegółowo

Bazy danych 2. Wykład 1

Bazy danych 2. Wykład 1 Bazy danych 2 Wykład 1 Sprawy organizacyjne Materiały i listy zadań zamieszczane będą na stronie www.math.uni.opole.pl/~ajasi E-mail: standardowy ajasi@math.uni.opole.pl Sprawy organizacyjne Program wykładu

Bardziej szczegółowo

AKADEMIA GÓRNICZO-HUTNICZA Wydział Elektrotechniki, Automatyki, Informatyki i Elektroniki

AKADEMIA GÓRNICZO-HUTNICZA Wydział Elektrotechniki, Automatyki, Informatyki i Elektroniki AKADEMIA GÓRNICZO-HUTNICZA Wydział Elektrotechniki, Automatyki, Informatyki i Elektroniki KATEDRA INFORMATYKI Mobicents VoIP Projekt wykonany w ramach SIUS i IOSR Biolik Wojciech Błazej Kardyś Informatyka,

Bardziej szczegółowo

Szczegółowy opis przedmiotu zamówienia

Szczegółowy opis przedmiotu zamówienia Załącznik nr 1b do SIWZ Szczegółowy opis przedmiotu zamówienia Cześć II Dostawa niewyłącznych, nieograniczonych czasowo 3 sztuk licencji oprogramowania Microsoft Server 2012 R2 DataCenter x64 w celu rozbudowy

Bardziej szczegółowo

Architektura Systemu. Architektura systemu umożliwia kontrolowanie iteracyjnego i przyrostowego procesu tworzenia systemu.

Architektura Systemu. Architektura systemu umożliwia kontrolowanie iteracyjnego i przyrostowego procesu tworzenia systemu. Architektura Systemu Architektura systemu umożliwia kontrolowanie iteracyjnego i przyrostowego procesu tworzenia systemu. Architektura jest zbiorem decyzji dotyczących: organizacji systemu komputerowego,

Bardziej szczegółowo

OSGi Agata Hejmej 4.05.2009

OSGi Agata Hejmej 4.05.2009 OSGi Agata Hejmej 4.05.2009 Plan prezentacji Co to jest OSGi Jakie problemy rozwiązuje Opis standardu Przykładowa aplikacja Podsumowanie korzyści Co to jest OSGi? Standard, który pozwala na tworzenie wysoce

Bardziej szczegółowo

Praca w sieci z serwerem

Praca w sieci z serwerem 11 Praca w sieci z serwerem Systemy Windows zostały zaprojektowane do pracy zarówno w sieci równoprawnej, jak i w sieci z serwerem. Sieć klient-serwer oznacza podłączenie pojedynczego użytkownika z pojedynczej

Bardziej szczegółowo

Leonard G. Lobel Eric D. Boyd. Azure SQL Database Krok po kroku. Microsoft. Przekład: Marek Włodarz. APN Promise, Warszawa 2014

Leonard G. Lobel Eric D. Boyd. Azure SQL Database Krok po kroku. Microsoft. Przekład: Marek Włodarz. APN Promise, Warszawa 2014 Leonard G. Lobel Eric D. Boyd Microsoft TM Azure SQL Database Krok po kroku Przekład: Marek Włodarz APN Promise, Warszawa 2014 Spis treści Wprowadzenie........................................................

Bardziej szczegółowo

Licencjonowanie pytania i odpowiedzi

Licencjonowanie pytania i odpowiedzi Pytanie: Czym jest CPS? Odpowiedź: CPS to akronim od Cloud Platform Suite, pakietu obejmującego produkty Windows Server 2012 R2, System Center 2012 R2, Windows Azure Pack oraz SQL Server 2012 Standard,

Bardziej szczegółowo

Wykład I. Wprowadzenie do baz danych

Wykład I. Wprowadzenie do baz danych Wykład I Wprowadzenie do baz danych Trochę historii Pierwsze znane użycie terminu baza danych miało miejsce w listopadzie w 1963 roku. W latach sześcdziesątych XX wieku został opracowany przez Charles

Bardziej szczegółowo

Dokumentacja aplikacji Szachy online

Dokumentacja aplikacji Szachy online Projekt z przedmiotu Technologie Internetowe Autorzy: Jakub Białas i Jarosław Tyma grupa II, Automatyka i Robotyka sem. V, Politechnika Śląska Przedmiot projektu: Aplikacja internetowa w języku Java Dokumentacja

Bardziej szczegółowo

System zarządzania i monitoringu

System zarządzania i monitoringu Załącznik nr 12 do Opisu przedmiotu zamówienia System zarządzania i monitoringu System zarządzania i monitoringu powinien być zbudowany z odrębnych, dedykowanych modułów oprogramowania, monitorujących:

Bardziej szczegółowo

Wprowadzenie do sieciowych systemów operacyjnych. Moduł 1

Wprowadzenie do sieciowych systemów operacyjnych. Moduł 1 Wprowadzenie do sieciowych systemów operacyjnych Moduł 1 Sieciowy system operacyjny Sieciowy system operacyjny (ang. Network Operating System) jest to rodzaj systemu operacyjnego pozwalającego na pracę

Bardziej szczegółowo

Aplikacje Internetowe, Servlety, JSP i JDBC

Aplikacje Internetowe, Servlety, JSP i JDBC Aplikacje Internetowe, Servlety, JSP i JDBC Opis Java 2 Enterprise Edition (JEE) jest potężną platformą do tworzenia aplikacji webowych. PLatforma JEE oferuje wszystkie zalety tworzenia w Javie plus wszechstronny

Bardziej szczegółowo

IO - SAD. M.Jałmużna T.Jurkiewicz P.Kasprzyk M.Robak. 5 czerwca 2006

IO - SAD. M.Jałmużna T.Jurkiewicz P.Kasprzyk M.Robak. 5 czerwca 2006 IO - SAD M.Jałmużna T.Jurkiewicz P.Kasprzyk M.Robak 5 czerwca 2006 1 SPIS TREŚCI 2 Spis treści 1 Historia zmian 3 2 Wprowadzenie 3 2.1 Cel................................. 3 2.2 Zakres...............................

Bardziej szczegółowo

Dane bezpieczne w chmurze

Dane bezpieczne w chmurze Dane bezpieczne w chmurze Grzegorz Śladowski Dyrektor Działu Technicznego S4E S.A. Agenda Chmura definicja, zasady działania, rodzaje Cechy bezpiecznej chmury Architektura Chmura - definicja Model przetwarzania

Bardziej szczegółowo

Autorytatywne serwery DNS w technologii Anycast + IPv6 DNS NOVA. Dlaczego DNS jest tak ważny?

Autorytatywne serwery DNS w technologii Anycast + IPv6 DNS NOVA. Dlaczego DNS jest tak ważny? Autorytatywne serwery DNS w technologii Anycast + IPv6 DNS NOVA Dlaczego DNS jest tak ważny? DNS - System Nazw Domenowych to globalnie rozmieszczona usługa Internetowa. Zapewnia tłumaczenie nazw domen

Bardziej szczegółowo

REFERAT PRACY DYPLOMOWEJ

REFERAT PRACY DYPLOMOWEJ REFERAT PRACY DYPLOMOWEJ Temat pracy: Projekt i implementacja środowiska do automatyzacji przeprowadzania testów aplikacji internetowych w oparciu o metodykę Behavior Driven Development. Autor: Stepowany

Bardziej szczegółowo

Spis treści. Dzień 1. I Wprowadzenie (wersja 0906) II Dostęp do danych bieżących specyfikacja OPC Data Access (wersja 0906) Kurs OPC S7

Spis treści. Dzień 1. I Wprowadzenie (wersja 0906) II Dostęp do danych bieżących specyfikacja OPC Data Access (wersja 0906) Kurs OPC S7 I Wprowadzenie (wersja 0906) Kurs OPC S7 Spis treści Dzień 1 I-3 O czym będziemy mówić? I-4 Typowe sytuacje I-5 Klasyczne podejście do komunikacji z urządzeniami automatyki I-6 Cechy podejścia dedykowanego

Bardziej szczegółowo

Cleeng Case Study. Klient Cleeng. Branża. Okres realizacji. Zakres usługi: Consulting. Projekt i wdrożenie Chmury AWS. Zarządzanie chmurą

Cleeng Case Study. Klient Cleeng. Branża. Okres realizacji. Zakres usługi: Consulting. Projekt i wdrożenie Chmury AWS. Zarządzanie chmurą Klient Cleeng Branża E-commerce, Video, Internet Okres realizacji 2014 - nadal Zakres usługi: Projekt i wdrożenie infrastruktury chmurowej AWS, consulting, zarządzanie chmurą Projekt i wdrożenie Chmury

Bardziej szczegółowo

Praca klienta biura rachunkowego na wspólnej bazie

Praca klienta biura rachunkowego na wspólnej bazie Praca klienta biura rachunkowego na wspólnej bazie (wersja 1.0) Soneta Sp z o.o. ul. Wadowicka 8a, wejście B 31-415 Kraków tel./fax +48 (12) 261 36 41 http://www.enova.pl e-mail: handel@enova.pl 1 Spis

Bardziej szczegółowo

Warstwa integracji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe.

Warstwa integracji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. Warstwa integracji wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. 1. Ukrycie logiki dostępu do danych w osobnej warstwie 2. Oddzielenie mechanizmów trwałości od modelu obiektowego Pięciowarstwowy

Bardziej szczegółowo

IBM POWER8 dla SAP HANA

IBM POWER8 dla SAP HANA IBM POWER8 dla SAP HANA SUCCESS STORY Efektywność Innowacyjność Bezpieczeństwo Success Story Pierwsze wdrożenie w Polsce Dzięki współpracy firm itelligence, COMPAREX oraz IBM została zaprojektowana i zrealizowana

Bardziej szczegółowo

Koszty budowy infrastruktury wewnętrznej: hardware, administracja, zespół utrzymaniowy

Koszty budowy infrastruktury wewnętrznej: hardware, administracja, zespół utrzymaniowy 2012 Koszty budowy infrastruktury wewnętrznej: hardware, administracja, zespół utrzymaniowy Andrzej Bobyk Wdrożenie systemu B2B Lublin, 25 października 2012 Kwestie do rozważenia Analiza potrzeb firmy

Bardziej szczegółowo

Nowoczesne narzędzia HR. Waldemar Lipiński DMZ-CHEMAK sp. z o.o.

Nowoczesne narzędzia HR. Waldemar Lipiński DMZ-CHEMAK sp. z o.o. Nowoczesne narzędzia HR Waldemar Lipiński DMZ-CHEMAK sp. z o.o. W CHMURY CZY Z CHMUR Z ZIEMI NA ZIEMIĘ OPROGRAMOWANIE ROZWIĄZANIA ON-LINE OUTSOURCING PLUS CONSULTING 4 wymiary HR to inicjatywa firm: DMZ-Chemak

Bardziej szczegółowo

OFFICE 365 + ADFS - POŁĄCZENIE KORZYŚCI ROZWIĄZAŃ CHMUROWYCH I CENTRALNEGO ZARZĄDZANIA

OFFICE 365 + ADFS - POŁĄCZENIE KORZYŚCI ROZWIĄZAŃ CHMUROWYCH I CENTRALNEGO ZARZĄDZANIA Marta Grum, Administrator Systemów Microsoft w Grupie Unity OFFICE 365 + ADFS - POŁĄCZENIE KORZYŚCI ROZWIĄZAŃ CHMUROWYCH I CENTRALNEGO ZARZĄDZANIA Usługa Office365 jest niezbędnym pakietem narzędzi wykorzystywanych

Bardziej szczegółowo

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa 1 Java Wprowadzenie 2 Czym jest Java? Język programowania prosty zorientowany obiektowo rozproszony interpretowany wydajny Platforma bezpieczny wielowątkowy przenaszalny dynamiczny Rozumiana jako środowisko

Bardziej szczegółowo

ZAPYTANIE OFERTOWE. Zamawiający. Przedmiot zapytania ofertowego. Wrocław, dnia 23.03.2015 r.

ZAPYTANIE OFERTOWE. Zamawiający. Przedmiot zapytania ofertowego. Wrocław, dnia 23.03.2015 r. ZAPYTANIE OFERTOWE Wrocław, dnia 23.03.2015 r. W związku z realizacją przez Nova Telecom spółka z ograniczoną odpowiedzialnością, projektu pn.: Wdrożenie zintegrowanego systemu klasy B2B, umożliwiającego

Bardziej szczegółowo

7. zainstalowane oprogramowanie. 8. 9. 10. zarządzane stacje robocze

7. zainstalowane oprogramowanie. 8. 9. 10. zarządzane stacje robocze Specyfikacja oprogramowania do Opis zarządzania przedmiotu i monitorowania zamówienia środowiska Załącznik nr informatycznego 1 do specyfikacji Lp. 1. a) 1. Oprogramowanie oprogramowania i do systemów

Bardziej szczegółowo

Typy przetwarzania. Przetwarzanie zcentralizowane. Przetwarzanie rozproszone

Typy przetwarzania. Przetwarzanie zcentralizowane. Przetwarzanie rozproszone Typy przetwarzania Przetwarzanie zcentralizowane Systemy typu mainfame Przetwarzanie rozproszone Architektura klient serwer Architektura jednowarstwowa Architektura dwuwarstwowa Architektura trójwarstwowa

Bardziej szczegółowo

WYDAJNOŚĆ I SKALOWALNOŚĆ

WYDAJNOŚĆ I SKALOWALNOŚĆ WYDAJNOŚĆ I SKALOWALNOŚĆ Skalowalność systemu Microsoft Dynamics CRM 4.0 2008 SPIS TREŚCI STRESZCZENIE DLA KIEROWNICTWA... 1 PODSUMOWANIE WYNIKÓW... 1 OMÓWIENIE... 2 METODYKA TESTOWANIA... 2 TRANSAKCJE

Bardziej szczegółowo

Gemini Cloud Project Case Study

Gemini Cloud Project Case Study Gemini Cloud Project Case Study business model and integration/implementation aspects Maciej Morawski - Gemini Cloud Polska Gemini Cloud Usługi IT od 1995 10+ lat doświadczenia w projektach międzynarodowych

Bardziej szczegółowo

Chmura nad Smart City. dr hab. Prof. US Aleksandra Monarcha - Matlak

Chmura nad Smart City. dr hab. Prof. US Aleksandra Monarcha - Matlak Chmura nad Smart City dr hab. Prof. US Aleksandra Monarcha - Matlak Miasta generują ogromne zbiory danych cyfrowych. Ten trend jest napędzany przez zbiór powiązanych ze sobą wydarzeń. Po pierwsze, w czasie

Bardziej szczegółowo

Bezpieczeństwo dla wszystkich środowisk wirtualnych

Bezpieczeństwo dla wszystkich środowisk wirtualnych Bezpieczeństwo dla wszystkich środowisk wirtualnych SECURITY FOR VIRTUAL AND CLOUD ENVIRONMENTS Ochrona czy wydajność? Liczba maszyn wirtualnych wyprzedziła fizyczne już 2009 roku. Dzisiaj ponad połowa

Bardziej szczegółowo

Forum Client - Spring in Swing

Forum Client - Spring in Swing Forum Client - Spring in Swing Paweł Charkowski. 0. Cel projektu Celem projektu jest próba integracji Spring Framework z różnymi technologiami realizacji interfejsu użytkownika, oraz jej ocena. Niniejszy

Bardziej szczegółowo

Założenia projektowe dla zapytania ofertowego EAK_ZA_01/2015

Założenia projektowe dla zapytania ofertowego EAK_ZA_01/2015 Warszawa, 23.01.2015r. NIP: 521-32-79-750 Założenia projektowe dla zapytania ofertowego EAK_ZA_01/2015 I. Wstęp W związku z realizacją projektu Wdrożenie i świadczenie usługi w modelu SaaS eakceptacje,

Bardziej szczegółowo

Rozwiązania biznesowe na żądanie. IBM Workplace Services Express

Rozwiązania biznesowe na żądanie. IBM Workplace Services Express Rozwiązania biznesowe na żądanie IBM Workplace Services Express Elastyczny dostęp do dokumentów i aplikacji biznesowych Oprogramowanie IBM Workplace Services Express dostarcza zintegrowane narzędzia umożliwiające

Bardziej szczegółowo

AppSense - wirtualizacja użytkownika

AppSense - wirtualizacja użytkownika AppSense - wirtualizacja użytkownika Zaawansowana personalizacja, zarządzanie polisami: Personalizacja ustawień użytkownika, takich jak preferencje druku czy zasobów sieciowych, personalizacja ustawień

Bardziej szczegółowo

Aplikacje webowe wspomagające działalność przedsiębiorstwa na przykładzie przychodni stomatologicznej

Aplikacje webowe wspomagające działalność przedsiębiorstwa na przykładzie przychodni stomatologicznej Aplikacje webowe wspomagające działalność przedsiębiorstwa na przykładzie przychodni stomatologicznej Małgorzata Barańska Wydział Informatyki i Zarządzania, Politechnika Wrocławska Beata Laszkiewicz Wydział

Bardziej szczegółowo

Hosting aplikacji on-line

Hosting aplikacji on-line Klient Sp. z o.o. Branża gospodarka i biznes, IT Okres realizacji Od września 2010 do chwili obecnej Rodzaj usługi doradztwo, hosting, hosting danych osobowych, zarządzanie serwerami Doradztwo Hosting

Bardziej szczegółowo

Cechy e-usługi i e-firmy. Elastyczność i niezawodność. Jak się przygotować na zmiany?

Cechy e-usługi i e-firmy. Elastyczność i niezawodność. Jak się przygotować na zmiany? 2012 Cechy e-usługi i e-firmy. Elastyczność i niezawodność. Jak się przygotować na zmiany? Borys Glass-Brudziński Marek Kosno Wizja rozwoju e-usługi Gdańsk, 07 listopada 2012 E-usługa i E-firma E-usługi

Bardziej szczegółowo

Usługi analityczne budowa kostki analitycznej Część pierwsza.

Usługi analityczne budowa kostki analitycznej Część pierwsza. Usługi analityczne budowa kostki analitycznej Część pierwsza. Wprowadzenie W wielu dziedzinach działalności człowieka analiza zebranych danych jest jednym z najważniejszych mechanizmów podejmowania decyzji.

Bardziej szczegółowo

Zdalne monitorowanie i zarządzanie urządzeniami sieciowymi

Zdalne monitorowanie i zarządzanie urządzeniami sieciowymi Uniwersytet Mikołaja Kopernika w Toruniu Wydział Matematyki i Informatyki Wydział Fizyki, Astronomii i Infomatyki Stosowanej Piotr Benetkiewicz Nr albumu: 168455 Praca magisterska na kierunku Informatyka

Bardziej szczegółowo

Usprawnienie procesu zarządzania konfiguracją. Marcin Piebiak Solution Architect Linux Polska Sp. z o.o.

Usprawnienie procesu zarządzania konfiguracją. Marcin Piebiak Solution Architect Linux Polska Sp. z o.o. Usprawnienie procesu zarządzania konfiguracją Marcin Piebiak Solution Architect Linux Polska Sp. z o.o. 1 Typowy model w zarządzaniu IT akceptacja problem problem aktualny stan infrastruktury propozycja

Bardziej szczegółowo

Warszawa, 6 lutego 2014. www.hypermixer.pl. Case Study: Chmura prywatna HyperOne dla Platige Image dzięki Microsoft Hyper-V Server. Wyzwanie biznesowe

Warszawa, 6 lutego 2014. www.hypermixer.pl. Case Study: Chmura prywatna HyperOne dla Platige Image dzięki Microsoft Hyper-V Server. Wyzwanie biznesowe Case Study: Chmura prywatna HyperOne dla Platige Image dzięki Microsoft Hyper-V Server Warszawa, 6 lutego 2014 www.hypermixer.pl 01 1 2 3 4 Wyzwanie biznesowe Wdrożenie Korzyści dla Klienta Wnioski o megatrendach

Bardziej szczegółowo

Klastrowe architektury serwera aplikacji Oracle Application Server 10g

Klastrowe architektury serwera aplikacji Oracle Application Server 10g XV Seminarium PLOUG Warszawa Maj 2007 Klastrowe architektury serwera aplikacji Oracle Application Server 10g Mariusz Masewicz Politechnika Poznańska Mariusz.Masewicz@cs.put.poznan.pl Abstrakt. Współczesny

Bardziej szczegółowo

B2BCloud simple way to Scale Sale

B2BCloud simple way to Scale Sale B2BCloud simple way to Scale Sale For Suppliers and e-commerce. Usługi platformy B2B - B2BCloud pozwalają Klientom skalować sprzedaż poprzez uruchomienie nowego kanału dystrybucji w mgnieniu oka - nie

Bardziej szczegółowo

Symantec Backup Exec System Recovery 7.0 Server Edition. Odtwarzanie systemu Windows w ciągu najwyżej kilkudziesięciu minut nie godzin czy dni

Symantec Backup Exec System Recovery 7.0 Server Edition. Odtwarzanie systemu Windows w ciągu najwyżej kilkudziesięciu minut nie godzin czy dni GŁÓWNE ZALETY Odtwarzanie systemu Windows w ciągu najwyżej kilkudziesięciu minut nie godzin czy dni Firma Symantec wielokrotnie publicznie udowadniała, że dzięki oprogramowaniu Backup Exec System Recovery

Bardziej szczegółowo

SYSTEM WSMS ZARZĄDZANIE STANDARDEM STACJI ROBOCZYCH. info@prointegra.com.pl tel: +48 (032) 730 00 42

SYSTEM WSMS ZARZĄDZANIE STANDARDEM STACJI ROBOCZYCH. info@prointegra.com.pl tel: +48 (032) 730 00 42 SYSTEM WSMS ZARZĄDZANIE STANDARDEM STACJI ROBOCZYCH info@prointegra.com.pl tel: +48 (032) 730 00 42 1. WPROWADZENIE... 3 2. KORZYŚCI BIZNESOWE... 4 3. OPIS FUNKCJONALNY WSMS... 4 WSMS AUDIT... 6 WSMS SM...

Bardziej szczegółowo