LABORATORIUM ARCHITEKTURY SYSTEMÓW KOMPUTEROWYCH WYDZIAŁ ELEKTYCZNY POLITECHNIKA POZNAŃSKA System informacji giełdowej na urządzenia mobilne Inżynierska praca dyplomowa Projekt zespołowy Łukasz STACHOWIAK Tomasz SOBKOWIAK Promotor: dr inż. Krzysztof BUCHOLC Poznań 2009 System informacji giełdowej na urządzenia mobilne Spis treści WSTĘP ........................................................................................................................................... 5 1. SYSTEM MOBILE STOCK MONITOR ....................................................................................... 5 2. ARCHITEKTURA SYSTEMU MOBILE STOCK MONITOR ........................................................... 6 2.1. Ogólny schemat............................................................................................................. 6 2.2. Komunikacja .................................................................................................................. 7 2.2.1. Protokół SOAP ....................................................................................................... 7 2.2.2. Web Services Description Language ..................................................................... 8 2.2.3. Short Message Service .......................................................................................... 9 3. BUDOWA SERWERA ............................................................................................................ 11 4. APLIKACJA DLA PLATFORMY JAVA MICRO EDITION............................................................ 12 4.1. Wprowadzenie ............................................................................................................ 12 4.2. Wprowadzanie do platformy Java Micro Edition ........................................................ 12 4.3. Konfiguracje ................................................................................................................ 13 4.4. Profile .......................................................................................................................... 14 4.5. Konfiguracja Connected Limited Device Configuration .............................................. 15 4.6. Profil Mobile Information Device Profile .................................................................... 16 4.7. Szkielet budowy oraz cykl życia MIDletu .................................................................... 18 4.8. Zapis danych w systemie Record Management System ............................................. 20 4.9. Biblioteki dodatkowe .................................................................................................. 21 4.9.1. J2ME Web Services ............................................................................................. 21 4.9.2. OpenBaseMovil-db.............................................................................................. 22 4.9.3. Lightweight UI Toolkit ......................................................................................... 23 4.9.4. kXML .................................................................................................................... 24 4.10. 5. Opis implementacji aplikacji ................................................................................... 24 4.10.1. Inicjalizacja aplikacji ............................................................................................ 24 4.10.2. Baza danych......................................................................................................... 26 4.10.3. Menu główne, nawigacja oraz struktura klas okien ............................................ 29 4.10.4. Komunikacja z serwerem .................................................................................... 31 4.10.5. Uaktualnianie notowań ....................................................................................... 32 SERWIS WWW ..................................................................................................................... 34 5.1. Funkcjonalność serwisu .............................................................................................. 34 5.2. Platforma Java Enterprise Edition ............................................................................... 34 5.3. Java Persistence API .................................................................................................... 34 3 System informacji giełdowej na urządzenia mobilne 5.4. JavaServer Faces ......................................................................................................... 35 5.5. Implementacja ............................................................................................................ 35 5.5.1. Nawigacja między stronami ................................................................................ 35 5.5.2. Uwierzytelnianie użytkownika ............................................................................ 36 5.5.3. Wybór obserwowanych spółek ........................................................................... 37 ZAKOŃCZENIE.............................................................................................................................. 40 BIBLIOGRAFIA .............................................................................................................................. 41 ZAŁĄCZNIKI .................................................................................................................................. 41 4 System informacji giełdowej na urządzenia mobilne WSTĘP 1. SYSTEM MOBILE STOCK MONITOR 5 System informacji giełdowej na urządzenia mobilne 2. ARCHITEKTURA SYSTEMU MOBILE STOCK MONITOR 2.1. Ogólny schemat System Mobile Stock Monitor został zbudowany w architekturze rozproszonej typu klient-serwer. Ogólny schemat systemu przedstawiono na rysunku 2.1. Rysunek 2.1. Schemat architektury systemu Mobile Stock Monitor. Głównym elementem systemu jest Serwer MSM którego zadaniem jest udostępnianie danych klientom mobilnym. Dane udostępniane przez serwer są wcześniej pobierane z zewnętrznego źródła i zapisywane w bazie danych MSM. Baza danych jest wspólna dla wszystkich elementów systemu, jednak nie każdy element ma do niej dostęp bezpośredni. Urządzenia mobilne pobierają i zapisują dane w bazie danych korzystając z serwera MSM, natomiast Serwis WWW ma do niej bezpośredni dostęp. Komunikacja między aplikacjami klienckimi oraz serwerem MSM odbywa się poprzez sieć Internet. Użytym protokołem warstwy zastosowania jest SOAP. Dodatkowo dla urządzeń wyposażonych w system Symbian możliwe jest zdefiniowanie przez użytkownika łączności za pomocą wiadomości SMS. Wiadomość taka jest przesyłana w specjalnym formacie który zostaje rozpoznany przez aplikację i przetworzony w celu pobrania informacji. 6 System informacji giełdowej na urządzenia mobilne Serwer MSM udostępnia także opis wszystkich metod które mogą wykonać na nim operacje klienckie. Operacjami takimi są m.in. zmiana spółek w portfelu, pobranie danych historycznych, pobranie wykresu. 2.2. Komunikacja Komunikacja między aplikacjami klienckimi oraz serwerem MSM odbywa się poprzez sieć Internet. Użytym protokołem warstwy zastosowania jest SOAP. Dodatkowo dla urządzeń wyposażonych w system Symbian możliwe jest zdefiniowanie przez użytkownika łączności za pomocą wiadomości SMS. Wiadomość taka jest przesyłana w specjalnym formacie który zostaje rozpoznany przez aplikację i przetworzony w celu pobrania informacji. 2.2.1. Protokół SOAP Simple Object Access Protocol jest niezależnym od platformy protokołem tekstowym opartym o XML. Został on ustandaryzowany przez konsorcjum W3C i jest najpopularniejszym protokołem wykorzystywanym do komunikacji z usługami sieciowymi (ang. web service). Zadaniem jego jest umożliwienie wywołania metod zdalnych w systemach o architekturze rozproszonej. Struktura XML umożliwia łatwe rozszerzenie możliwości protokołu czy niezależność od platformy. Komunikacja pomiędzy klientem a serwerem odbywa się na zasadzie żądanie – odpowiedz którą przedstawia rysunek 2.2. Po wysłaniu żądania, serwer je przetwarza, wykonuje odpowiednie operacje a następnie wysyła do klienta odpowiedz. Nie jest przechowywany żaden stan sesji, wszystkie niezbędne informacje przechowywane są w komunikatach. Wysyłany komunikat nazywany jest kopertą. Rysunek 2.2. Diagram sekwencji przedstawiający komunikację za pomocą protokołu SOAP. 7 System informacji giełdowej na urządzenia mobilne Koperta SOAP składa się z 4 głównych elementów: Envelope – jest to główny węzeł dokumentu. Zawarta w nim jest przestrzeń nazw SOAP Header – jest to element opcjonalny. Zawiera informacje pomocnicze Body – zawiera główną część dokumentu, zawierająca dane przesyłane między uczestnikami Fault – występuje tylko w przypadku błędu. Zawarte są w nim informacje o przyczynie jego wystąpienia Przykład koperty żądania ma postać: <?xml version="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Header/> <S:Body> <ns2:login xmlns:ns2="http://temp.webservice.msm/"> <login>test</login> <password>test</password> </ns2:login> </S:Body> </S:Envelope> Odpowiedzią na takie żądanie może być: <?xml version="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:loginResponse xmlns:ns2="http://temp.webservice.msm/"> <return>true</return> </ns2:loginResponse> </S:Body> </S:Envelope> 2.2.2. Web Services Description Language Do opisu metod udostępnianych przez usługi sieciowe opracowano język Web Services Description Language (WSDL). W języku tym tworzone są dokumenty które zawierają szczegółowy opis metod ich parametrów oraz zwracanych wartości aby udostępnić klientom zdalnym opis w jaki sposób powinna przebiegać poprawna komunikacja z usługodawcą. Dodatkowi istnieje możliwość zdefiniowania jakiego protokołu warstwy transportowej należy użyć do komunikacji. Język ten podobnie jak SOAP został oparty o język XML i również został ustandaryzowany przez konsorcjum W3C. 8 System informacji giełdowej na urządzenia mobilne Dokument WSDL składa się z następujących elementów: types – zawiera definicje typów abstrakcyjnych message – definicja abstrakcyjnego komunikatu, który składa się z wielu części, a każda część może być innego typu portType – abstrakcyjny zbiór operacji obsługiwanych przez punkt końcowy binding – specyfikacja konkretnego protokołu i formatu danych dla określonego portType service – zbiór powiązanych punktów końcowych – punkt końcowy definiowany jest jako połączenie wiązania i adresu Gotowe dokumenty WSDL często są wykorzystywane do generowania kodu dla aplikacji klienckiej. 2.2.3. Short Message Service Short Message Service (SMS) to protokół komunikacyjny przeznaczony do przesyłania krótki (do 160 znaków) wiadomości tekstowych pomiędzy dwoma urządzeniami, którymi najczęściej są telefony komórkowe. Początkowo protokół ten przeznaczony był wyłącznie dla sieci GSM, aktualnie dostępny jest także w innych sieciach jak np. 3G. Wiadomość SMS po wysłaniu przesyłana jest do Short Message Service Center które przesyła ją do odbiorcy. Jeśli nie jest on dostępny, wiadomość zostaje zapisana, a próba nadania jest ponawiana co określony czas. Mechanizm dostarczania wiadomości nie zapewnia 100% pewności jej dostarczenia, dlatego możliwe jest nadanie jej z odpowiednim parametrem który aktywuje wysyłanie wiadomości potwierdzających po dostarczeniu. Każdy przesyłany znak w wiadomości kodowany jest domyślnie na 7 bitach i obsługa takiego kodowania jest wymagana przez urządzenia obsługujące SMS. Istnieje jednak możliwość użycia kodowania na większej liczbie bitów, jednak wpływa to znacząco na długość wiadomości możliwej do przesłania. Dla kodowania 8 bitowego jest to 140 znaków natomiast dla 16 bitowego 70 znaków. Wiadomości które przekraczają maksymalną liczbę znaków mogą zostać przesłane w kilku komunikatach a urządzenie 9 System informacji giełdowej na urządzenia mobilne odbierające wiadomość będzie odpowiadać za połączenie ich w jeden. W taki wypadku pole danych jest pomniejszone o wielkość nagłówka wiadomości i może zawierać maksymalnie 153 znaki przy kodowaniu 7 bitowym. Short Message Service jest obecnie bardzo popularną formą wymiany wiadomości między urządzeniami. Funkcjonalność tej usługi jest ciągle powiększana, aktualnie możliwe za jej pomocą jest także głosowanie, opłacanie innych usług, sterowanie urządzeniami [17]. 10 System informacji giełdowej na urządzenia mobilne 3. BUDOWA SERWERA 11 System informacji giełdowej na urządzenia mobilne 4. APLIKACJA DLA PLATFORMY JAVA MICRO EDITION 4.1. Wprowadzenie Zostanie napisany po zakończeniu pisania pracy. 4.2. Wprowadzanie do platformy Java Micro Edition Początkowo język Oak stworzony przez Sun Microsystems na początku lat 90, przeznaczony dla urządzeń mobilnych nie odniósł sukcesu. Pomimo tego, że był on stworzony z myślą o tym by jak najbardziej ograniczyć liczbę błędów możliwych do popełnienia przez programistę (co było udręką programistów C++) nie udało się sprzedać żadnego urządzenia wyposażonego w obsługę tego języka. Po zmianie nazwy na Java i kierunku rozwoju, język ten stał się najpopularniejszym językiem programowania doby Internetu. Sukces zawdzięcza z pewnością obsłudze obiektowego paradygmatu programowania, przenośności, łatwości w programowaniu rozproszonym, bezpieczeństwu i niezawodności. Firma Sun po kilku latach ponownie rozpoczęła prace nad obsługa urządzeń przenośnych co poskutkowało wydaniem PersonalJava (znanym także pod nazwą pJava). Ostateczne uformowanie wszystkich edycji Javy nastąpiło w 1999 roku kiedy to Sun ogłosił istnienie trzech platform Java: Java Enterprise Edition (Java EE) – dla aplikacji tzw. klasy enteprise Java Standard Edition (Java SE) – dla aplikacji desktopowych Java Micro Edition (Java ME) – dla urządzeń o ograniczonych zasobach Platforma Java Micro Edition (Java ME) jest zbiorem technologii oraz specyfikacji do tworzenia aplikacji dla urządzeń o ograniczonych zasobach takich jak telefony komórkowe, urządzenia wbudowane, palmtopy. Platforma ta z czasem stała się podstawową w tworzeniu gier oraz programów użytkowych na tych urządzeniach. Językiem programowania na tej platformie jest oczywiście obiektowy język Java. Ponieważ zbiór urządzeń przenośnych jest bardzo duży i co za tym idzie możliwości każdego z nich są odmienne ze względu na liczbę posiadanej pamięci, moc procesora, dostępne inne peryferia (np. ekran, głośnik) twórcy postanowili utworzyć zbiór specyfikacji tworzących zbiór platform. Taka specyfikacja nazywana jest konfiguracją i definiuje ona platformę 12 dla określonego zbioru urządzeń System informacji giełdowej na urządzenia mobilne elektronicznych. Taka konfiguracja jest rozszerzana przez profile które dodają określone możliwości w celu wyspecjalizowania platformy dla konkretnej grupy urządzeń. Ponad to taka platforma może zostać wzbogacona o pakiety opcjonalne nadające specyficzne możliwości lub obsługę konkretnych technologii. Na rysunku 5.1 przedstawiono schemat architektury platformy Java ME. Rysunek 4.1. Architektura platform Java wraz z wyszczególnioną platformą Micro Edition[2]. Taka architektura może wydawać się skomplikowana jednak firma Sun dość intensywnie prowadziła rozmowy z producentami urządzeń aby objęła ona jak największą ich liczbę. Skutkiem tego stało się praktycznie wprowadzenie nowego standardu – większość nowych urządzeń przenośnych posiada w sobie obsługę platformy Java ME. 4.3. Konfiguracje Konfiguracja jest podstawą platformy, specyfikuje ona minimalne cechy grupy urządzeń które obejmuje i tworzy spójne środowisko dla programistów. Środowisko oprogramowania rodziny urządzeń, jest charakteryzowane przez następujące cechy: 13 System informacji giełdowej na urządzenia mobilne typ i ilość dostępnej pamięci typ i prędkość procesora typ połączenia sieciowego jakie udostępnia urządzenie Java ME została podzielona na dwie główne konfiguracje: Connected limited device configuration (CLDC) – przeznaczona jest dla urządzeń takich jak telefony komórkowe, posiadających bardzo ograniczone zasoby pamięciowe oraz moc procesora. Konfiguracja ta zostanie szerzej opisana w jednym z następnych podrozdziałów. Connected device configuration (CDC) – przeznaczona jest dla bardziej rozbudowanych urządzeń na których możliwe jest uruchomienie bardziej rozbudowanych programów. Przyjęto wymaganie co najmniej 2 MB pamięci podręcznej aby możliwa była obsługa tej konfiguracji przez urządzenie. CDC najczęściej przeznaczone jest dla urządzeń typu PDA. Każda konfiguracja składa się z maszyny wirtualnej oraz zestawu podstawowych klas. Ze względu na ograniczone zasoby urządzeń maszyna wirtualna Java ME nie może zapewnić pełnej funkcjonalności którą posiada maszyna wirtualna Java SE. Dlatego jej specyfikacja składa się z elementów języka Java oraz maszyny wirtualnej Java SE z której nie musi posiadać. Np. w pierwszej wersji CLCD nie wymagana była obsługa liczb zmienno przecinkowych i nie została ona zaimplementowana. 4.4. Profile Profile rozszerzają konfigurację tak aby dopasować całą platformę do wymagań konkretnej grupy urządzeń (jak np. telefony komórkowe). Wprowadzają nowe pakiety klas dodające obsługę np. urządzeń wejścia wyjścia, ekranu, mediów, pamięci trwałej itd. Profili zostało zdefiniowanych znacznie więcej niż konfiguracji, co więcej wszystkie z nich zostały opracowane w ramach inicjatywy Java Community Process (JCP). Program ten ma na celu zebranie grupy specjalistów w danej dziedzinie i opracowanie spójnej specyfikacji dla danego problemu[4]. Dzięki takiemu podejściu wszystkie stworzone profile, w których opracowywaniu brały udział firmy produkujące docelowe urządzenia, są powszechnie zaakceptowane i mogą być obsługiwane przez znacznie większą liczbę urządzeń. Do najbardziej popularnych profili należą: 14 System informacji giełdowej na urządzenia mobilne Mobile Information Device Profile PDA Foundation Personal i Personal Basis 4.5. Konfiguracja Connected Limited Device Configuration Przed przystąpieniem do pracy nad aplikacją koniecznie jest zapoznanie się ze środowiskiem w jakim ta aplikacja będzie pracować. Dlatego w tym i w kolejnych podrozdziałach zostaną omówione szczegóły konfiguracji CLDC, profilu MIDP a następnie kilku podstawowych bibliotek z których autor korzystał w trakcie implementacji. Aplikacja Mobile Stock Monitor oparta jest o konfigurację Connected Limited Device Configuration w wersji 1.1 która jest najczęściej spotykaną konfiguracją na urządzeniach przenośnych. Ta konfiguracja posiada następujące wymagania sprzętowe: 160 kb pamięci nieulotnej dla maszyny wirtualnej oraz bibliotek podstawowych 32 kb pamięci podręcznej do uruchomienia aplikacji 16 lub 32 bitowy procesor Obejmuje następujące elementy: język Java maszynę wirtualną (KVM) biblioteki podstawowe (pakiety klas java.lang.* oraz java.util.*) obsługę wejścia/wyjścia (pakiet klas java.io.*) bezpieczeństwo obsługę sieci internacjonalizacja Ze względu na niezwykle małe rozmiary maszyna wirtualna Java ME nazwana została kilobajtową maszyną wirtualną (ang. kilobyte virtual machine) jednak przyjętą nazwą stosowaną dla niej jest skrót KVM (z ang. kilobyte virtual machine). Biblioteki wchodzące w skład specyfikacji to w większości biblioteki pochodzące ze standardowej wersji Javy w wersji 1.3. Jednak ta lista została w znaczący sposób 15 System informacji giełdowej na urządzenia mobilne ograniczona, nie tylko ze względu na oszczędność zasobów ale także bezpieczeństwo oraz „oczyszczenie” języka z niezalecanych w użytku już klas oraz metod (oznaczone jako przedawnione – ang. deprecated). W tej konfiguracji brakuje następujących elementów: refleksja – brak pakietu java.lang.reflect oraz metod w pakiecie java.lang.Class związanych z refleksją brak metod finalizujących finalize() brak interfejsu Java Native Interface umożliwiającego uruchamianie kodu napisanego w innym języku programowania niż Java ograniczona została liczba typów wyjątków oraz błędów zmniejszono liczbę metod w obsłudze wątków oraz uniemożliwiono tworzenie ich grup a także wątków demonów brak możliwości definiowania własnych klas ładujących CLDC wprowadza dodatkowo jedną bibliotekę nazwaną Generic Connection Framework której przeznaczeniem jest obsługa połączeń sieciowych. Ta biblioteka jednak nie posiada implementacji obsługi żadnego protokołu sieciowego. Stanowi jedynie interfejs na bazie którego należy tworzyć połączenia sieciowe. Konkretną implementacją poszczególnych protokołów sieciowych zajmuje się rozszerzający konfigurację profil. Biblioteka ta została zdefiniowana w pakiecie javax.microedition.io [3]. Wybór konfiguracji CLDC w wersji 1.1 dla tworzonej aplikacji ogranicza w niewielkim zakresie liczbę urządzeń dla których może być ona przeznaczona. Jednak wybór ten był jednak konieczny ze względu na brak obsługi liczb zmienno przecinkowych w wersji 1.0 tej konfiguracji. Bez tego typu operacji zarówno nie byłoby możliwe wierne oddanie notowań giełdowych oraz aplikacja stała by się uboższa ze względu na wymaganie ich obsługi przez biblioteki zewnętrze które także zostały użyte podczas implementacji. 4.6. Profil Mobile Information Device Profile Profil MIDP w wersji 2.0 jest najpopularniejszym profilem używanym w urządzeniach przenośnych. Jego implementacja znajduje się na praktycznie każdym modelu wydawanym modelu telefonu komórkowego. Profil ten w wystarczający sposób 16 System informacji giełdowej na urządzenia mobilne rozszerza konfigurację CLDC zapewniając bardzo rozwinięte środowisko do tworzenia aplikacji użytkowych oraz gier. Głównymi elementami wprowadzanymi przez MIDP są: obsługa protokołów sieciowych TCP, UDP, HTTP a także połączeń szyfrowanych SSL tworzenie interfejsu użytkownika obsługa klawiatury obsługa zdarzeń wprowadzanie wielu kontrolek ułatwiających tworzenie gier odtwarzanie dźwięków obsługa dodatkowych urządzeń jak np. wbudowany aparat fotograficzny utrwalanie danych w pamięci stałej obsługa ekranów dotykowych Zwiększona liczba bibliotek odbija się na wymaganiach sprzętowych narzucanych urządzeniom. Wymagane jest dodatkowo: 256 kb pamięci trwałej 8 kb dodatkowej pamięci trwałej na zapis danych 128 kb pamięci podręcznej Oraz urządzenie powinno dodatkowo posiadać: ekran wielkości 96 na 54 piksele o co najmniej 1 bitowej głębi kolorów urządzenie wejściowe typu klawiatura lub ekran dotykowy połączenie sieciowe możliwość odgrywania dźwięków mechanizm zapisu oraz odczytu danych z pamięci trwałej oraz obsługę innych elementów jak format PNG, kodowanie UTF-8. Ich lista została zawarta w dokumencie [5] Aplikacje MIDP nazywane są MIDletami i są rozprowadzane w plikach typu jar (java archive). Możliwe jest także umieszczanie wielu MIDletów w jednym pliku jar nazywanym zestawem MIDletów (ang. MIDlet Suits). Taki zestaw jest traktowany jako całość i nie można usuwać pojedynczo MIDletów wchodzących w jego skład [5]. 17 System informacji giełdowej na urządzenia mobilne 4.7. Szkielet budowy oraz cykl życia MIDletu Profil MIDP narzuca określony szkielet budowy MIDletu a także definiuje cykl życia aplikacji tego typu. Każdy MIDlet musi posiadać jedną klasę dziedziczącą po abstrakcyjnej klasie basowej javax.microedition.midlet.MIDlet. Taka klasa staje się główną w aplikacji i to od niej zaczyna się jej działanie. Abstrakcyjna klasa MIDlet zawiera w sobie metody konieczne obsługi przejść między poszczególnymi stanami cyklu życia, dodatkowo wymusza implementację kilku metod. Najprostszy szkielet MIDletu przedstawia się następująco: public class SzkieletMIDletu extends MIDlet { protected void startApp() throws MIDletStateChangeException { } protected void pauseApp() { } protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { } } Dodatkowo wymagane jest przez klasę posiadanie konstruktora bezargumentowego. Jeśli taki nie zostanie zdefiniowany zostanie automatycznie utworzony podczas kompilacji. Metody startApp, pauseApp, destroyApp są ściśle związane z cyklem życia aplikacji. W urządzeniach typu telefon komórkowy konieczna jest obsługa zdarzeń typu odebranie połączenia telefonicznego, aplikacja w takim momencie nie może blokować nadchodzącej rozmowy lecz musi w poprawny sposób zostać wstrzymana, a po zakończeniu rozmowy ponownie przywrócona do poprzedniego stanu. Dlatego wydzielono trzy możliwe stany w jakich może znajdować się aplikacja: zatrzymany, aktywny, zniszczony. Diagram znajdujący się na rysunku 4.2 przedstawia przejścia pomiędzy poszczególnymi stanami. 18 System informacji giełdowej na urządzenia mobilne Rysunek 4.2. Diagram przejść między poszczególnymi stanami aplikacji typu MIDlet. Jak przedstawiono metody których implementacja jest wymuszana są wywoływane przed przejściem w kolejny stan zgodnie z diagramem. Programista może dzięki temu wykonać niezbędne czynności aby aplikacja bezpiecznie przygotowała się do zmiany stanu. Bardziej szczegółowego omówienia wymaga metoda destroyApp odpowiedzialna za zwalnianie zasobów podczas zamykania aplikacji. Posiada on jeden parametr uncoditional typu logicznego który decyduje czy operacja zamykania aplikacji może zostać przerwana i pozostać w swoim aktualnym stanie czy zamknięcie aplikacji jest nieuniknione. W pierwszym przypadku wartość tego parametru to false, może to zostać wykorzystane np. by dać szanse użytkownikowi na zapisanie wyników pracy, jeśli takiej możliwości nie ma i MIDlet musi zostać natychmiast zamknięty wartość parametru to true. Należy także zwrócić uwagę na wyjątek typu MIDletStateChangeException który może zostać zgłoszony przez metody startApp oraz destryApp. Jest on generowany w przypadku gdy zmiana stanu nie jest z jakiś powodów możliwa [1]. 19 System informacji giełdowej na urządzenia mobilne 4.8. Zapis danych w systemie Record Management System Profil MIDP wprowadza uniwersalny system zapisu i odczytu danych który zapewnia przenośność między różnego typu urządzeniami. System ten jest oparty o prostą rekordową bazę danych i nazwany został Record Management System (RMS). W RMS dane utrwalane są w zbiorach rekordów. Taki zbiór jest przechowywany w pamięci trwałej nawet po wyłączeniu aplikacja i jest dostępny przy każdym jej uruchomieniu. Za integralność danych zawartych w rekordach odpowiada system operacyjny danego urządzenia. Musi on zapewnić trwałość tych danych nawet podczas takich sytuacji jak restart systemu czy jego wyłączenie spowodowane rozładowaniem baterii. Zbiory rekordów są tworzone w niezależny od platformy sposób. Każdy MIDlet może ich utworzyć dowolną liczbę, jedynym warunkiem jest nadawanie każdemu unikalnej nazwy w obrębie zestawu MIDletów. Nazwa może być dowolnym ciągiem znaków Unicode (wielkość liter ma znaczenie) o maksymalnej długości 32 znaki. Możliwe jest także nadawanie uprawnień zbiorom tak aby mogły być współdzielone przez większa liczbę MIDletów. Ponad to zbiory są oznaczane znacznikami czasu który reprezentuje datę ostatniej modyfikacji na nim wykonanej. Przy każdej operacji zwiększana jest także jego wersja która jest reprezentowana przez liczbę całkowitą. Takie dodatkowe oznaczenia ułatwiają w niektórych przypadkach synchronizację danych. Kiedy MIDlet jest usuwany z pamięci telefonu wszystkie jego zbiory są także usuwane. Każdy przechowywany rekord jest tablicą bajtów. Programista pragnący zapisać jakąś daną musi najpierw zamienić ją na tablicę bajtów i dopiero wtedy będzie możliwego jej zapisanie w systemie RMS. Rekordy w obrębie zbioru są automatycznie indeksowane. Pierwszy rekord zapisywany posiada identyfikator 1 i dla każdego kolejnego wprowadzanego rekordu ta wartość jest inkrementowana. Dla programisty korzystającego z RMS najważniejszą klasą jest RecordStore która odpowiada za zarządzanie wszystkimi danymi zapisywanymi w pamięci trwałej. Klasa ta posiada wiele użytecznych metod z których do najważniejszych należą: openRecordStore – tworzy nowy zbiór rekordów addRecord – dodaje rekord do zbioru setRecord – modyfikuje dany rekord 20 System informacji giełdowej na urządzenia mobilne getRecord – pobiera wybrany rekord, metoda zwraca tablicę bajtów enumarateRecords – metoda zwraca obiekt typu RecordEnumeration pomocna przy przeglądaniu rekordów danego zbioru Rekordy przeglądane za pomocą klasy RecordEnumeration można dodatkowo filtrować i sortować. Wystarczy przypisać obiekt implementujący interfejs RecordFilter dla filtru oraz RecordComparator dla sortowania, daje to możliwość przeglądania tylko wybranych rekordów w odpowiednim porządku [5]. Pomimo sporych możliwości Record Management System jest dla programisty dość niewygodny w użyciu. Główną tego przyczyną jest zapis danych w postaci tablicy bajtów, rodzi to dodatkowe problemy w konwersjach takiej tablicy na konkretne typy danych. RMS jest jednak elementem profilu MIDP bez którego nie można stworzyć funkcjonalnej aplikacji. W aplikacji która jest przedmiotem tego rozdziału RMS został użyty do zapisu danych konfiguracyjnych oraz informacji o użytkowniku. Do przechowywania większych zbiorów danych wykorzystana została biblioteka OpenBaseMovil-db, która została utworzona właśnie na bazie RMS. Będzie ona dokładniej omówiona w dalszej części rozdziału. 4.9. Biblioteki dodatkowe Praktycznie wszystkie tworzone w dzisiejszych czasach aplikacje na wszelkie możliwe platformy korzystają z zewnętrznych bibliotek aby zwiększyć bezpieczeństwo oraz przyspieszyć proces ich tworzenia. Biblioteki takie są sprawdzonym i uniwersalnym rozwiązaniem które może zostać zastosowane w bardzo szerokim spektrum. Dlatego także w aplikacji Mobile Stock Monitor postanowiono skorzystać z kilku sprawdzonych rozwiązań aby nie tylko przyspieszyć proces powstawania aplikacji ale także zwiększyć funkcjonalność i zapewnić większą przenośność. Poszczególne dodatkowe biblioteki zostaną omówione w kolejnych podpunktach. 4.9.1. J2ME Web Services Specyfikacja J2ME Web Services została opracowana przez grupę ekspertów w ramach inicjatywy Java Community Process. Jej celem było zdefiniowanie opcjonalnego pakietu bibliotek odpowiedzialnych za przetwarzanie dokumentów XML oraz poprawną komunikację z serwisami sieciowymi komunikującymi się poprzez protokoły oparte o XML a w szczególności SOAP. Implementacja tej specyfikacji jest 21 System informacji giełdowej na urządzenia mobilne przeznaczona zarówno dla konfiguracji CLDC jak i CDC i jej implementacja na urządzeniu jest wymagana do poprawnego działania aplikacji Mobile Stock Monitor [6]. 4.9.2. OpenBaseMovil-db System Record Management System pomimo dobrej idei aby stworzyć uniwersalne rozwiązanie dla zapisu danych na urządzeniach przenośnych zostało w znaczący sposób zepsute przez producentów konkretnych urządzeń. Nie każdy model urządzenia obsługiwał system RMS w ten sam sposób. Np. pojawiały się problemy w ograniczeniami na wielkość zbioru, lub ich liczbę. Tego typu różnice w znaczący sposób utrudniają stworzenie uniwersalnej aplikacji zarządzającej dużym zbiorem danych i niszczą idee niezależnych od platformy rozwiązań javowych. Twórcy biblioteki OpenBaseMovil-db wyszli naprzeciw tym nieścisłością i stworzyli uniwersalną relacyjną bazę danych niezależną od modelu urządzenia i ograniczeń przez nie narzucanych. Biblioteka ta umożliwia tworzenie wielu baz danych, tabel, indeksów czy wierszy w tabeli i jest ograniczona jedynie przez liczbę dostępnej przestrzeni w pamięci trwałej. Nie zaimplementowano obsługi języka zapytań SQL jednak obiektowy dostęp do danych został znacznie bardziej poszerzony w stosunku do systemu RMS. Wprowadzono także podstawowe typy danych jakie mogą być przechowywane w kolumnach: BLOB Boolean Date Image Int Long Short String Zwalnia to programistę z kłopotliwej kontroli typów czy serializacji/deserializacji obiektów podczas operacji na danych. Dla wbudowanych typów zaimplementowany już zostały metody wyszukujące oraz sortujące. Ciekawą możliwością jest wyszukiwanie wierszy w tabeli które posiadają odpowiednie (podane) wartości w większej liczbie kolumn [7]. 22 System informacji giełdowej na urządzenia mobilne Inne możliwości oraz przykłady użycia tej biblioteki zostaną opisane w części rozdziału poświęconej implementacji. 4.9.3. Lightweight UI Toolkit Innym wyzwaniem stawianym przed programistami platformy Java ME jest interfejs użytkownika. Pomimo jednakowego zestawu bibliotek standardowych zawartych w profilu dla wszystkich urządzeń utworzona aplikacja może wyglądać i zachowywać się zupełnie inaczej na różnych urządzeniach. Co więcej dość uboga liczba kontrolek zmusza często programistów do pisania własnych, trudnych do zaimplementowania rozwiązań. Tego typu problemy rozwiązuje biblioteka do tworzenia bogatego interfejsu użytkownika Lightweight UI Toolkit (LWUIT). Jest to darmowe rozwiązanie rozprowadzane na licencji GPL1 zapewniające identyczny wygląd oraz zachowanie aplikacji na każdym urządzeniu przenośnym. LWUIT zostało stworzone na wzór biblioteki Java SE do tworzenia interfejsu użytkownika Swing, ten model zapewnia łatwe przejście dla programistów mający doświadczenie wcześniej wyłącznie z programowaniem aplikacji desktopowych na programowanie aplikacji na urządzenia mobilne. Do głównych cech biblioteki należą: interfejsy klas podobne do Swingowych duży zestaw gotowych komponentów możliwość rozmieszczania komponentów w wielu rodzajach układów graficznych (ang. layouts) łatwa zmiana styli komponentów (tzw. Look and Feel) możliwość tworzenia motywów dla aplikacji obsługa wielu czcionek obsługa ekranów dotykowych łatwe tworzenie animacji oraz efektów przejść między ekranami internacjonalizacja integracja z SVG możliwość wyświetlania animacji 3D 1 Treść licencji dostępna jest pod adresem [9]. 23 System informacji giełdowej na urządzenia mobilne Dodatkowo pomimo bogatego zestawu gotowych komponentów tworzenie własnych jest znacznie prostsze niż w przypadków biblioteki standardowej. Żadna klasa komponentu w bibliotece LWUIT nie jest oznaczona słowem kluczowy final2 co oznacza, że programista może w łatwy sposób dziedziczyć jej zachowanie w własnych podklasach i zmieniać jego wygląd oraz zachowanie dostosowując je do własnych potrzeb. MIDlety tworzone za pomocą tej biblioteki charakteryzują się także wysoką responsywnością, ponieważ komponenty rysowane są na osobnym wątku co nie zatrzymuje aplikacji. Razem z biblioteką rozpowszechniany jest także specjalny edytor zasobów, który umożliwia tworzenie pakietów zasobów dla aplikacji LWUIT. Do takiego pakietu możemy dołączyć czcionki, obrazy, animacje, tłumaczenia tekstów na poszczególne języki a także gotowe motywy których tworzenie jest także jedną z funkcjonalności programu. LWUIT wymaga środowiska CLDC 1.1/MIDP 2.0 oraz 272 kb pamięci trwałej dla zestawu bibliotek [8]. 4.9.4. kXML Niektóre komunikaty odbierane z serwera są w postaci dokumentów XML. Aby je przetworzyć w poprawny sposób wykorzystywana jest biblioteka kXML. Jej niezwykle małe rozmiary (składa się z zaledwie 3 klas) oraz możliwości wystarczające do przetwarzania mało skomplikowanych wiadomości XML w bardzo dobry sposób wpasowują ją do zastosowań w aplikacjach Java ME. Przykłady użycia biblioteki zostaną opisane w podrozdziale dotyczącym implementacji [11]. 4.10. Opis implementacji aplikacji W następnych podrozdziałach autor przedstawi szczegółowy opis implementacji najważniejszych części programu. 4.10.1. Inicjalizacja aplikacji Główną klasa aplikacji jest MSMClient która to jest podklasą klasy MIDlet. Z tego względu jest ona zmuszona implementować metodę startApp od jakiej rozpoczyna się uruchomienie aplikacji. Metoda ta wykonuje podstawowe operacje. W pierwszej kolejności inicjalizowany jest ekran poprzez wywołanie metody Display.init() w której 2 Klasy języka Java oznaczone słowem kluczowym final nie mogą podlegać dziedziczeniu [10]. 24 System informacji giełdowej na urządzenia mobilne jako parametr podawany jest obiekt MIDletu. Następnie wczytuje się główny motyw graficzny. Resources r = Resources.open(THEME_FILE); UIManager.getInstance(). setThemeProps(r.getTheme(r.getThemeResourceNames()[0])); W pierwszej linii następuje wczytanie zasobu znajdującego się w katalogu wskazywanym przez stałą3 THEME_FILE a w kolejnej jego wczytanie oraz zastosowanie jako głównej. W jednym zbiorze może znajdować się więcej niż jeden motyw dlatego metoda getThemeResourceNames zwraca tablicę w której następuje odwołanie do pierwszego elementu. Po tej operacji możliwe jest wyświetlenie okna z informacją dla użytkownika, o wczytywaniu aplikacji, co realizuje następujący kod: Form waitForm = new Form("Wczytywanie"); waitForm.setLayout(new BorderLayout()); Label message = new Label("Proszę czekać"); message.setAlignment(Label.CENTER); waitForm.addComponent(BorderLayout.CENTER, message); waitForm.show(); Każde okno w bibliotece LWUIT jest reprezentowane przez obiekt typu Form. Obiektowi temu przypisujemy główny układ graficzny wg którego będą rozmieszczane komponenty. Następnie tworzona jest kontrolka z wiadomościa, jest ona wyśrodkowywana i ostatecznie dodawana środek okna wg układu BorderLayout. Ostatecznie okno jest wyświetlane. Po tej operacji następują takie działania jak: przygotowanie menu głównego inicjalizacja bazy danych inicjalizacja konfiguracji wyświetlenie menu głównego Przyjęło się tak nazywać zmienne oznaczone jako statyczne oraz finalne jednocześnie, pomimo tego, że w języku Java nie istnieje taki byt jak stała. 3 25 System informacji giełdowej na urządzenia mobilne 4.10.2. Baza danych Biblioteka OpenBaseMovil-db umożliwia utworzenia na bazie systemu zapisu RMS imitacji bazy danych w środowisku Java ME. Baza danych zastosowana w aplikacji składa się z dwóch tabel, które przedstawione są na rysunku 4.3. Rysunek 4.3. Diagram przedstawiający tabele dostępne w bazie danych. W tabeli stockcorps przechowywane są informacje na temat spółek giełdowych, które może obserwować użytkownik. Poszczególne kolumny przechowują następujące informacje: id – całkowitoliczbowy identyfikator spółki shortname – nazwa skrócona spółki (3 znaki) name – pełna nazwa spółki (maksimum 30 znaków) observed – wartość boolowska określająca czy użytkownik obserwuje daną spółkę Drugą tabelą jest stockquotes przechowująca informację na temat notowań spółek: stock_id – identyfikator spółki price – cena akcji change – zmiana w stosunku do poprzedniej wartości (procentowo) total – obrót (w tyś. zł.) date – data kiedy spółka posiadała takie notowania last_result – pole pomocnicze oznaczające czy dane w tym rekordzie są najbardziej aktualne 26 System informacji giełdowej na urządzenia mobilne Pola price oraz OpenBaseMovil-db change przechowywane niestety nie jako liczby całkowite. umożliwia Biblioteka przechowywania liczb zmiennoprzecinkowych dlatego te wartości przed zapisem są mnożone przez 100 i zapisywane jako całkowite. Za tworzenie i zarządzenie bazą danych odpowiada obiekt klasa typu singleton4 [16] MSMDb przechowywana w pakiecie msm.j2meclient.data. Struktura bazy tworzona jest jednokrotnie podczas pierwszego uruchomienia aplikacji na urządzeniu. Za tę operację odpowiada metoda createDB: dbh = Database.connect(DATABASE_NAME); if (dbh.getVersionMajor() == (short) 0) { dbh.drop(); dbh = Database.create(DATABASE_NAME); dbh.setVersionMajor((short) 1); createTables(dbh); } W pierwszej kolejności wykonywane jest łączenie z bazą danych, która w przypadku gdy nie istnieje jest automatycznie tworzona. Aby stwierdzić czy baza wcześniej nie została utworzona wykorzystywana jest informacja o wersji bazy. W przypadku gdy jej wartość jest równa zero, oznacza to, że nie została wcześniej utworzona i wykonywane jest usuwanie informacji, przypisanie wersji równej jeden, a następnie w metodzie createTables tworzenie struktury. Przykładowo utworzenie tabeli stockcorps wygląda następująco: Table stockCorpTable = new Table("stockcorps"); stockCorpTable.addColumn("id", Constants.FT_LONG); stockCorpTable.addColumn("shortname", Constants.FT_STRING, 5); stockCorpTable.addColumn("name", Constants.FT_STRING, 30); stockCorpTable.addColumn("observed", Constants.FT_BOOLEAN); W pierwszej kolejności tworzony jest obiekt typu Table a następnie za pomocą metody addColumn dodawane są kolumny. Informacja potrzebna do stworzenia kolumny to jej nazwa, oraz typ danych jaki będzie przechowywać. Nazwy typów danych jakie mogą być przechowywane zdefiniowane zostały jako stałe w klasie Constants biblioteki OpenBaseMovil-db. Biblioteka ta aby możliwe było wyszukiwanie danych wymusza na programiście zdefiniowanie indeksów na poszczególnych kolumnach. Przykładowo indeks na polu id tworzy się następująco: 4 Klasy skonstruowane na zasadzie wzorca projektowego singleton mogą posiadać tylko jedną instancję. 27 System informacji giełdowej na urządzenia mobilne stockCorpTable.createIndex("id_index", "id"); Dzięki temu możliwe jest teraz wyszukiwanie po wartościach w polu id. Inną przydatną funkcjonalnością związana z indeksami jest możliwość tworzenia ich na kilku polach. Takie rozwiązanie umożliwia wyszukiwanie wartości po wielu kolumnach. Indeks tego typu został utworzony dla tabeli stockquotes: stockQuotesTable.createIndex("ix_idlastresult", new String[]{"stock_id", "last_result"}); Po zakończeniu tworzenia tabeli zostaje ona zapisana w wywołaniu metody na obiekcie bazy danych createTable której parametrem jest tworzona tabela. Podczas pierwszego uruchomienia dodawane do bazy są także informacje o wszystkich spółkach dostępnych. Proces ten ze względu na dużą ich liczbę może trwać do 2-3 minut5. 4.10.3. Przechowywanie konfiguracji Aplikacja przechowuje kilka informacji konfiguracyjnych które wpływają na jej zachowanie podczas działania. Do takich informacji należą: czy należy pobierać notowania spółek okresowo interwał czasowy pomiędzy kolejną aktualizacją data ostatniego pobrania listy nowych spółek Klasą odpowiadającą za przechowywanie tych informacji jest klasa Config. Korzysta ona z systemu zapisu RMS aby przechować odpowiednie wartości w pamięci stałej. Dodatkowo klasa ta zarządza obiektem pobierającym okresowo notowanie spółek. Za dostęp do odpowiednich wartości odpowiadają metody getXXX, setXXX lub dla zmiennych typu logicznego także isXXX. Przykładową metodą odpowiadającą za przypisywanie wartości zmiennej autoCheck która aktywuje lub dezaktywuje funkcję okresowego pobierania notowań spółek jest setAutoCheck() public void setAutoCheck(boolean autoCheck) throws RecordStoreFullException, RecordStoreException { // usuniecie zbioru 5 Wynik otrzymany podczas testów przy użyciu na modelu telefonu Sony Ericsson K750i 28 System informacji giełdowej na urządzenia mobilne RecordStore.deleteRecordStore(RECORD_PREFIX + AUTO_CHECK_OPTION); // utworzenie nowego zbioru RecordStore autoCheckStore = RecordStore.openRecordStore( RECORD_PREFIX + AUTO_CHECK_OPTION, true); // zamiana wartosci logicznej na tablicę byte[] data = {autoCheck == true ? (byte) 1 : (byte) 0}; // dodanie nowego rekordu autoCheckStore.addRecord(data, 0, data.length); // zamknięcie zbioru autoCheckStore.closeRecordStore(); this.autoCheck = autoCheck; // powiadomienie obiektu pobierajacego // notowania o zmianie wartosci autoChecker.setDoCheck(autoCheck); } Każda zmienna odpowiadająca opcji konfiguracji posiada własny zbiór którego nazwa jest stałą przypisaną jako pole klasy. Zbiór taki zawsze posiada tylko jeden rekord. Podczas zmiany wartości cały zbiór jest usuwany i tworzony nowy. Taki algorytm zapewnia największą wydajność do minimum ograniczając operacje na pamięci stałej. 4.10.4. Menu główne, nawigacja oraz struktura klas okien Podczas inicjalizacji aplikacji inicjalizowane jest także menu główne, które w przeciwieństwie do innych okien usuwane z pamięci jest dopiero podczas zamykania programu. Dla tego okna został wybrany układ graficzny GridLayout charakteryzujący się rozmieszczeniem poszczególnych elementów na siatce. Z czego rozmiar siatki jest dobierany w zależności od rozmiarów ekranu urządzenia. Każdy element menu jest obiektem dziedziczącym po abstrakcyjnej klasie MenuItem. Klasa ta narzuca implementację dwóch metod: render() oraz cleanUp(). Zadaniem pierwszej jest wyświetlenie okna danej opcji z menu, natomiast drugiej usunięcie wszystkich niepotrzebnych już danych po zamknięciu okna. W każdej implementacji tej metody występuję także wywołanie metody System.gc() której zadaniem jest wykonanie operacji odświecania pamięci. Ponadto każdy obiekt typu MenuItem posiada trzy właściwości ikonę gdy przycisk jest aktywny, ikonę gdy przycisk jest nieaktywny oraz podpis. Oba te elementy są inicjalizowane podczas tworzenia obiektu w konstruktorach klas dziedziczących. Tworzenie menu odbywa się w metodzie startApp() podczas uruchamiania aplikacji. W pierwszej kolejności inicjalizowana jest tablica menuItems która przechowuje obiekty poszczególnych okien. private static final MenuItem[] menuItems = {new SelectSCForm(), 29 System informacji giełdowej na urządzenia mobilne new new new new GraphsForm(), StockQuotesForm(), SynchronizeForm(), SettingsForm()}; Tablica ta jest atrybutem klasy i jest dostępna dla innych metod. Następnie dla każdego elementu tej tablicy wykonywane są operacje: // utworzenie przycisku z opisem i ikoną Button button = new Button(menuItems[i].getDescription(), menuItems[i].getImageUnselected()); // formatowanie i nadawanie styli button.getStyle().setBgTransparency(0); button.getStyle().setBorder(null); button.setTextPosition(Button.BOTTOM); button.setAlignment(Button.CENTER); // przypisanie ikony gdy przycisk nie jest aktywny button.setRolloverIcon(menuItems[i].getImageSelected()); // dodanie przycisku do listy przycisków menuForms.put(button, new Integer(i)); // dodanie przycisku do formularza menuForm.addComponent(button); Za reakcje na działania użytkownika w MIDletach zbudowanych przy pomocy Lightweight UI Toolkit odpowiadają tzw. klasy słuchaczy (ang. listeners). Klasa takiego słuchacza musi implementować interfejs ActionListener oraz posiadać metodę publiczną actionPerformed która odpowiada za reakcje na działania. Tego typu klasą jest główna klasa aplikacji MSMClient i to ona odpowiada za reakcje na działania obejmujące menu główne. Działania podejmowane w przypadku wciśnięcia przycisku w menu obsługiwane są następująco: public void actionPerformed(ActionEvent source) { switch (source.getCommand().getId()) { // przycisk "wybierz" case RUN_COMMAND: // pobranie wybranej opcji z menu MenuItem item = menuItems[((Integer) menuForms.get( menuForm.getFocused())).intValue()]; // ustawienie przycisku powrotu dla tej opcji item.setBackForm(menuForm); // wyświetlenie item.render(); // rejestracja aktualnie wybranej opcji registerCurrent(item); break; // przycisk "wyjście" case EXIT_COMMAND: destroyApp(true); notifyDestroyed(); 30 System informacji giełdowej na urządzenia mobilne break; } } Rejestracja aktualnie wybranej opcji znajduje zastosowanie przy odświeżaniu zawartości niektórych formularzy. Metoda może sprawdzić które okno jest wyświetlane i jeśli spełnia ono wymagania może zostać wykonana na nim akcja. 4.10.5. Komunikacja z serwerem Komunikacja pomiędzy klientem a serwerem oparta jest o protokół SOAP. Opis wszystkich metod udostępnianych przez serwer zapisany został w pliku opisu usług WSDL. Na podstawie tego pliku z pomocą środowiska NetBeans IDE [12] została wygenerowana dlasa DataService znajdująca się w pakiecie msm.j2meclient.data.webservice która posiada identyczny interfejs z tym jaki posiada serwer udostępniający dane. Implementacja poszczególnych metod korzysta z bibliotek dostępnych w pakiecie J2ME Web Services i przetwarza komunikaty SOAP w celu pobrania z nich odpowiednich informacji. Przykładowo metoda wykonująca logowanie do serwera zaimplementowana jest następująco: public boolean login(String login, String password) throws java.rmi.RemoteException { // zapisanie wysyłanych parametrów do tablicy Object inputObject[] = new Object[] { login, password }; // wybór operacji logowania Operation op = Operation.newInstance( _qname_operation_login, _type_login, _type_loginResponse ); // przygotowanie operacji _prepOperation( op ); // wybranie SOAP jako nośnika op.setProperty( Operation.SOAPACTION_URI_PROPERTY, "" ); Object resultObj; try { resultObj = op.invoke( inputObject ); } catch( JAXRPCException e ) { /** * Obsługa błędów */ } // zwrócenie wyniku return ((Boolean )((Object[])resultObj)[0]).booleanValue(); } Z obiektów tego typu korzystają inne klasy odpowiedzialne za sterowanie konkretnymi procesami. 31 System informacji giełdowej na urządzenia mobilne 4.10.6. Uaktualnianie notowań W klasie StockQuotesManager zostały zaimplementowane wszystkie metody odpowiedzialne za operacje na notowaniach spółek. Jedną z nich jest metoda updateStockQuotes() która pobiera z serwera najświeższe dane o wskaźnikach spółki i zapisuje je do lokalnej bazy danych. W pierwszej kolejności następuje pobranie danych z serwera: DataService service = new DataService(); String data = service.getStocksQuotes(login, password); Ponieważ odbierany jest komunikat w postaci XML, należy go poprawnie przetworzyć aby uzyskać odpowiednie wartości. Do przetwarzania komunikatu XML użyta została biblioteka kXML. Przetwarzanie ciągu odbywa się w pętli, dla każdej spółki informacje zawarte są między znacznika <quote></quote>. W pętli tej pobranie konkretnych wartości wygląda następująco (przykład dla identyfikatora spółki): // przejście do znacznika <stockid> parser.require(XmlPullParser.START_TAG, null, "stockid"); // pobranie wartości Integer id = Integer.valueOf(parser.nextText()); // przejście do tagu zamykającego parser.nextTag(); Po pobraniu wszystkich wartości wyszukiwany jest w bazie danych rekord który przechowuje najbardziej aktualne notowania. Zmieniana jest w nim wartość pola last_result na false. Wstawiany rekord z wartościami pobranymi otrzymuje wartość true w tym polu co oznacza go jako najbardziej aktualny. // odszukanie rekordów które były oznaczone jako najbardziej aktualne RowSet oldRows = quotesTable.find("stock_id+last_result", "" + id.intValue() + "+" + true); // dla każdej oznaczenie jej jako nieaktualna while(oldRows.next()) { Row oldRow = oldRows.getCurrent(); oldRow.setField("last_result", new Boolean(false)); oldRow.save(); } // zapis do bazy danych Row row = quotesTable.createRow(); row.setField("stock_id", id); row.setField("price", price); row.setField("change", change); row.setField("total", total); row.setField("date", date); row.setField("last_result", new Boolean(true)); row.save(); 32 System informacji giełdowej na urządzenia mobilne 4.11. Instalacja aplikacji na urządzeniu przenośnym Proces instalacji należy rozpocząć od przekopiowania plików MSMClient.jar oraz MSMCliend.jad z katalogu /Java client/ znajdującego się na dołączonym DVD do pamięci stałej urządzenia. Następnie należy uruchomić z jego poziomu dowolny z tych plików, co spowoduje uruchomienie procesu instalacji programu. Po zakończeniu instalacji program jest gotowy do uruchomienia. 4.12. Obsługa programu 33 System informacji giełdowej na urządzenia mobilne 5. 5.1. SERWIS WWW Funkcjonalność serwisu W dzisiejszych czasach praktycznie każda aplikacja posiada własną stronę WWW. Zadaniem takiej strony jest przedstawienie możliwości aplikacji oraz dodatkowa funkcjonalność zależna od charakteru produktu. Dla systemu Mobile Stock Monitor serwis WWW przedstawiony w tym rozdziale pełni rolę uzupełnienia aby cała platforma tworzyła spójną całość. Do zadań serwisu należy: rejestracja nowych użytkowników, zarządzanie profilem, wybór obserwowanych spółek. 5.2. Platforma Java Enterprise Edition Serwis WWW został zbudowany na platformie Java Enterprise Edition 5 (Java EE). Platforma ta definiuje środowisko do tworzenia aplikacji działających w sieci której głównymi elementami są Enterprise JavaBeans, serwlety oraz JavaServer Pages (JSP). Te trzy elementy tworzą razem kompletne rozwiązanie dla tworzenia aplikacji. Gotowe aplikacje Java EE uruchamiane są na serwerze aplikacyjnym zgodnym z tą platformą. Do najważniejszych cech wyróżniających tę platformę są: bezpieczeństwo, transakcyjność, współbieżność, trwałość, obsługa obiektów rozproszonych [14]. 5.3. Java Persistence API Począwszy od Java EE w wersji 5, ze specyfikacji Enterprise Java Beans wydzielono osobną specyfikację zwaną Java Persistence API (JPA). Interfejs ten definiuje sposób odwzorowania obiektów języka Java (obiekty takie często są nazywane POJO, ang. Plain Old Java Objects) w bazie danych (jest to odwzorowanie nazywane ORM – ang. obiect to Relational Mapping). Tak odwzorowywane obiekty nazywane są komponentami encyjnymi (ang. entity beans). Korzystanie z JPA ułatwia komunikację pomiędzy aplikacją a serwerem bazy danych, nie wymagane jest w kodzie tworzenie żadnych połączeń oraz korzystania z natywnego języka SQL. Obiekty mogą być zapisywane i odczytywane przezroczyście, tzn. to biblioteka odpowiada za poprawną komunikację z bazą danych i zapis lub odczyt informacji. Java Persistence API jest całkowicie niezależna od wybranej bazy danych, aplikacje napisane w połączeniu z tą biblioteką mogą w bardzo łatwy sposób zostać przeniesione na inną bazę danych bez jakichkolwiek zmian w implementacji. Dodatkowo wprowadzono uniwersalny język zapytań EJB QL który pod wieloma względami 34 System informacji giełdowej na urządzenia mobilne przypomina język SQL – jednak został on stworzony przed wszystkim z myślą o obiektach Javy (nie o przetwarzaniu schematów relacyjnych) [14]. 5.4. JavaServer Faces JavaServerFaces (JSF) jest bazują na JavaServer Pages (JSP) biblioteką służącą do tworzenia interfejsu użytkownika dla aplikacji Java EE. Powstała ona by uprościć tworzenie stron WWW, oraz przyspieszyć proces ich tworzenia. Posiada wyrazisty model MVC [16], bogaty zbiór komponentów interfejsu użytkownika, przezroczysty dla programisty sposób przechowywania stanu sesji. Podobnie jak inne elementy platformy jest rozwiązaniem darmowym oraz stworzonym z pomocą specjalistów z całego świata w programie JCP. [] 5.5. Serwer aplikacji Na rynku dostępnych jest wiele serwerów przeznaczonych dla platformy Java EE. Znaczna ich liczba jest rozprowadzana bez opłat na licencji GPL i podobnych. Wszystkie te produkty udostępniają podstawowo tę samą ustandaryzowaną przez specyfikację Java EE funkcjonalność oraz dodatkową zależną od produktu i docelowych zastosowań. Gdy aplikacja nie wykorzystuje tej specyficznej funkcjonalności wdrożenie jej na inny serwer aplikacji jest niezwykle łatwe i nie wymagające znaczących kosztów. Dla aplikacji WWW systemu Mobile Stock Monitor został wybrany Serwer Aplikacji GlassFish v2 wydany we wrześniu 2007 roku. Produkt ten jest tworzony przez firmę Sun Microsystems i dostępny na zasadach licencji GPL. Implementacja serwisu WWW nie wykorzystuje żadnych specyficznych dla tego serwera funkcji i może zostać uruchomiona na dowolnym innym produkcie zgodnym ze specyfikacją Java EE w wersji 5. [] 5.6. Implementacja W następnych podrozdziałach autor przedstawi implementację wraz z opisem najważniejszych elementów serwisu WWW. 5.6.1. Nawigacja między stronami Opis reguł nawigacji całej aplikacji zawarty jest WEB-INF/faces-config.xml. Przykładowa nawigacja wygląda następująco: <navigation-rule> 35 w pliku System informacji giełdowej na urządzenia mobilne <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>registration</from-outcome> <to-view-id>/registration.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/pages/loggedIn.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/login.jsp</to-view-id> </navigation-case> </navigation-rule> Pojedyncza reguła zawarta jest w znaczniku <navigation-rule> i dotyczy widoku zdefiniowanego w znaczniku <from-view-id>. Ten widok może posiadać jeden lub więcej przypadków nawigacji (ang. naviagtion case). W przykładzie strona /login.jsp posiada trzy takie przypadki. Podstawą na zasadzie które jest wnioskowane do którego przypadku się odnieść jest akcja. Źródłem akcji może być wciśniecie przycisku na stronie lub wartość zwraca przez mechanizm obsługi zdarzeń. Znacznik <to-view-id> określa jaka strona ma zostać wyświetlona. 5.6.2. Uwierzytelnianie użytkownika Uwierzytelnianie użytkownika zostało zaimplementowane z pomocą biblioteki Spring Security która jest częścią szkieletu aplikacyjnego Spring. Biblioteka ta wymaga aby klasa przechowująca informacje o użytkowniku implementowała interfejs UserDetails. Implementacje tej klasy znajduje się w pakiecie msm.web.user. Ponad to wymagana jest klasa usługowa implementująca interfejs UserDetailsService której zadaniem jest zwracanie użytkownika o podanej nazwie. Oto implementacja jej jedynej metody: // pobranie jednostki utrwalania InitialContext ictx = new InitialContext(); Context envCtx = (Context) ictx.lookup("java:comp/env"); entityManager = (EntityManager) envCtx.lookup("persistence/msmPU"); // pobranie użytkownika z bazy danych Query query = entityManager.createQuery( "SELECT new User(u.id, u.name, u.surname, u.password, u.login) " + "FROM User AS u where LOWER(u.login)='" + username.toLowerCase() + "'"); user = (User) query.getSingleResult(); W przypadku nie odnalezienia użytkownika o podanej nazwie w bazie danych zgłaszany jest wyjątek typu UsernameNotFoundException. 36 System informacji giełdowej na urządzenia mobilne Aby serwlet wywoływał usługi biblioteki odpowiedzialne za uwierzytelnianie i autoryzację, konieczne było uzupełnienie deskryptora wdrożenia o następujące wpisy: <listener> <listenerclass>org.springframework.web.context.ContextLoaderListener</listenerclass> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filterclass>org.springframework.web.filter.DelegatingFilterProxy</filterclass> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Wpis ten filt DelegatingFilterProxy dla wszystkich wywołań stron dostępnych w serwisie. Reguły dotyczące filtrowania zawarte są w pliku WEB-INF/applicationContext-security.xml. <http auto-config="true"> <intercept-url pattern="/pages/**" access="ROLE_USER" /> <intercept-url pattern="/login.faces" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <form-login login-page="/login.faces" default-target-url="/pages/loggedIn.faces"/> </http> Dostęp do zasobów dla osób niezalogowanych jest ograniczony tylko do stron zawartych w katalogu główny. Do podstroi znajdujących się w katalogu /pages/ mają dostęp tylko osoby zalogowane [15]. 5.6.3. Wybór obserwowanych spółek Dodanie spółki do obserwowanych odbywa się poprzez zaznaczenie jej na liście dostępnych spółek. Lista spółek w formularzu wyświetlana jest przez komponent DataGrid. Każdy element na liście reprezentuje obiekt typu StockWrapper, który posiada dwie właściwości stock – komponent encyjny reprezentujący spółkę observed – czy dana spółka jest obserwowana przez użytkownika 37 System informacji giełdowej na urządzenia mobilne Zbiór tych obiektów jest tworzony w metodzie getObserved() w klasie ObservedCorpsBean. // pobranie wszystkich spółek giełdowych Query query = entityManager.createQuery("select new Stock(id, name, shortName, addDate) from Stock order by id asc"); List<Stock> result = query.getResultList(); // pobranie listy spółek obserwowanych przez użytkownika List<Stock> observedByUser = loggedUser.getObservedStocks(); // utworzenie listy spółek for(Stock stock : result) { if(observedByUser.contains(stock)) // spółka jest obserwowana observed.add(new StockWrapper(true, stock)); else // spółka nie jest obserwowana observed.add(new StockWrapper(false, stock)); } return observed; W zależności od spełnienia warunku sprawdzającego czy spółka znajduje się na liście spółek obserwowanych przez użytkownika zostaje utworzony obiekt StockWrapper który na formularzu będzie domyślnie zaznaczony lub nie. Po przyciśnięciu przycisku zapisz na formularzu wywoływana jest metoda save() // rozpoczęcie transakcji trans.begin(); // usuniecie wszystkich elementów z portfela i zapis do bazy loggedUser.getObservedStocks().clear(); entityManager.merge(loggedUser); // dla każdej wybranej do obserwacji spółki dodaj ją do listy for (StockWrapper wrapper : observed) { if (wrapper.isObserved()) { loggedUser.getObservedStocks().add(wrapper.getStock()); } } // zapis i zatwierdzenie transakcji entityManager.merge(loggedUser); trans.commit(); 5.7. Uruchomienie aplikacji Aby uruchomić aplikację WWW należy przekopiować znajdujący się na płycie DVD katalog /SerwisWWW/GlassFish/ zawierający serwer aplikacji GlassFish wraz z wdrożonym na niego serwisem na dysk twardy komputera. Następnie należy uruchomić z linii komend polecenie uruchamiające serwer: [ścieżka do katalogu]/bin/asadmin start-domain domain1 38 System informacji giełdowej na urządzenia mobilne Po uruchomieniu aplikacja dostępna jest z poziomu przeglądarki internetowej pod adresem: http://[adres serwera]:8080/MobileStockMonitorWWW/. 39 System informacji giełdowej na urządzenia mobilne ZAKOŃCZENIE 40 System informacji giełdowej na urządzenia mobilne BIBLIOGRAFIA [1.] Kim Topley, J2ME Almanach, Helion, Gliwice 2003 [2.] Oficjalna strona platformy Java Micro Edition http://java.sun.com/javame/index.jsp [3.] Specyfikacja CLDC 1.1 http://jcp.org/en/jsr/detail?id=139 [4.] Strona główna programu Java Community Process http://jcp.org/en/home/index [5.] Specyfikacja MIDP 2.0 http://jcp.org/en/jsr/detail?id=118 [6.] Specyfikacja J2ME Web Services http://jcp.org/en/jsr/detail?id=172 [7.] Oficjalna strona biblioteki OpenBaseMovil http://www.openbasemovil.org/ [8.] Oficjalna strona biblioteki Lightweight UI Toolkit https://lwuit.dev.java.net/ [9.] Treść licencji GPL http://www.gnu.org/licenses/old-licenses/gpl-2.0.html [10.] Cay S. Horstmann, Gary Cornell, Java 2 Podstawy, Helion, Gliwice 2003 [11.] Oficjalna strona biblioteki kXML http://kxml.objectweb.org/ [12.] Oficjalna strona środowiska programistycznego NetBeans http://www.netbeans.org/ [13.] Robert Bruner, Java w komercyjnych usługach sieciowych, Helion, Gliwice 2003 [14.] Bill Rurke, Richard Manson-Haefel, Enteprise JavaBeans 3.0, Helion, Gliwice 2007 [15.] Oficjalna strona biblioteki Spring Security http://static.springframework.org/spring-security/site/ [16.] Jakaś literature o wzorcach projektowych [17.] Coś o SMSach o-O [18.] Oficjalna strona serwera aplikacji GlassFish https://glassfish.dev.java.net/ [19.] David Geary, Cay S. Horstmann, Core JavaServer Faces wydanie II, Helion, Gliwice 2008 ZAŁĄCZNIKI 41