Aapo Puhakka
TEKNILLINEN KORKEAKOULU | DIPLOMITYÖN TIIVISTELMÄ |
Tekijä: | Aapo Puhakka |
---|---|
Työn nimi: | Erilaisten käyttöliittymien yhteisen toiminnallisuuden keskittäminen sovelluspalvelimeen |
Title in English: | Concentrating Common Functionality of Different User Interfaces into an Application Server |
Päivämäärä: | 24.9.2001 |
Sivumäärä: | 73 |
Osasto: | Tietotekniikan osasto |
Professuuri: | Tik-111 Vuorovaikutteinen digitaalinen media |
Työn valvoja: | Prof. Tapio Takala |
Työn ohjaaja: | FK Hannu Puhakka |
Tässä diplomityössä tarkastellaan uudenlaista ohjelmistoarkkitehtuuria, jolla eri käyttöliittymät kykenevät käyttämään toiminnoissaan yhteisiä olioita. Nämä yhteiset oliot on keskitetty käyttöliittymien ja tietokannan välissä sijaitsevaan sovelluspalvelimeen, jonka käyttäminen on pakollista. Tämänkaltaista järjestelmää kutsutaan myös kolmitasoarkkitehtuuriksi. Työssä on rakennettu yleinen toimintamalli ja sitä tukevat komponenttikirjastot kolmitasoarkkitehtuurin mukaisten sovellusten tekemiseksi. Esimerkkinä tarkastellaan laajan projektinhallintajärjestelmän toteuttamista tämän mallin mukaisesti tehtyjen komponenttikirjastojen avulla. | |
Avainsanat: | sovelluspalvelin, kolmitasoarkkitehtuuri, monitasoarkkitehtuuri, middleware, komponentti, käyttöliittymä, java |
HELSINKI UNIVERSITY OF TECHNOLOGY | ABSTRACT OF MASTERS'S THESIS |
Author: | Aapo Puhakka |
---|---|
Title of the thesis: | Concentrating Common Functionality of Different User Interfaces into an Application Server |
Title in Finnish: | Erilaisten käyttöliittymien yhteisen toiminnallisuuden keskittäminen sovelluspalvelimeen |
Date: | 24.9.2001 |
Number of pages: | 73 |
Department: | Department of Computer Science and Engineering |
Professorship: | Tik-111 Interactive Digital Media |
Supervisor: | Prof. Tapio Takala |
Instructor: | MSc Hannu Puhakka |
This Master's Thesis contemplates a new kind of software architechture, where different user interfaces can use common objects to implement their functionality. These objects are concentrated between user interfaces and database into an application server, which use is mandatory. This kind of system is also called three-tiered architechture. A general design framework and supporting component libraries for development of three-tiered systems have been developed in the work. As an example design of a large project management system with these component libraries shall be examined. | |
Keywords: | application server, three-tiered architechture, multi-tiered architechture, middleware, component, user interface, java |
Vetokonsultit Oy:llä on pitkät perinteet yleiskäyttöisten kirjastojen ja komponenttien rakentamisessa ohjelmistotuotannon tehostamiseksi. Yritys on aikoinaan perustettu konsultointitoimistoksi vuonna 1984. Toiminta on vähitellen laajentunut tietojärjestelmien konsultointiin, määritykseen ja lopulta yksityiskohtaiseen toteutukseen yhä vaativammalla tasolla. Ensimmäisiä yleiskirjastoja rakensivat FK Hannu Puhakka ja DI Sakari Aaltonen Paradox-kehittimen ympärille 80-luvun lopulla. 90-luvun alussa yleiskirjastoja rakensi DI Martti Kallavuo SQLWindows-kehittimelle. 90-luvun loppupuolella yleiskomponentteja kehittivät mat. yo Olli Niinivaara ja allekirjoittanut Delphi-sovelluskehittimelle.
Graafisten käyttöliittymien esiintulo 90-luvulla merkitsi ohjelmoinnin huomattavaa vaikeutumista. Saman toiminnallisuuden toteuttaminen graafiseen sovellukseen saattoi viedä moninkertaisesti työtä entiseen merkkipohjaiseen versioon verrattuna. Toivon kehittämäni uuden yleiskäyttöisen tietokantajärjestelmien tekemiseen suunnatun komponentiston palauttavan tarvittavan työmäärän 80-luvun lopun tasolle ja pienemmäksikin. Uskoisin tämän onnistuvan käyttämällä tehokkaasti hyväksi Javan Delphiä kehittyneempiä mahdollisuuksia oliopohjaiseen ajatteluun, ottamalla oppia menneistä komponenttisukupolvista sekä tuomalla esiin muutamia uusia ajatuksia. Toivon, että tämä diplomityö soveltuu johdatusmaiseksi opetusmateriaaliksi kehitettyjen komponenttien keskeisistä piirteistä ja ideoista tuleville komponentinkehittäjille ja komponentteja käyttäville sovellusohjelmoijille.
Haluan kiittää ohjaajaani FK Hannu Puhakkaa jatkuvasta uusiin komponentteihin liittyvien toiminnallisuusvaatimusten esiintuomisesta. Kiitoksia valvojana toimineelle prof. Tapio Takalalle kirjoitustyöhön liittyvistä neuvoista. Haluan kiittää aiempien komponenttisukupolvien tekijöitä niistä saaduista ideoista. Kiitoksia tekn. yo Taru Hannikaiselle oikoluvusta. Tiettyjä komponenttien yksityiskohtia ja joitakin niillä tehtyjä esittelysovelluksia on ollut tekemässä muutamia kesätyöntekijöitä, heitä ovat olleet tekn. yo:t Anton Alstes, Juha Immonen, Heikki Linnakangas, Tapani Löksy, Jani Pyhtilä, Kaarle Ritvanen ja Jorma Sainio.
90-luvulla käytetyimmäksi tietojärjestelmien toteutusarkkitehtuuriksi nousi ns. client/server arkkitehtuuri. Sen etuna on mm. kyky turvata tiedon eheys useamman käyttäjän käsitellessä samaa tietoa samaan aikaan; eikä se ole riippuvainen yhteisellä verkkolevyllä sijaitsevan tekstitiedoston synkronoidun käsittelyn onnistumisesta. Tyypillisissä räätälöidyissä järjestelmissä serverinä toimii relaatiotietokanta, joka vastaa tiedon tallennuksesta. Client-osana on käyttöliittymän ja toiminnallisen logiikan sisältävä sovellusohjelma. [1]
Kaikki toiminallisuus on kuitenkin sidottu client-puolen sovelluksiin. Tästä aiheutuu client-osan sovellusten kasvaminen suuriksi kokonaisuuksiksi, joissa sovelluksen looginen toiminnallisuus (ns. business-logiikka) ja käyttöliittymän käsittelyn yksityiskohdat ovat toisiinsa sekoittuneena samassa paikassa. Koodin jakaminen ja hyväksikäyttäminen eri sovellusten välillä vaikeutuu. Eri sovellukset sinänsä voivat jakaa yhteisiä kirjastoja, mutta arkkitehtuuri ei kannusta eikä pakota siihen. Yhteisten muuttuja-arvojen ja olioiden jakaminen on lähes mahdotonta. Tästä syystä client-sovellusten keskinäinen viestintä, valvonta ja synkronointi on hyvin hankalaa.
Mm. näiden client/server -arkkitehtuurin ongelmien takia on kehittynyt uudempi kolmi- tai monitasoarkkitehtuurin malli. Siinä client-osan ja tietokannan välissä on sovelluspalvelinkerros, johon pyritään keskittämään eri client-osien yhteinen toiminnallisuus sekä valvonta- ja synkronointilogiikka. Client-osa ei saa suoraan ottaa yhteyttä tietokantaan eikä käyttää SQL-lauseita, vaan sen on kutsuttava sovelluspalvelimen olioiden metodeja. [2] [1]
Viime aikoina on noussut esiin tarve tehdä samaan järjestelmään käyttöliittymiä eri tekniikoilla erilaisia tarkoituksia varten [3] . Perinteisten GUI-sovellusten lisäksi voidaan tarvita mistä tahansa nopeasti käyttöönotettavaa HTML-liittymää, mobiilikäyttöön SMS/WAP-liittymää ja ehkä jopa tehokäyttäjälle täysin tekstipohjaista käyttöliittymää. Näiden eri käyttöliittymien tekeminen nopeutuu, kun ne voivat käyttää samoja palveluja [1] .
Päätavoitteena työssä on ollut kehittää toimivat komponenttikirjastot, joilla tämän arkkitehtuurin mukaisten sovellusten tekeminen sujuu nopeasti ja tehokkaasti. Toimiva sovellus pitäisi saada aikaan määrittelemällä pari perusluokkaa sekä tietokannan taulujen rakenteet, linkitykset ja kenttien näkyvyysoptiot. Client-puolen pitäisi pystyä tämän määrittelyn perusteella rakentamaan hakusivut ja päivityslomakkeet, sekä normaalin lisäys-, päivitys- ja poistologiikan täytyy toimia. Näin saadaan nopeasti aikaan toimiva prototyyppi sovelluksesta. Silti kehitysympäristön tulisi olla mahdollisimman joustava ja erilaisten asiakaskohtaisten erikoisratkaisujen tekemisen on oltava mahdollista.
Tämän sovelluskehitysympäristön toimivuutta testataan rakentamalla sillä uudistettu versio laajahkosta projektinhallinta-, tuntikirjaus- ja laskutusjärjestelmästä; Proslasta.
Tässä vaiheessa järjestelmän kaikki osat toteutetaan Java:lla [4] . Periaatteessa myös liittymät muihin kieliin ovat mahdollisia, jos toteutetaan sovelluspalvelimen kutsu-rajapinta ao. kielellä. Vaatimuksena on, että ao. kielessä on mahdollista luoda TCP/IP -yhteyksiä.
Näiden komponenttikirjastojen avulla rakennetusta sovelluspalvelimesta käytetään tarvittaessa nimitystä VetoBox-sovelluspalvelin. Kehitetystä sovelluskehitysmenetelmästä käytetään tarvittaessa nimitystä VetoBox-menetelmä.
Tavoitteena on myös ollut kehittää tekniikkaa, joka mahdollistaisi ns. ASP-toiminnan. Eli mahdollisuuden erilaisten tietojärjestelmien tarjoamiseksi asiakkaiden käytettäväksi Internet-yhteyden yli sovelluspalvelun tarjoajan (Application Service Provider) servereiltä. Kyseessä olisi tällöin sovellusvuokraus laskutuksen ollessa esim. kuukausipohjaista. Malli mahdollistaisi sovellusten tarjoamisen halvemmalla esim. pk-yritysten käyttöön, sillä yritysten ei tarvitsisi hankkia omia servereitä eikä ylläpitää niitä. Erilaisten sovellusongelmien selvittäminen olisi paljon helpompaa, sillä tukihenkilön ei tarvitsisi matkustaa asiakkaan luokse nähdäkseen ongelmaa tai tietokannan tai sovelluksen tilannetta ( kuva 1.1 ).
Kuva 1.1: Asiakas ja tukihenkilö käyttävät samaa sovellusta eri paikoista.
Jotta järjestelmä toisi kustannussäästöjä, yritysten tulisi siis voida jakaa sama serveri, tietokanta ja ylläpitohenkilöstö, ilman että he välttämättä edes tietävät toistensa olemassaolosta. Jotta järjestelmää voitaisiin käyttää toisinaan hieman takkuisenkin Internetin läpi, tulee käytettyjen tietoliikenneprotokollien olla mahdollisimman tehokkaita. Jotta asiakkaat voisivat uskoa luottamuksellisia tietojaan ASP-tarjoajan haltuun käytettäväksi avoimen Internetin yli, täytyy järjestelmän turvallisuus- ja luotettavuustason olla korkea. Kommunikoinnissa tulee käyttää asiallisia ja vahvoja salausalgoritmeja, eikä tule antaa mahdollisuutta päästä käsiksi toisten tietoihin esim. hyökkääjän modifioimilla client-sovelluksilla.
Useimmissa luvuissa tarkastellaan erikseen asiaa yleisesti ja sen jälkeen esitellään komponenttien avulla toteutetun laajan projektinhallintajärjestelmän, Proslan, ratkaisuja. Näin ei ole menetelty Tietoliikenne-luvussa, missä Proslaa varten ei ole kehitetty erityisratkaisuja ja Graafinen käyttöliittymä-luvussa, missä eri käyttöliittymämalleja esiteltäessä käytetään Proslan käyttöliittymiä esimerkkeinä.
Arkkitehtuuri-luvussa käsitellään tarkemmin yleisarkkitehtuuria ja vertaillaan sen ominaisuuksia kirjallisuudessa esiintyviin kuvauksiin. Sovelluspalvelin-luvussa kuvataan tarkemmin sovelluspalvelimen toimintaideaa ja sisäistä rakennetta. Tietoliikenne-luvussa tarkastellaan vaihtoehtoja eri osien väliseen kommunikointiin.
Graafinen käyttöliittymä-luvussa tarkastellaan järjestelmällä rakennettavia perinteisiä, 'raskaita' graafisia käyttöliittymiä Java-kielellä ja Swing-käyttöliittymäkomponenttikirjastolla toteutettuna. HTML-käyttöliittymä-luvussa käsitellään erilaisia menetelmiä ja valittua tapaa täysin selainpohjaisten www-sovellusten tekemiseen.
Raportointi-luvussa käsitellään tapoja tuottaa järjestelmällä erilaisia sovelluksiin liittyviä raportteja tietokannasta. Muita käyttöliittymäideoita-luvussa kerrotaan muista ideointi- tai suunnitteluasteella olevista järjestelmään mahdollisesti liitettävistä käyttöliittymistä. Asiakaskohtaiset sovitusmahdollisuudet-luvussa esitellään mahdollisuuksia tuottaa samasta sovelluksesta eri asiakkaille erilaisia versioita.
Arviointi-luvussa arvioidaan järjestelmän eri osa-alueita sekä sitä, mitä hyötyä tai haittaa tämäntyyppisestä arkkitehtuurista on ollut niiden toteuttamisessa. Lopussa on vielä Yhteenveto, lähdeluettelo sekä liitteinä lyhyt yhteenvedonomainen kuvaus client-osan ja sovelluspalvelimen välisestä ohjelmointirajapinnasta sekä käytetystä tietoliikenneprotokollasta.
Proslan (Projektilaskutus) tehtävinä on tukea projektityötä tekevän yrityksen töiden hallintaa ja seurantaa, tuntikirjanpitoa, laskutusta, kustannus- ja kannattavuuslaskentaa sekä operatiivista johtamista.
Työntekijät syöttävät joko päivittäin tai jaksoittain tekemänsä työtunnit järjestelmään jollain työilmoitussovelluksella. Samoin järjestelmään syötetään omilla sovelluksillaan kulut (ostolaskut) ja matkalaskut. Haluttaessa myös sihteeri voi hoitaa tietojen tallennuksen työtekijöiden täyttämien paperilomakkeiden perusteella.
Työntekijät merkitsevät ilmoituksen tilaksi Valmis, jolloin ilmoitusta ei enää muuteta ja esimiehet voivat hyväksyä ilmoitukset. Hyväksynnän jälkeen ajetaan ajo, jossa määritetään ilmoitusten laskutustuotteet ja -arvot sekä tilastoidaan ilmoituksia tehtävien seurannan nopeuttamiseksi. Kaikkien syöttösovellusten tiedot tallettuvat tehtavaloki-tauluun.
Laskutettavat tuotteet ovat tuote-taulussa. Käyttäjä ilmoittaa tekemälleen työlle työlajin, joka kuvautuu työn kustannustason määrääväksi kustannuslajiksi. Tietyn työntekijän mahdolliset kustannuslajit näkyvät Olento-sovelluksen kautta päivitettävässä työntekijäntuote-taulussa, jossa myös määritetään, miten työlaji kuvautuu kustannuslajiksi ja edelleen laskulla asiakkaalle näkyväksi tuotteeksi. Kulukirjaus-sovelluksella kustannuslaji muuttuu tuotteeksi kustannuslajin laskutustuote-kentän perusteella.
Tehtävä-sovelluksella voidaan hallita projekteja sekä tarkkailla niiden tilastoja ja tuntimääriä. Päätason projektiin liittyy asiakas ja hinnasto. Hinnastossa määritellään kunkin laskutettavan tuotteen hinta. Tehtävä-sovelluksella voidaan lisätä sellaisten tehtävien, joiden laskutustapa on urakka tai toistuva lasku, laskutusta varten tarvittavat rivit tehtavaloki-tauluun.
Tilastoinnin jälkeen voidaan aja laskutusajo Laskutus-sovelluksella, millä laskutusta tekevät henkilöt voivat vielä tarkastaa summien oikeellisuuksia ennen laskujen muodostusta. Laskutusajossa muodostetaan asiakkaille lähetettävät erilaisten laskutustapojen (esim. tuntilaskutus tai urakkalaskutus) mukaisesti.
Laskuja jatkokäsitellään Lasku-sovelluksella, jossa tietoja on mahdollista korjata. Kun lasku siirtyy tilasta Ehdotus tilaan Avoin, sen tietoja ei voi enää muuttaa ja sen rivien summat takaisinlasketaan tehtavaloki-tauluun, jotta järjestelmällä voidaan seurata todellisuudessa laskutettuja määriä.
Järjestelmästä on olemassa aiempi versio, jonka on tehnyt FK Hannu Toivonen Paradox for Windows -kehitysvälineellä. Uutta versiota tehtäessä ei ole pelkästään käännetty vanhoja ominaisuuksia uuteen ympäristöön, vaan myös järjestelmän tietokantarakenne on uudistettu, jotta järjestelmästä saataisiin joustavampi, laajennettavampi ja paremmin uudenlaisiin tehtäviin ja tarpeisiin soveltuva. Aiemman version nimi oli Prosla for Windows; tämän version työnimenä on ollut Prosla for Java.
Toteutettaessa tietokantajärjestelmää client/server -arkkitehtuurilla (kuten kuvassa 2.1) käytössä on yksi keskustietokanta, johon lukuisat eri client-sovellukset ovat suoraan yhteydessä. Eri sovellukset (esim. tuntikirjaus, projektinhallinta, laskutus) ovat tyypillisesti omia suoritettavia ohjelmiaan. Serverikoneella ei juurikaan suoriteta järjestelmän kehittäjien ohjelmoimaa koodia. Siellä pyörii ainoastaan normaali tietokantapalvelin. Siten kaikki sovellusten toiminnallinen tilatieto on joko raskaissa client-sovelluksissa tai tietokannan tauluissa.
Kuva 2.1: Perinteinen client/server -arkkitehtuuri.
Toteutettaessa järjestelmää kolmitasoarkkitehtuurin ( kuva 2.2 ) mukaisesti tietokannan ja client-sovellusten välissä on VetoBox-sovelluspalvelin, joka säilyttää tietoa client-sovellusten tilasta. Sovelluspalvelin synkronoi client-sovellusten toiminnan, jakaa yksikäsitteiset avaimet, hoitaa lukitukset, etc. Sovelluspalvelimeen pyritään keskittämään eri sovellusten yhteinen logiikka. Client-sovellukset eivät ota suoraan yhteyttä kantaan; siten ne eivät tarvitse tietokanta-ajureitakaan ja periaatteessa tietokanta voitaisiin vaihtaa ilman, että client-sovellukset asiaa huomaisivat. Lisäksi järjestelmään voidaan lisätä muita erityyppisiä elementtejä, jotka käyttävät sovelluspalvelimen palveluja, kuten raportointipalvelin, HTML-käyttöliittymä, mobiilikäyttöliittymä tai jollakin toisella kielellä tehty käyttöliittymä.
Kuva 2.2: Käytetty kolmi- (tai moni-) tasoarkkitehtuuri. Pisteillä ympäröityjä lisäosia ei ole toteutettu.
Kuvassa 2.2 Java client on Swing-käyttöliittymäkomponenttikirjastolla tehty perinteinen, 'raskas', graafinen käyttöliittymä. Raportointipalvelimen tehtävänä on muotoilla HTML:ksi järjestelmän tiedoista tehtävät raportit ja toimia samalla HTTP-palvelimena, jolta raportit voidaan hakea selaimen kautta. HTML-palvelimen tehtävänä on generoida järjestelmään liitetyt selaimen kautta käytettävät HTML-sovellukset sekä toimia niiden HTTP-palvelimena. Lisäksi on mietitty, muttei vielä toteutettu, mahdollisuuksia liittää järjestelmään Delphi:llä tehty sovelluspalvelimen kanssa keskusteleva perinteinen 'raskaalla' graafisella käyttöliittymällä varustettu Windows-sovellus sekä kännykkäyhteyden mahdollistava WAP/SMS-palvelin.
Tavallisimmissa järjestelmissä tietokanta, sovelluspalvelin, raportointipalvelin ja HTML-palvelin kannattanee sijoittaa samalle koneelle. Niiden väliset yhteydet kannattaa luoda siten, että sovelluspalvelin, raportointipalvelin ja HTML-palvelin toimivat saman prosessin sisällä ja näin vältytään tietoliikenneprotokollan aiheuttamalta ylimääräiseltä kuormitukselta. Suuremmissa järjestelmissä eri palvelimet voidaan jakaa eri koneille ja samoja palvelimia voi periaatteessa olla useillakin koneilla. Tällöin tietyt krittiset sovelluspalvelimen lukitusoperaatiot keskitetään yhdelle tietylle palvelimelle. Tällaista useiden rinnakkaisten, hajautettujen ja skaalautuvien palvelimien muodostamaa kokonaisuutta ei tosin vielä ole toteutettu. Kuitenkin sellaisen kehittäminen on mahdollista kohtuullisella työmäärällä.
Client/Server-maailmassa käyttöoikeuksien hallinnassa täytyy nojautua siihen, että client-sovellukset on ohjelmoitu oikein eivätkä ne tee muuta kuin määriteltyjä operaatioita. Tällöin järjestelmä on haavoittuvainen hyökkäykselle, jossa käytetään sopivasti muunneltuja client-sovelluksia. Ongelmaa hieman pienentää mahdollisuus turvautua tietokannan taulukohtaisiin käyttöoikeuksien määrittelyihin (ns. GRANT -lauseet). Mutta esim. rivikohtaisten rajoitusten tekeminen ei ole mahdollista muuten kuin luottamalla client-sovellusten koodin toimivuuteen. Sen sijaan käytettäessä välissä sovelluspalvelinta, voidaan siihen toteuttaa mitä moninaisempia käyttöoikeusrajauksia.
Sovelluspalvelimen käytön etuna on myös mahdollisuus yhdistää hyvin erilaisia, eri käyttöjärjestelmillä toimivia ja eri ohjelmointikielillä tehtyjä osia toisiinsa [5] . Ainoastaan sovelluspalvelimella täytyy olla käytettävän tietokannan ajurit, niitä ei tarvitse jaella eri client-osille. Vaihdettaessa käytettävää tietokantapalvelinta täytyy vaihtaa ainoastaan sovelluspalvelimen ajurit. Lisäksi sovelluspalvelimen avulla on mahdollista yhdistää eri tietokannoissa sijaitseva informaatio loogiseksi kokonaisuudeksi.
Alan termistö on hieman epäyhtenäinen. Sovelluspalvelinkerroksesta käytetään myös nimitystä middleware. Samoin käsitys siitä, minkälaisia osia on missäkin kerroksessa on hieman epäyhtenäistä. Varhaisissa esityksissä [5] katsottiin tietokannan olevan osa middleware:a käyttöjärjestelmän muodostaessa pohjakerroksen. Mielestäni kuitenkaan käyttöjärjestelmä ei ole järjestelmän toiminnallinen elementti, vaan on osa jokaisen kerroksen tarvitsemaa perusinfrastruktuuria, joka ei näyttele kovin aktiivista osaa järjestelmän toiminnassa. Uudemmissa esityksissä [2] katsotaankin tietokannan muodostavan alhaisimman tason kerroksen.
Tunnetussa esityksessä [5] middleware jaetaan erikseen osiin middleware services ja framework. Kehitetty komponenttikirjasto sisältää ominaisuuksia kummastakin tyypistä. Middleware service:n tapaan komponenttikirjastolla voidaan kehittää toimialariippumattomia sovelluksia. Toisaalta kutakin järjestelmää varten yleiskomponenteista perityt järjestelmäkohtaiset luokat muodostavat framework:n tapaan pohjan tietyn sovellusalueen käyttöliittymille.
Framework:n tapaan client-puolen yleiskomponentit määrittelevät pitkälti tietynkaltaisen alustariippumattoman käyttöliittymän, joka tosin on hyvin samantapainen eri toimialojen sovellusten kesken. Framework:n tapaan VetoBox-sovelluspalvelin tarjoaa client-sovelluksille yksinkertaisemman rajapinnan alapuolella olevan tietokannan käsittelyyn.
Middleware service:n tapaan VetoBox-sovelluspalvelinta voidaan ajaa eri alustoilla ja siihen voidaan ottaa etäyhteyksiä. Samoin middleware service-käsitteen vaatimuksen mukaisesti VetoBox-sovelluspalvelimen käyttöön tarvittava tietoliikenneprotokolla ja ohjelmointirajapinta on julkisesti määritelty; ne ovat pääpiirteissään kuvattuina mm. tämän diplomityön liitteinä.
Valitulla toimintatavalla usein mainittu ongelma [5] siitä, mitä toiminnallisuutta pitäisi toteuttaa client-puolella ja mitä pitäisi toteuttaa serveri-puolella, muuttuu yksinkertaisemmaksi. Tietokantaa suoraan hyödyntävien toimintojen logiikkaosa tulee toteuttaa sovelluspalvelimen puolella ja niiden käyttöliittymäosat sekä pelkästään käyttöliittymää koskettavat toiminnot client-puolella. Silti yksittäisten erikoistoimintojen osalta sovelluskehittäjän eteen voi tulla valintatilanne, jossa tietyn sovelluksen toiminnon voisi toteuttaa joko puhtaasti client-puolella tai sovelluspalvelimelle tehtävää erikoispalvelua käyttäen.
Proslassa on keskitetty tietokanta, siihen yhteydessä oleva sovelluspalvelin, ainakin kahdeksan eri Java Application:ia (työilmoitus (josta on olemassa 4 eri versiota), kulukirjaus, matkalasku, tehtävä, laskutusajo, laskujen hallinta, työntekijöiden ja asiakkaiden hallinta ja perustieto: erilaisten harvemmin päivitettävien taulujen hallinta), raportointipalvelin ja HTML-käyttöliittymäpalvelin.
Työilmoitussovelluksella työntekijät kirjaavat eri projekteille tekemänsä työtunnit järjestelmään. Eri organisaatioilla voi olla erilainen ilmoitusjakson pituus, mahdollisten projektien määrä tai haluttu ilmoitusten yksityiskohtaisuuden taso. Koska Työilmoitus on kaikkien eniten käytetty sovellus, siitä on kehitetty useita vaihtoehtoisia käyttöliittymiä yrityksen käyttötilanteen mukaan valittavaksi.
Kulukirjaus-sovelluksella voidaan kirjata erilaisia ostolasku-tyyppisiä kuluja järjestelmään. Näitä tietoja voidaan kirjata myös työilmoitussovelluksen kautta. Tietojen käsittelyprosessi yrityksessä vaikuttaa siihen kumpi syöttötapa on luontevampi.
Matkalasku-sovelluksella voidaan kirjata erillisiä 'virallisia' matkalaskuja. Haluttaessa toimia yksinkertaisesti, voidaan kilometrit ja päivärahat ilmoittaa suoraan myös työilmoitussovelluksella. Työilmoitus-, Kulukirjaus- ja Matkalasku-sovellukset tallentavat tietonsa yhtenäisellä tavalla samaan tauluun, jolloin kaikkia kustannuksia voidaan käsitellä yhtenevällä tavalla tästä eteenpäin.
Tehtävä-sovelluksella hallitaan projektien tietoja, kuten laskutustapaa, asiakkaita, osallistujia, etc. Sovelluksella voidaan seurata myös projektien kulloistakin työtunti- ja laskutustilannetta. Projektien hierarkiarakenne voidaan valita yrityskohtaisesti 1-n tasoiseksi.
Laskutus-sovelluksella voidaan tarkastaa laskutettavien projektien summatietoja eri tasoilla ennen laskutusta sekä muodostaa laskut. Lasku-sovelluksella voidaan korjata, hyväksyä ja tulostaa laskutus-sovelluksella tehtyjä laskuja sekä luoda kokonaan uusia laskuja.
Työntekijöitä ja asiakkaita hallitaan omalla Olento-sovelluksella. Mm. erilaisten harvemmin päivitettävien perustietotaulujen ja käyttöoikeustietojen hallinnointiin on oma Perustieto-sovellus.
Työlista-sovelluksella hallitaan projektien yksityiskohtaisia työlistoja. Toisinaan halutaan tarkastella jostain ulkopuolelta satunnaiselta koneelta tietyn projektin yksityiskohtaista työtilannetta. Tätä varten on erillinen selaimen kautta käytettävä HTML:llä tehty työlistan käsittelysovellus. Esim. yrityksen asiakkaille voidaan antaa käyttöoikeudet sovellukseen siten, että he kykenevät seuraamaan reaaliaikaisesti omien projektiensa töiden tilannetta ja esittämään uusia työtehtäviä.
Järjestelmän raportit tehdään pääsääntöisesti omalla raporttieditorilla ja ne tuotetaan HTTP-protokollaa noudattavalla ja editorilla tehtyjä raporttimäärittelyjä ymmärtävällä raporttipalvelimella selaimeen HTML:nä. Käyttäjä voi tämän jälkeen vaikka tulostaa raportin tai syöttää sen tiedostona johonkin toiseen ohjelmaan. HTML ei kuitenkaan sovellu esim. laskulomakkeiden tulostukseen, koska niiden asettelun täytyy olla tarkasti oikein. Tätä varten on toteutettu oma graafinen raporttieditori, jolla voidaan tehdä suoraan paperille tulostettavia lomakkeita.
Sovelluspalvelimen suunnittelun keskeinen idea on ollut tehdä siitä oliotietokanta. Perinteisiä oliotietokantoja on rakennettu käyttämällä omaa oliokyselykieltä [6] . Sen sijaan VetoBox-sovelluspalvelimelle voidaan tehdä oliokutsuja kuten mihin tahansa muuhun oliopohjaisen kielen olioon. Myös varsinaisten oliokantojen kehityksessä on tällä hetkellä nähtävissä suuntaus pois pelkällä kyselykielellä toimimisesta aktiivisempaan suuntaan [7] [8] .
VetoBox-sovelluspalvelimella on yksi keskusluokka, Serveri, josta päästään käsiksi muihin luokkiin. Client-sovelluksen avatessa yhteyden sovelluspalvelimeen luodaan uusi Sessio-olio, joka kuvaa yhtä palveltavaa sovellusta. Sessio:n muiden metodien suoritus ei onnistu, ennenkuin käyttöoikeus on hyväksytty asianomaisella metodilla. Sekä Serveri että Sessio-luokasta peritään toteutettavaan sovelluspalvelimeen järjestelmäkohtainen versio.
Sovelluspalvelimen perusolioita ovat Taulu-tyypin oliot, jotka vastaavat tietokannan tauluja. Niihin on liitetty toimintoja, kuten haku, lisäys, talletus ja poisto. Taulu-oliot jakaantuvat kahteen ryhmään:
TauluRakenne-olioihin, jotka kuvaavat taulun rakennetta ja josta kustakin on yleensä vain yksi instanssi järjestelmässä.
Taulu-olioihin, jotka kuvaavat taulun käyttöä tietyssä tarkoituksessa järjestelmässä ja joista on useita instansseja.
Näihin jälkimmäisiin voidaan varastoida välimuistiin kullakin hetkellä tietyn sovelluksen kannalta relevantteja tietoja kannasta. Niissä voidaan pitää yllä sovellusten toiminnallisia tilatietoja. Jokaista tietokannan taulua varten tarvitaan perityt TauluRakenne ja Taulu -luokat. Näiden perusluokkien väliset suhteet ovat nähtävillä kuvassa 3.1.
Kuva 3.1: Serveri, Sessio, TauluRakenne ja Taulu -luokkien suhteet.
Taulun kentät ovat myös olioita, joilla on ominaisuuksia, kuten ohjelmoijan kentästä käyttämä nimi, käyttäjälle näytettävä nimi, kentän nimi kannassa, tyyppi, saako kentän perusteella hakea, saako kentän arvoa muuttaa, etc. Nämä kenttäoliot sijaitsevat komponentteina TauluRakenne-olioissa.
Lisäksi TauluRakenne-olioissa on määritelty taulujen yhteydet toisiinsa. Taulu-tyyppisten olioiden komponentteina saattaa olla muita Taulu-tyyppisiä olioita taulujen välisten yhteyksien mukaisesti.
Taulu ja TauluRakenne -olioiden periytymiskaavio on esitelty kuvassa 3.2. Ylimmät Taulu ja TauluRakenne kuvaavat geneerisiä tauluja, joiden metodien toteutukset eivät käytä SQL-kantaa lainkaan. Hakutaulu ja HakutauluRakenne -luokat kuvaavat taulua, jolle voidaan tehdä hakuoperaatioita.
Kuva 3.2: Taulu ja TauluRakenne-luokkien periytymispuu.
Varsinaiset sovelluskohtaiset Taulu-luokat (sekä Rakenne-luokat että sessiokohtaiset instanssit) periytyvät joko Paataulu, Lookuptaulu tai Alataulu -luokasta. Tämä kolmijako vastaa taulun mahdollista roolia käyttöliittymässä. Päätaulu on taulu, jolle käyttöliittymässä saatetaan suoraan tehdä esim. haku-, lisäys- tai talletusoperaatioita. Päätaulu saattaa sisältää alatauluja ja lookuptauluja.
Alataulu-käsite kuvaa taulua tilanteessa, jossa yhteen päätaulun tietueeseen liittyy monta alataulun tietuetta ja nämä alataulun tietueet halutaan näyttää käyttöliittymässä päätaulun lomakkeella, kuten kuvassa 5.2 . Alataulun operaatiot liittyvät aina kiinteästi johonkin päätaulun operaatioon.
Taulun kenttä voidaan määritellä lookupkentäksi. Tällöin kenttään sijoitettavan arvon oikeellisuus tarkistetaan kenttään liittyvästä lookuptaulusta. Lookupkenttään voidaan liittää asetettavia kenttiä, joiden arvo muuttuu lookupkentän arvon mukaan. Lookuptaulu-luokka kuvaa tällaista lookupkenttään liitettyä taulua. Lookuptaululle lähetetään tarkistuskyselyt, onko tietty kentän arvo sallittu ja siltä voidaan hakea käyttäjälle näytettäväksi lista kaikista kenttään mahdollisesti sijoitettavista arvoista, kuten kuvassa 5.4 .
VetoBox-sovelluspalvelin muodostaa peruskäytössä suoritettavat SQL-lauseet automaattisesti ilman, että niitä tarvitsee kirjoittaa erikseen ohjelmakoodiin. SQL-lauseiden muodostus suoritetaan määriteltyjen taulujen välisten yhteyksien ja Kentta-olioiden perusteella. Esimerkiksi client-sovelluksen hakiessa tiettyä taulun arvoa, se antaa alustaHaku()-metodille parametrina listan, mitä hakukriteerejä eri kentille on asetettu. Tämän perusteella sovelluspalvelin rakentaa tarvittavan SQL-lauseen ja suorittaa sen. Metodin onnistuttua client voi annaSeuraaviaRiveja()-kutsuilla pyytää halutun määrän tulosjoukon rivejä.
Järjestelmän käyttäjät on listattu yhdessä taulussa. Siihen liittyvään alatauluun on kiinnitetty tieto käyttäjälle sallituista sovelluksista ja niiden käyttöoikeuksista. Sovelluksen käsitteellä ei ole suoranaista merkitystä sovelluspalvelimen puolella (muuten, kuin että jokaista avattua sovellusta kohden avataan uusi sessio). Pikemminkin tietyn sovelluksen käyttöoikeus tarkoittaa oikeutta käyttää tiettyä käyttöliittymää kannan tietojen hallitsemisessa. Sen sijaan jokaiselle TauluRakenne-luokalle määritellään oikeustasot, jotka tarvitaan, että vastaavan Taulu-instanssin tietoja voisi selata, muuttaa ja poistaa. Lisäksi voidaan määritellä erityisiä tiettyyn käyttäjään liittyviä käyttöehtoja, joilla voidaan esim. säädellä, saako käyttäjä käyttää tiettyä yksittäistä toimintoa. Tämä käyttöehto voi olla ns. rivikohtainen rajoitusehto, millä voidaan rajoittaa ettei käyttäjä pääse näkemään kuin tiettyjä taulun rivejä. Sovelluspalvelin nimittäin lisää ao. rivikohtaisen rajoitusehdon taulua koskevien SELECT-lauseiden WHERE-osaan.
Sovelluspalvelimen tehtävänä on myös hoitaa rivien lukitukset. Eli jos joku käyttäjä on aloittanut taulun jonkun tietueen muuttamisen, muut käyttäjät eivät pääse sitä muuttamaan niin kauan kuin lukitus on voimassa. Samoin sovelluspalvelin vastaa yksikäsitteisten avainten arvojen määrittämisestä.
Jos tietokantaan ei ole määritelty tai ei voida määritellä esim. FOREIGN KEY -rajauksia, sovelluspalvelin kykenee hoitamaan ne. Perittyihin Taulu-luokkiin voidaan toteuttaa myös sovelluskohtaisia laskenta-algoritmejä, joissa voidaan suorittaa tapauskohtaisia kiinteitä SQL-lauseita.
Jokainen sovelluspalvelimessa suoritettava SQL-lause annetaan yleiselle tarkistusfunktiolle. Tämä funktio voi esimerkiksi lisätä kaikkiin lauseisiin ylimääräisiä rivikohtaisia rajoitusehtoja. Näin on mahdollista rakentaa luotettavasti järjestely, jossa useat eri yritykset kykenevät käyttämään samaan aikaan samaa tietokantaa ja sovelluspalvelinta ilman, että mitenkään huomaavat toistensa olemassaoloa.
Sovelluksien käytön valvomiseksi voidaan sovelluspalvelimessa rajoittaa sovelluksien käyttöoikeus tiettyihin IP-osoitteisiin. Lisäksi jokainen sovelluksen käynnistyskerta ja käynnistysyritys voidaan tallettaa tietokantaan.
Kehitysvaiheessa on tärkeää, että voidaan selvittää, mitä sovelluspalvelimessa tapahtuu ja monitoroida sen tiloja. Tätä varten sovelluspalvelimeen kuuluu yksinkertainen tekstikäyttöliittymä, jolla voidaan selvittää esim. tällä hetkellä auki olevat sessiot ja lukitukset. Samoin voidaan valita sovelluspalvelimen käyttämä debuggaustaso. Sopivalla tasolla on mahdollista tulostaa näytölle esim. ilmoitukset suoritettavista palveluista tai kaikki sovelluspalvelimen suorittamat SQL-lauseet.
Lyhyt kuvaus sovelluspalvelimen rajapinnasta client-osiin päin on tämän diplomityön liitteenä A .
Proslassa erilaisia tauluja on kannassa n. 30-40 kappaletta. Jokaista taulua varten tarvitaan kaksi luokkaa, taulun rakennemäärittelyn sisältävä luokka ja sessiokohtainen luokka, jotka periytyvät komponenttikirjaston luokista. Luokkien sisällöt ovat perustapauksissa varsin yksinkertaisia, koska tavallisten haku, lisäys, poisto, talletus, lukitus, ym. operaatioiden logiikka on toteutettu kokonaisuudessaan peruskomponenteissa. Rakennemäärittelyluokka koostuu lähes yksinomaan constructorista, jossa on määritelty taulun yhteydet muihin tauluihin ja luotu kenttäoliot. Taulun sessiokohtainen luokka koostuu perustapauksessa muutamasta rivistä, joilla luodaan tauluun liittyvien muiden taulujen instanssit.
Keskeisimpiin tauluihin liittyy taulukohtaisia erikoislaskenta-algoritmejä, jotka on toteutettu taulun sessiokohtaiseen luokkaan. Lisäksi niihin on toteutettu käyttöliittymän vaatimia erikoispalveluja. Tällainen on esimerkiksi sovelluspalvelu, jota käytetään, kun lisätään uutta tunti-ilmoitusta ja halutaan, että sovellus automaattisesti hakee edellisten ilmoitusten projektit pohjaksi.
Eri koneilla olevien sovellusten välistä tehokasta viestintää varten on tarpeen luoda rajapinnat, joiden avulla ne voivat kommunikoida keskenään kutsumalla tavallisia funktioita [1] . Ensimmäisiä eri koneilla olevien sovellusten väliseen kommunikointiin kehitettyjä protokollia oli SUN:in verkkolevyjärjestelmää (NFS) varten kehittämä RPC [9] . Käytännössä rajapintoihin liittyvät luokat, jotka muuttavat client-pään metodikutsut tietoliikenneprotokollan merkkijonoiksi ja serveri-puolella merkkijonot takaisin metodikutsuiksi [5] .
Tänä päivänä sovelluspalvelimen ja eri client-osien keskinäinen kommunikointi voidaan toteuttaa hyvin monella eri tavalla. Osien sijaitessa samalla koneella tulee niiden välisen kommunikoinnin olla mahdollisimman nopeaa. Käytettäessä client-sovellusta julkisen Internetin yli satunnaisesta työpisteestä tarvitaan vahvaa salausta. Kolmannen osapuolen tekemille sovelluksille tulisi myös olla mahdollista ottaa yhteyttä sovelluspalvelimeen. Joustavuuden lisäämiseksi olisi suotavaa olla mahdollisuus kommunikointiin sovelluspalvelimen kanssa toisella ohjelmointikielellä tehdyllä ohjelmalla.
Näistä syistä sovelluspalvelimen ja client-osien välinen kommunikointi tulee toteuttaa siten, että on helppoa vaihtaa käytettyä kommunikointitapaa. Käytännössä tämä tarkoittaa, että kummassakaan osassa ei saa suoraan viitata tietoliikenneluokkiin vaan ainostaan kuorikerroksen rajapintoihin.
Käytännössä HTML-raportointipalvelin ja HTML-käyttöliittymäpalvelin on usein tarkoituksenmukaisinta sijoittaa samalle koneelle sovelluspalvelimen kanssa. Tällöin on tehokkainta, että oliot sijaitsevat samassa prosessissa. Niinpä näissä tapauksissa käytettävät tietoliikenneluokat kutsuvat välikerroksen jälkeen suoraan sovelluspalvelimen metodeja.
Sovelluspalvelimen ja client-sovellusten välinen kommunikointi toteutettiin aluksi RMI:llä [4] , koska se tuli Java:n mukana valmiina ja oli nopeasti käyttöönotettavissa. RMI:n toiminnassa on kuitenkin ongelmia. Salauksen toteuttaminen siihen on mahdollista vain tietyillä JDK:n versioilla. RMI:n käyttäminen muista ohjelmointikielistä ei ole mahdollista. Lisäksi sen käyttämiseen tarvittaan erillisen \texttt{RMIRegistry}-prosessi, mikä mutkistaa asennustyötä. Siksi toteutettiin myöhemmässä vaiheessa kommunikointia varten oma, suoraan TCP/IP:n [9] päällä toimiva protokolla, nimeltään VetoRPC.
Tietoliikenneyhteys voitaisiin toteuttaa myös CORBA:n [10] avulla, mutta se on tarpeettoman raskas protokolla. Haluttaessa sovelluspalveelimeen on mahdollista lisätä CORBA-yhteys kohtuullisella työllä, koska sovelluspalvelin ei viittaa suoraan varsinaisiin tietoliikenneluokkiin.
Uudempi ja RMI:n tapaan Javalle luontainen vaihtoehto kommunikoinnin toteuttamiseen ovat ns. Java 2 Enterprise Edition -menetelmät [11] , mutta ne eivät olleet käyttöönotettavissa projektin alkaessa. toteutusta. Sovelluspalvelimeen on mahdollista rakentaa J2EE-yhteys tulevaisuudessa jos tarvetta ilmenee.
Muita vaihtoehtoja kommunikoinnin toteuttamiseen ovat uudehko protokolla SOAP ja Microsoftin kehittämä DCOM. Jälkimmäinen tuskin toimii kunnolla muilla kuin Microsoftin käyttöjärjestelmillä.
VetoRPC -prokollan serveri toimii HTTP-serverin [12] tapaan eli jokaista palvelupyyntöä varten avataan uusi TCP/IP-yhteys. Toiminta olisi hieman nopeampaa, jos TCP/IP -yhteydet pysyisivät auki, mutta näin sovelluspalvelin ei tarvitse omaa säiettä kutakin client-sovellusta kohti, vaan säikeitä tarvitaan ainoastaan yhtä monta kuin sovelluspalvelimella on samanaikaisesti suoritettavia pyyntöjä. Säikeiden määrän pitäminen vähäisenä on oleellista, koska esim. Linux:ssa JVM:n jokainen Java-säie kuvautuu useinmiten (ns. natiiveja säikeitä käytettäessä) suoraan käyttöjärjestelmän säikeeksi (prosessiksi). Käyttöjärjestelmän prosessien määrä taas on rajoitettu oletusarvoisesti n. 500 säikeeseen. Tätä määrää on mahdollista kasvattaa kääntämällä kernelistä korjattu versio, jossa vakion arvoa on muutettu. Mutta valtava käyttöjärjestelmän säikeiden määrä johtaa tehottomuuteen, sillä suoritettavan prosessin vaihtamisen vaatima 'hukkaprosessoriaika' kasvaa. [13]
Jokaiselle palvelupyynnölle avattavan uuden TCP/IP-yhteyden haittapuolena on myös, ettei sovelluspalvelin pysty lähettämään oma-aloitteisesti viestejä client:lle. Tätä varten client avaa käynnistysvaiheessa oman TCP/IP-yhteyden sovelluspalvelimelta clientille tapahtuvaa liikennettä varten. Tämä yhteys pysyy jatkuvasti auki, eikä liikenne toiseen suuntaan ole mahdollista. Nimittäin sovelluspalvelin ei kuuntele kanavaa, vaan ainoastaan säilöö avatut yhteydet tietorakenteeseen, josta voi tarvittaessa hakea tietyn client:in yhteyden. Tällä tavalla sovelluspalvelin tarvitsee ainoastaan yhden säikeen uusien kanavien avauksien kuuntelua varten. Koska client avaa tämän kanavan sovelluspalvelimelle, niin välissä mahdollisesti olevat palomuurit eivät pääse haittaamaan liikennöintiä.
Sovelluspalvelin ja client käyttävät kaikilla kanavilla yhteistä luokkaa instanssi-viittausten, metodinimien ja parametrien muuttamiseen TCP/IP-yhteyttä pitkin kulkeviksi merkkijonoiksi. Samoin kaikilla kanavilla käytetään yhteisiä luokkia salauksen toteuttamiseen. Salaus on toteutettu samaan tapaan kuin SSH-protokollassa [14] , missä käytetään julkisen avaimen salauksen (RSA) [15] ja symmetrisen salauksen (Blowfish) [15] yhdistelmää. Sovelluspalvelimella on oma julkinen-salainen avainpari, jonka julkinen avain lähetetään client:lle sen avatessa VetoRPC-yhteyttä. Client on tallettanut aiemmin lähetetyn julkisen avaimen kovalevylle ja näyttää käyttäjälle varoituksen, jos avain on muuttunut. Kun julkinen avain on hyväksytty, client generoi jatkossa käytettävän symmetrisen Blowfish-avaimen ja lähettää sen sovelluspalvelimelle salattuna julkisella RSA-avaimella.
Tarkempi kuvaus VetoRPC-protokollan toiminnasta on tämän diplomityön liitteenä B .
Useimpia tämän päivän sovelluksia käytetään graafisella käyttöliittymällä, joka koostuu ikkunoista, menuista, osoittimista ja erilaisista ikkunoihin sijoitettavista käyttöliittymäelementeistä, kuten painonapeista, kentistä ja taulukoista. Graafisille käyttöliittymille asetetaan paljon vaatimuksia käytettävyyden suhteen [16] . Näitä ovat mm. seuraavat:
Kaikkien toimintojen tulee olla näkyvissä ja käyttäjän tulee nähdä järjestelmän sisäinen tila.
Ohjelman tulee antaa käyttäjälle nopeaa palautetta.
Uuden käyttöliittymän tulee olla nopeasti opittavissa. Tämän takia eri käyttöliittymien tulee käyttäytyä samankaltaisesti.
Toisaalta ohjelmaa tulee voida käyttää tehokkaasti myös, kun käyttäjä on tottunut sen käyttöön ja tietää täsmälleen mitä on tekemässä.
Käytön tulee olla joustavaa: Käyttäjällä tulee olla mahdollisuus tehdä asiat haluamassaan järjestyksessä ja jopa samanaikaisesti. Eri tehtäviä täytyy voida joustavasti siirtää käyttäjältä toiselle.
Toimenpiteet täytyy voida perua.
Hyvien virheilmoitusten sijasta tulisi estää käyttäjää tekemästä virheellisiä toimenpiteitä. Kussakin tilanteessa ainoastaan järkevät toimenpiteet olisivat mahdollisia.
Käyttöliittymän pitäisi olla esteettisesti hyvännäköinen.
Ohjelman tulisi olla muokattavissa ja täyttää käyttäjän tarpeet (myös ne, joita ei osattu aavistaa järjestelmää tilattaessa).
Nämä vaatimukset ovat melko vaativia toteuttaa ja yhdessä ne johtavat usein varsin monimutkaiseen ohjelmaan, jossa on paljon edestakaisin olevia viittauksia. Tällöin lopputuloksesta saattaa tulla kallis ja epäluotettava. Ohjelmiston ylläpito saattaa muodostua hyvin vaikeaksi koodin määrän, monimutkaisuuden ja lukuisten samanaikaisesti huomioitavien seikkojen takia.
Toimintojen ja ohjelman sisäisen tilan näkyvyysvaatimukset sekä nopea palaute toiminnoista lisäävät tehtävien asioiden määrää, vaikkeivät muutoin kovin paljon monimutkaista ohjelman rakennetta. Tarve ohjelman nopeaan opittavuuteen ja päivittäisessä käytössä tärkeäksi nouseva mahdollisuus tehokäyttöön saattavat johtaa ristiriitoihin.
Erityisesti käyttäjän vapaus tehdä asioita missä järjestyksessä tahansa, kaikenkattava perumismahdollisuus ja virheellisten toimintojen esto ennakolta johtavat ohjelman rakenteelliseen monimutkaistumiseen. Jotta virheelliset toiminnot voidaan estää, täytyy jokaisen toiminnon yhteydessä säätää uudelleen kaikkien muiden toimintojen valintamahdollisuuksia. Tämä johtaa helposti ohjelmakoodiin, jossa on hyvin paljon viittauksia edestakaisin ja jossa 'kaikki vaikuttaa kaikkeen'. Sellainen koodi on virhealtista ja hankalasti ylläpidettävää. Lisäksi ohjelmiston testaus käy hyvin vaikeaksi, koska kaikkia toimintopolkuja ei ole mahdollista käydä läpi. Siten lopputuotteeseen saattaa helposti jäädä virheitä.
Tarve täyttää käyttäjän tarpeet, joita käyttäjä ei osannut tuoda esiin järjestelmää tilattaessa, vaatii vankkaa kokemusta samantyyppisten ohjelmistojen tekemisestä. Lisäksi tarvitaan paljon kokemusta ja näkemystä siitä, minkälaisia tarpeita käyttäjillä yleensä on tai saattaa ilmetä.
Graafisen ulkonäön tekeminen ei ole vaikeaa valmiina saatavien monipuolisten käyttöliittymäelementtikokoelmien ansiosta [16] . Näitä kokoelmia voidaan hyödyntää monilla eri tavoilla. Eräs suosituimmista tavoista tänä päivänä on käyttää jotain sovelluskehitysympäristöä eli IDE:tä, johon kuuluu eräänlainen käyttöliittymän piirto-ohjelma, jolla voidaan sijoitta käyttöliittymäolioita kuten nappeja ja kenttiä lomakkeelle [17] . Kehitysympäristö generoi piirroksista ohjelmakoodia. Tällaisia ohjelmia ovat esim. Delphi, Visual Basic, SQLWindows ja C++Builder. Ennen käyttöliittymien piirto-ohjelmien ilmestymistä vallitsevana tapana oli sijoittaa käyttöliittymän elementit lomakkeelle pikselikoordinaattien avulla, mikä oli varsin työlästä.
Java-kielessä on hieman toisenlainen lähestymistapa GUI-olioiden sijoitteluun lomakkeelle. Niitä ei (yleensä) sijoiteta suoraan tiettyihin pikseli-koordinaatteihin vaan sijoittelu annetaan ns. layout managerien tehtäväksi. Layout manager vastaa sitten olioiden sijoittelusta.
Koodia generoivien käyttöliittymän piirto-ohjelmien haittapuolina on mm. että luotu koodi on huonolaatuista ja hankalaa lukea, lomakkeiden muuttaminen dynaamisesti on vaikeaa eikä lomakkeita voi periyttää toisista lomakkeista normaalin olioajattelun mukaisesti. Lisäksi käyttöliittymien piirtäminen joka kerta alusta asti uudelleen tarkoittaa turhaa työtä, koska eri sovellusten käyttöliittymissä on usein paljon yhteistä. Käyttöliittymien piirtäminen saattaa pahentaa ohjelmien monimutkaisuutta, sillä piirtäminen helposti johtaa tilanteeseen, jossa kaikki tiettyyn ikkunaan liittyvä koodi on samassa tiedostossa. Tällöin ikkunaan liittyvä lähdekooditiedosto saattaa kasvaa hyvin suureksi ja siihen saattaa kertyä paljon vaikeasti hallittavia sisäisiä viittauksia.
Javalle on myös olemassa IDE-työkaluja olioiden sijoittelemiseen lomakkeelle, mutta ne ovat melko kömpelöitä ja raskaita. Ennenkaikkea käyttöliittymien piirtäminen ei mahdollista eri käyttöliittymien yhteisten ominaisuuksien tehokasta hyödyntämistä. Näistä syistä VetoBox-menetelmässä graafinen käyttöliittymä kehitetään puhtaasti JDK-pohjalta ilman koodia generoivia IDE-ympäristöjä.
Käyttöliittymien tekemistä on tehostettu niiden puoliautomaattisella generoinnilla sovelluspalvelimen TauluRakenne-olioiden rakenteellisen informaation perusteella. Puoliautomaattisesti generoituun käyttöliittymään on mahdollista liittää tarkasti määriteltyjä osia. Lisäksi on mahdollista periyttää lomakkeita toisistaan.
Puoliautomaattisesti generoituvat käyttöliittymät ovat ulkonäöltään ja toiminnoiltaan hyvin samankaltaisia. Tämä parantaa myös järjestelmien käytettävyyttä, sillä uudet käyttöliittymät ovat nopeammin opittavissa edellisten pohjalta. Myös ohjelmien luotettavuus paranee, kun samaa asiaa ei toteuteta useampaan kertaan, sillä tällöin ei tulla toistaneeksi samoja virheitä uudelleen.
Java-kielessä voi käyttöliittymiä toteuttaa joko AWT:n tai SWING:in avulla. Näistä AWT nojaa käyttöliittymäelementtien toteutuksessa takana olevan selaimen tai käyttöjärjestelmän elementteihin ja on valikoimaltaan huomattavasti suppeampi. SWING:ssä myös käyttöliittymäkomponenttien piirtäminen on toteutettu Java:lla. Projektissa lähdettiin heti alussa liikkeelle SWING:llä, koska sen komponenttivalikoima vastaa laajuudeltaan perinteisiä raskaita käyttöliittymäkomponenttikirjastoja.
Kuva 5.1: Yleinen käyttöliittymämalli, hakusivu.
Esimerkkinä sovellusten yleisestä käyttöliittymämallista on kuvassa 5.1 oleva Proslan kustannuslajitietojen hallintaikkuna Perustieto-sovelluksesta. Käyttöliittymän ulkonäköä ja perustoimintojen merkitystä käyttäjän kannalta ei ole kehitetty tämän diplomityön puitteissa. Yleisen käyttöliittymämallin ulkonäkö on kopioitu melko suoraan aiemmin tehdyistä Delphi-sovelluksista. Yksityiskohdissa käytettävyyttä on pyritty parantamaan. Esim. toimintojen näkyvyyttä on parannettu lisäämällä ylärivin nappeihin kuvien lisäksi nimet.
Käyttöliittymäikkuna koostuu menuista, nappirivistä ja kortistomaisista sivuista, joista vain yksi on näkyvillä kerrallaan. Näistä kortistosivuista käytetään nimitystä tab-sivu. Paaikkuna-luokka kuvaa koko ikkunaa. Myös jokainen tab-sivu on oma luokkansa.
Kuvassa 5.1 olevaa ensimmäistä Selaus-tabsivua vastaa Hakusivu-luokka. Sen käyttöliittymä generoidaan periaatteessa kokonaisuudessaan vastaavan sovelluspalvelimen TauluRakenne-olion perusteella. Hakusivun vasempaan puoliskoon käyttäjä voi kirjoittaa totuusarvologiikan mukaisia hakuehtoja. Niiden tulkinta ja muunnos sopivaksi SQL-lauseen WHERE-osaksi suoritetaan sovelluspalvelimen puolella. Clientin tehtävänä on kertoa, mitä arvoja eri kenttiin on kirjoitettu. Hakusivun oikeaan puoliskoon tulevat haun tulokset.
Muut tab-sivut periytyvät Tietosivu-luokasta. Sovelluskohtaisesti voidaan valita periytetäänkö sovelluksen lomakesivu AutomaattiTietosivu-luokasta, joka osaa sijoitella kentät ja alataulut lomakkeelle automaattisesti, vaiko PiirtoTietosivu-luokasta, jolloin sovelluskohtaisessa koodissa määritellään lomakkeen olioiden sijoittelut. Kuvassa 5.2 on Perustieto-sovelluksen automaattisesti generoitu hinnastotietojen muutoslomake. Tällä tavoin tehdyt lomakkeet ovat käyttökelpoisia erityisesti harvemmin käytettyjen taulujen tietojen muuttamisessa. Kuvassa 5.3 on eräs Tehtävä-sovelluksen lomake esimerkkinä sovelluskohtaisesti määritellystä lomakkeesta.
Kuva 5.2: Perustieto-sovelluksen hinnastotietojen päivityssivu. Lomake on peritty AutomaattiTietosivusta, joten kentät on sijoiteltu lomakkeelle heurististen sääntöjen mukaan. Sovellus on päivitystilassa.
Kuva 5.3: Tehtävä-sovelluksen 1. lomakesivu. Kenttien sijainnit on sovelluskohtaisesti määritelty. Sovellus on selailutilassa.
Siirryttäessä hakusivulta tietosivulle haetaan lomakkeen tiedot sovelluspalvelimen haeRivi()-metodilla. Toiminnossa käytetään erillistä hakua, koska hakusivun päähaku pyritään pitämään suhteellisen yksinkertaisena, jotta se olisi mahdollisimman nopea ja jottei tällöin tarvittaisi kovin monia hakua hidastavia taulujen välisiä liitoksia. Sen sijaan haeRivi()-operaatiossa, jonka tulosjoukkona on vain yksi päätaulun rivi, voidaan hakea tietoja hyvinkin monista liitostauluista (joita vastaavat sovelluskohtaiset LookupTaulu ja LookupTauluRakenne -luokat sovelluspalvelimessa).
Hinnaston lomakkeella (kuva 5.2) näkyvän taulukon tiedot tulevat sovelluspalvelimen Alataulu-tyyppisestä luokasta. Hakusivun taulukko ja lomakkeella oleva taulukko tarvitsevat tuekseen TauluPuskuri-luokan, johon talletetaan sovelluspalvelimelta haetut rivit. Jos haettavia rivejä on enemmän kuin taulukkoelementtiin mahtuu näkyville, haetaan aluksi sovelluspalvelimelta vain näkyvät rivit ja lisää haetaan tarvittaessa myöhemmin, jos käyttäjä kelaa taulukkoelementtiä alaspäin.
Lomakkeilla näkyvistä '...' -napeista saa näkyviin tiettyyn kenttään liittyvän lookuptaulun tietojen haku- ja valintaikkunan, ns. lookupikkunan ( kuva 5.4 ). Isomman lookuptaulun ollessa kyseessä siinä voidaan hakea haluttua arvoa samaan tapaan kuin hakusivulla, pienemmällä taululla vasemmanpuoleinen hakukenttien osasto katoaa ja ikkunaan on sen avautuessa haettu kaikki arvot. Automaattisesti generoituva lookupikkuna toimii lähes kaikissa tapauksissa.
Kuva 5.4: Lookupikkuna.
Peruskäyttöliittymässä ikkunan yläreunassa näkyvät Hae, Lisää, Päivitä, Talleta, Peru ja Poista -napit. Hae-toiminto suorittaa hakusivun haun. Sitä varten käytetään kolmea sovelluspalvelimen palvelua: alustaHaku(), joka muodostaa ja suorittaa tarvittavan SQL-lauseen; rivejaTulosjoukossa(), joka erillisellä SQL-lauseella muodostaa arvion tulosjoukon koosta taulukon hissielementtiä varten ja annaSeuraaviaRiveja(), joka palauttaa pyydetyn määrän rivejä.
Useimmille ylärivin napeille on olemassa vastaavat sovelluspalvelimen palvelut. Käyttöliittymällä on kolme eri tilaa: haku, päivitys ja lisäys. Lisäys ja päivitys ovat mahdollisia hakutilassa. Talletus, poisto ja peruminen ovat mahdoolisia päivitystilassa ja lisäystilassa talletus ja peruminen. Myös sovelluspalvelimella on tiedossaan client-sovelluksen tila; näin sovelluspalvelin kykenee suojautumaan client:ien virheiltä. Käyttöliittymien tiloja kannattaa usein hallita yksinkertaisella tilakonemallilla [16] , niin tässäkin tapauksessa. Käyttäjä voi havaita ohjelman tilan siitä, mitkä napit ovat mahdollisia sekä kenttien värityksistä.
Sovelluspalvelimella on jokaiselle taululle määritelty käyttöoikeustasot, joilla eri operaatioita saa tehdä. Client-sovelluksen pitäisi näiden tasojen perusteella vastaavasti poistaa asianomaiset napit näkyvistä. Mutta vaikkei client-sovellus toimisi oikein, käyttöoikeusrajoituksia ei silti pystytä rikkomaan, sillä sovelluspalvelin ei hyväksy operaatiota ja antaa virheilmoituksen.
Erilliset haku- ja päivitystilat ovat olemassa sen takia, että painaessaan Päivitä-nappia käyttäjä ilmoittaa sovelluspalvelimella päivittävänsä kyseistä tietuetta, jolloin se merkitsee tietueen lukituksi, eli muut käyttäjät eivät pääse päivittämään ao. tietuetta. Lukitus toteutetaan puhtaasti sovelluspalvelimessa. Vasta talletusoperaatiossa käytetään tietokannan transaktioita; päätaulun ja siihen liittyvien alataulujen talletusten SQL-lauseet suoritetaan saman transaktion sisällä. Lisäystilassa ei lukitusrajoituksia käytön suhteen ole. Rivin yksikäsitteinen avain (ID) määritetään vasta talletusvaiheessa.
Tehokäyttäjiä varten tavallisiin lisäys- ja päivitysoperaatioihin on olemassa pikanäppäimet, jolloin kättä ei tarvitse välillä siirtää hiirelle pois näppäimistöltä. Lookupkenttien yhteydessä olevia ikkunoita ei välttämättä tarvitse käyttää; myös suoraan kenttään voi kirjoittaa arvon. Erikseen on olemassa 'Pikapäivitys' ja 'Pikalisäys' -tilat, jolloin ei tarvitse painaa erikseen Talleta-nappia lisättäessä uutta tietuetta tai siirryttäessä muuttamaan seuraavaa tietuetta. Nimittäin esim. 'Pikalisäys'-tilassa Lisää-nappi suorittaa tarvittaessa talletuksen ennen lisäystä. Lisäksi on olemassa työkaluja esim. kaikkien tulosjoukon tietueiden tietyn kentän muuttamiseen samalla kertaa.
Koska Prosla on tarkoitettu tuotteeksi, joka voidaan sovittaa useille eri yrityksille, on kaikkien työntekijöiden käyttämästä tuntikirjauslomakkeesta suunniteltu neljä eri versiota, joista voidaan valita ao. yritykselle sopiva. Päiväkohtaisessa versiossa ( kuva 5.5 ) työntekijät ilmoittavat tuntinsa päivittäin, eri päivät tulevat eri päätaulun tietueille. Jaksokohtaisessa versiossa ( kuva 5.6 ) eri päiviä voi ilmoittaa samassa alataulussa. Tuntikorttiversiossa ( kuva 5.7 ) ilmoitetaan alataulussa saman projektin eri päivien tunnit alataulun samalla rivillä. Edelleen puutuntikorttiversiossa ( kuva 5.8 ) tehtäviä voidaan hallita puumaisella käyttöliittymäelementillä.
Kuva 5.5: Päiväkohtainen työilmoitus.
Kuva 5.6: Jaksokohtainen työilmoitus.
Kuva 5.7: Tuntikorttimainen työilmoitus.
Kuva 5.8: Puutuntikorttiversio.
Lisäksi Proslan sovellukset Kulukirjaus ja Matkalasku ovat samantyyppisiä kuin työaikasyötöt, joten niissäkin voidaan hyödyntää muihin käyttöliittymiin kehitettyjä elementtejä. Nämä eri lomakeversiot on periytetty samasta luokasta siten, että kaikilla työilmoitus-versioilla on samat Paaikkuna ja Hakusivu -luokat (TyoilmoitusPaaikkuna ja TyoilmoitusHakusivu). Myös Kulukirjauksen ja Matkalaskun Paaikkuna ja Hakusivu on periytetty näistä luokista. Näiden eri sovellusten yhteisenä logiikkana on mm. ilmoitusten Avoin/Valmis/Hyväksytty -logiikan hallinta sekä työjaksoihin, henkilöihin ja tehtäviin liittyvät tarkistukset. Varsinaisten työilmoitussovellusten yhteisenä logiikkana on mm. tuntisummien ja normierotuksen laskenta.
Kaikkien eri versioiden lomakkeet on periytetty YleinenTyoilmoitusTietosivu-luokasta, kuten kuvasta 5.9 näkyy. Eri tuntikirjaus-sovellukset periytyvät TyoilmoitusTietosivu-luokasta. Lisäksi puukortti-version tietosivu periytyy tavallisesta tuntikortti-tietosivusta. YleinenTyoilmoitusTietosivu-luokassa on mm. tilalogiikkaa, oletusarvona viimeisimmän ilmoituksen hakulogiikkaa ja erilaisia tarkistuksia. TyoilmoitusTietosivu-luokassa on mm. eri versioiden yhteisten käyttöliittymäelementtien asettelut, edellisen ilmoituksen tehtävien hakulogiikkaa ja tuntikirjauksille yhteisiä tarkistuksia. Tuntikortti-luokassa on mm. päiväkohtaiseen muotoon talletettaessa tarvittavan ns. ristiviitemuunnoksen koodi. Puukortti-luokassa on lisäpiirteitä, joita tarvitaan puumaiseen esitykseen.
Kuva 5.9: Proslan työilmoitustyyppisten sovellusten tietosivujen periytymispuu.
Tuntikirjaus-sovellukset tarvitsevat perityn version taulukkoelementin välimuistina toimivasta TauluPuskuri-luokasta (mm. interaktiivista summien laskemista varten). Tästä YleinenTyoilmoitusPuskuri-luokasta periytyvät vastaavasti KulukirjausPuskuri, TyoilmoitusPuskuri, TuntiKorttiPuskuri ja PuuKorttiPuskuri.
Projektia käynnistettäessä Javan käyttöön houkutteli mahdollisuus toteuttaa client-sovellukset pelkkinä Java Applet:eina, joita ei tarvitsisi asentaa erikseen työasemiin. Tällöin uuden version päivittäminen ei olisi mikään ongelma, koska ohjelma joka tapauksessa ladattaisiin aina uudestaan verkon yli sovellusta käynnistettäessä.
Kuitenkin appleteilla on muutamia perusrajoituksia, mm. paikallisten tiedostojen käsittely on mahdotonta. Siksi käyttöliittymä rakennettiin siten, että on hyvin helppoa muuttaa valmis sovellus appletista applicationiksi tai päinvastoin. Applettina toimittaessa varsinaista käyttöliittymää ei piirretä selaimen sisään, vaan avataan erilliseen ikkunaan. Tämän erillisen ikkunan koodi voi olla täsmälleen sama sekä applet että application -versioissa. Vain käynnistysikkunasta tarvitaan erilliset versiot. Tämäkin muutos saatiin helpoksi toteuttamalla täsmälleen saman rajapinnan (IKaynnistaja) omaavat AppletKaynnistaja ja ApplicationKaynnistaja -luokat, joista jommastakummasta voidaan varsinaisen sovelluksen Kaynnistaja-luokka periä. Operaatio olisi ollut vielä siistimpi, jos Javassa olisi C++:n tapaan mahdollisuus moniperintään.
Projektin edetessä osoittautui, että selainten JVM:t ovat laadultaan melko epäluotettavia ja vanhentuneita. Esimerkiksi tälläkään hetkellä mihinkään varteenotettavaan selaimeen ei JDK 1.2:sta näytä olevan tulossa. Periaatteessa JDK 1.1 on riittävä ylläolevien kaltaisten GUI:den toteuttamiseksi, tällöin tosin joudutaan lataamaan aina sovellusta käynnistettäessä n. kahden megatavun kokoinen SWING-kirjasto, joka ei tule JDK 1.1:sen mukana. Ja vaikka tämä kirjastopaketti olisi valmiiksi ladattuna selaimen välimuistiin, osoittautui sovelluksen käynnistyminen applettina tarpeettoman hitaaksi.
Näistä syistä yleensä käytetyksi menetelmäksi tuli itsenäinen Java Application. Uuden version päivitysongelma ratkaistiin siten, että ensimmäisenä käynnistettävänä luokkana ei ole varsinaiseen sovellukseen kuuluva luokka, vaan Loader-erikoisluokka. Se tarkistaa alussa, onko sovelluksesta tullut uutta versiota saataville. Jos sellainen on olemassa, niin Loader päivittää uuden version automaattisesti ja pyytää käyttäjää käynnistämään sovelluksen uudestaan. Näin client-päähän tarvitsee suorittaa ainoastaan ensiasennus, uudet versiot eivät vaadi työasemakohtaista käsityötä. Ensiasennus täytyy suorittaa jokaiselle työasemalle, mutta koska client-puoli koostuu lähinnä muutamasta .jar-paketista ja JRE:stä, niin asennus koostuu vain yhdestä hakemistosta alihakemistoineen ja se voidaan pakata yhteen, tarvittaessa itsepurkautuvaan, pakettiin.
Ensimmäisiä laajalti käytettyjä tapoja toteuttaa HTML-käyttöliittymiä olivat ns. CGI/BIN -ohjelmat. Niiden ideana on, että tietyillä erikoisosoitteilla HTTP-palvelin ei hae tekstitiedostoa kovalevyltä vaan suorittaa tietyn ohjelman, jonka ns. 'standard output':iin tulostama teksti lähetetään selaimelle HTML-sivuna. Käytetyimpiä ohjelmointikieliä CGI/BIN -ohjelmien tekemiseen ovat olleet käännettävä C ja tulkattava Perl. Tämän tavan haittapuolena on se, että jokaista HTML-sivupyyntöä varten joudutaan suorittamaan verraten raskas operaatio (prosessin käynnistäminen). Lisäksi käytettäessä tietokantaa joudutaan tekemään toinen raskas ja hidas operaatio eli tietokantayhteyden avaaminen. Näistä operaatioista ei ole mitään hyötyä seuraavilla sivupyynnöillä.
Uudempi tapa toimia on integroida HTTP-palvelimen sisään moduuleja, jotka suorittavat sivupyyntöjä. Suosittuja tulkattavia kieliä näiden moduulien tekemiseen ovat PHP ja Python. Java:lla toimittaessa on kahdenkinlaisia rajapintoja moduuleilla: Servletit ja JSP (Java Server Pages). Lisäksi on olemassa myös Microsoft:in täysin oma ratkaisu, joka toimii vain Microsoft:in palvelimilla, nimeltään ASP (Active Server Pages). PHP:lle, JSP:lle ja ASP:lle on yhteistä, että niissä yhdistellään staattisia HTML-sivuja, niihin ympättyjä tageja ja ohjelmakoodia, mikä ohjelmointia osaamattomalle on helppo tapa lähteä liikkeelle. [18]
Tiettyyn dynaamiseen HTML-sivuun liittyvien HTML-koodin pätkien jakaminen eri tiedostoihin on tapa, joka isommissa järjestelmissä johtaa sekavaan ja vaikeasti hallittavaan kokonaisuuteen [18] . Servletit [19] eivät kärsi tästä jakautumisesta, mutta tällainen moduulien integrointi tavalliseen HTTP-palvelimeen on riippuvainen tietyn palvelimen ominaisuuksista; asennus olemassaolevaan palvelimeen vaatii useimmiten manuaalista työtä.
Mielestäni dynaamisten HTML-sivujen tiukka integrointi johonkin yleiseen HTTP-palvelimeen on tarpeetonta ja aiheuttaa asennusvaiheessa ylimääräistä työtä, sillä dynaamiset HTML-sivut voivat aivan hyvin tulla erillisestä, toisessa portissa pyörivästä, tarkoitukseen suunnitellusta HTTP-palvelimesta. Tällaisen palvelimen toteutus ei sinällään ole kovin iso urakka, sillä HTTP-protokolla on loppujen lopuksi melko yksinkertainen, koska se nojautuu hankalammissa asioissa ( yhteyksien avaus, pakettien perillemenon takaaminen, etc. ) TCP/IP:n tarjoamalle alustalle. Lisäksi tarvittavaa työtä vähensi se, että VetoRPC-protokollan TCP/IP-yhteyslogiikka on samanlainen kuin HTTP-protokollan; eri protokollien palvelimet periytyvät yhteisestä luokasta.
Perusongelma dynaamisen HTML-käyttöliittymän toteuttamisessa HTTP-protokollalla on, että protokolla on alunperin suunniteltu vain staattisten sivujen välitykseen. Client lähettää pyynnön tietystä sivuosoitteesta jonka palvelin palauttaa. Kuinka tällöin palvelin voi identifioida käyttäjän ja lähettää eri käyttäjille erilaisia sivuja? Usein käytetään ns. kekseihin (Cookies) [20] perustuvaa ratkaisua. Siinä palvelin lähettää selaimelle tietyn merkkijonon, jonka selain palauttaa hakiessaan palvelimelta uusia sivuja. Keksit eivät kuitenkaan ole välttämättömiä, sillä asian voi hoitaa pitämällä yllä tietorakennetta, johon on talletettu tiedot, mihin sivuihin kustakin käynnissä olevasta sovelluksestä pääsee. Tällöin sivujen nimet ovat esim. satunnaislukuja, jotka ovat yksikäsitteisiä kaikkien eri sessioiden mahdollisten sivujen joukossa. Käytetyn protokollan pitämiseksi mahdollisimman yksinkertaisena päädyin tähän jälkimmäiseen menettelytapaan.
Koska Java Applicationit tarjoavat monipuolisen, nopeasti rakennettavan, nopeasti asennettavan ja nopeasti päivitettävän käyttöliittymän, tarve ilman minkäänlaisia asennuksia käyttöönotettavalle, mutta vähemmän mahdollisuuksia tarjoavalle käyttöliittymälle on vähäisempi. HTML-käyttöliittymä ei puolusta paikkaansa hitaillakaan yhteyksillä, sillä todellisuudessa se on hitaampi kuin java-client. Jokaista operaatiota varten täytyy palvelimelta hakea kokonainen HTML-sivu kaikkinen käyttöliittymäelementteineen, kun raskaammalla Java Application:lla riittää pelkän datan siirtäminen.
Sen sijaan HTML-käyttöliittymä tarjoaa etuja, jos järjestelmällä on paljon satunnaisia käyttäjiä. Erityisesti, jos jonkun järjestelmän osan halutaan tarjoavan tietoa vapaasti julkisesti käytettäväksi tai laajan, satunnaisen käyttäjäjoukon täytyy kyetä syöttämään tietoa järjestelmään.
Proslassa tällainen tarve on lähinnä projektitasoa huomattavasti yksityiskohtaisemmalla 'työlista' tai 'bugilista' -tasolla. Näitä työlista-asioita hallinnoidaan normaalisti omalla sovelluksellaan. Toisinaan voi olla tarkoituksenmukaista tarjoa asiakkaille mahdollisuus nähdä projektin sisälle: kuinka pitkällä mikäkin asia on projektissa toteutettavana. Samoin saatetaan tarvita mahdollisuutta esimerkiksi tietyn ohjelmiston käyttäjille lähettää bugiraportteja suoraan ohjelmistoa ylläpitävän yrityksen tietojärjestelmään. Projektipäällikölle voi olla kätevää päästä lisäämään projektin työlistalle uusia kohtia samalla, kun hän on neuvottelussa asiakkaan luona. Tällöin parhaimmillaan yksinkertaisissa tapauksissa uusi ominaisuus voi olla toteutettuna ja valmiina käyttöönotettavaksi ennenkuin neuvottelu on päättynyt.
Näitä tarpeita varten on olemassa HTML-työlistasovellus. Sovelluksen käyttäjille voidaan rajoittaa näkymä vain tiettyyn projektiin. Hakusivulla (kuva 6.1) voi hakea yksityiskohtaisia töitä. Hakusivulta klikkaamalla tietyn työn linkkiä päästään lomakesivulle, missä nähdään tarkemmin työtehtävän tiedot (kuva 6.2). Sieltä voidaan oikeuksien riittäessä muokata olemassaolevaa työlistaelementtiä (jos se on tilassa Ehdotettu ja jos sovelluksen käyttäjä on sen alunperin lisännyt) tai lisätä samalle projektille Ehdotettu-tilassa oleva työ (kuva 6.3).
Kuva 6.1: HTML-työlistasovelluksen hakusivu.
Kuva 6.2: HTML-työlistasovelluksen lomakesivu.
Kuva 6.3: Uuden työn lisäys HTML-työlistasovelluksella.
Monissa järjestelmissä raportointi ja erityisesti asiakaskohtaisesti räätälöitävät raportit ovat osoittautuneet yllättävän hankaliksi ja kalliiksi toteuttaa. Vaikkakin yksittäisen raportin toteuttaminen on melko yksinkertaista ja rutiininomaisia työtä, se kuitenkin vaatii ohjelmointia ja suuren raporttijoukon hallinta on hankalaa. Tänä päivänä raportteja pitäisi pystyä siirtämään myös sähköisesti toisiin ohjelmiin ja järjestelmiin.
Peruslähtökohtana raportoinnissa oli, ettei tämän järjestelmän tarvitsisi varsinaisesti hoitaa paperille tulostusta, vaan raportit tehtäisiin HTML-sivuiksi, jotka käyttäjä voisi joko siirtää jonnekin muualle tai tulostaa selaimesta. Toisena periaatteena on, ettei raporttien tekeminen vaadi ohjelmointityötä: raportit tehdään erityisellä raporttieditorilla ja talletetaan asiakaskohtaisina tietokantaan.
Sittemmin on osoittautunut, että on olemassa tulostustarpeita, joissa HTML-pohjainen raportointi ei riitä, erityisesti tarrat ja laskulomakkeet ovat tällaisia. Näitä varten on kehitteillä graafinen raporttieditori, jolla voidaan tulostaa suoraan paperille ja toisaalta on kehitteillä liittymä, jolla voidaan Java-sovelluksesta lähettää data Delphillä ohjelmoidulle raportille.
HTML-raportoinnissa käytetään HTML-käyttöliittymäpalvelimen kanssa yhteisestä lähteestä perittyä HTTP-palvelinta. Raporttia varten muodostetaan oma tauluinstanssi, jolle suoritetaan haku samoilla ehdoilla kuin käyttöliittymän päähaku on suoritettu. Client:lle ilmoitetaan HTTP-osoite, josta raportin voi hakea ja hakupyynnön tullessa hakujoukosta muodostetaan raporttikohtaisilla säännöillä HTML-sivu.
Raporttieditorilla tehtyjen raporttien rakennemäärittelyt tallennetaan omaan tietokannan tauluun, josta niitä on mahdollista myöhemmin hakea. Lisäksi käyttäjä voi määritellä, mitkä raportit näkyvät milläkin oikeustasolla sovelluksen perus-menuvalikossa.
Raporttieditorin käyttöliittymä on kuvassa 7.1. Siinä on raporttieditoriin ladattu kuvassa 7.2 tulostetun raportin määrittely. Perusideana editorissa on Java GridbagLayout eli HTML:n TABLE-elementti eli taulukkolaskennan ruudukko: jokainen raportilla tulostettava kenttä tai muu elementti sijoitetaan tiettyyn taulukon soluun. Jos kenttä on pitkä, se voi viedä leveyssuunnassa useamman solun paikan. Eri alueet tulostetaan raportilla omiin kohtiinsa, esimerkiksi Raportin otsikko tulostetaan raportin alkuun ja Sisältö-osa kerran jokaista tulosjoukon riviä kohti. Raporttieditorissa on lisäksi monipuolinen kokoelma erilaisia osioita ja soluihin sijoitettavia funktioita.
Kuva 7.1: Raporttieditori.
Kuva 7.2: Selaimeen haettu HTML-raportti.
Tulostettaessa HTML-raporttia sivutus muodostaa ongelman, koska alkuperäisessä HTML-määrittelyssä ei ole ollut sivun käsitettä. Sen sijaan uudemmassa CSS 2.0 -standardissa ymmärretään erikseen 'sivullinen media' sekä voidaan määritellä sivunvaihto tiettyjen elementtien jälkeen.
HTML-raporttien tapauksessa raporttieditori toimii client-puolella, mutta varsinainen raportin HTML:ksi muodostuslogiikka on sovelluspalvelimen puolella samoin kuin HTTP-palvelin, jolta raportin voi hakea.
Perinteisten graafisten käyttöliittymien yhteydessä suora tulostus paperille on vaatinut raportin 'piirtämistä' graafisilla piirtokäskyillä 2-ulotteiselle tasolle. Lopputuloksena on aikaansaatu näyttäviä raportteja, mutta niiden tekeminen ohjelmallisesti on työlästä. Tästä syystä suoraa paperitulostusta varten on kehitteillä oma graafinen raporttieditorinsa.
Graafisessa raporttieditorissa käyttäjä siirtää hiirellä eri raporttielementit haluamiinsa koordinaatteihin. Hiiren liikkuminen tulostettavalla alueella on 'kvantisoitu' eli rajoitettu siten, että koordinaattiarvot ainoastaan esim. viiden pikselin välein ovat mahdollisia. Näin on mahdollista saada melko nopeasti aikaan täsmällisen suoria sivuja.
Tulostaminen graafisessa editorissa tapahtuu käyttäen samoja piirtokäskyjä kuin varsinainen tulostus paperillekin; molemmissa operaatioissa käytetään hyväksi Java 2D API:a. Siten lähes kaikki graafiseen tulostamiseen liittyvä logiikka sijaitsee client-puolella. Graafiset raportit talletetaan HTML-raporttien tapaan tietokantaan. Graafisen raportin tulostuksessa sovelluspalvelimen tehtäviksi jää raporttin rakennemäärittelyn hakeminen kannasta sekä tulostuksessa käytettävän taulu-instanssin luominen.
Käytetty monitasoarkkitehtuuri mahdollistaisi hyvin erilaisten, mutta yhteensopivalla tavalla toimivien käyttöliittymien rakentamisen järjestelmään. Proslan tapauksessa tosin on toistaiseksi esiintynyt välitöntä tarvetta muutamalle eri tyyppiselle käyttöliittymälle: raskaalle Java Applicationina toteutettavalle GUI:lle, HTML-raportoinnille, graafiselle tulostukselle ja HTML-käyttöliittymälle. Tässä luvussa käsitellään muita, matkan varrella syntyneitä ideoita erilaisista käyttöliittymistä, joita ei kuitenkaan vielä ole toteutettu.
Periytetyt käyttöliittymät tarjoavat tehokkaan tavan sovellusten tuottamiseen, mikäli eri sovellusten käyttöliittymillä on paljon yhteisiä ominaisuuksia ja ne toimivat samankaltaisen logiikan mukaan. Sen sijaan, jos sovellusten käyttöliittymät ovat hyvin erilaisia tai hyvin räätälöityjä, periytymisestä saattaa olla enemmän haittaa kuin hyötyä. Tällöin tehokkaimmaksi käyttöliittymän tekomenetelmäksi nousee 'drag & drop' eli käyttöliittymän tekeminen piirtämällä.
Eräs tehokkaimmista välineistä käyttöliittymän piirtämiseen on Borlandin Delphi -sovelluskehitin, joka pohjautuu Object Pascal -kieleen. Täysin räätälöidyn käyttöliittymän tekeminen Delphillä on mielestäni tehokkaampaa kuin esim. saman firman JBuilder -kehittimellä. Jos siis tarkoituksena on tehdä räätälöityjä käyttöliittymiä, miksi tyytyä vähemmän tehokkaaseen kieleen? Varsinkin, kun Delphistä alkaa olla saatavilla versioita eri käyttöjärjestelmille.
Delphi-sovellukset vain pitäisi saada toimimaan yhteensopivasti muiden sovelluspalvelinta käyttävien sovellusten kanssa. Tietoliikenneyhteyden saisi toimimaan melko suoraviivaisesti kääntämällä VetoRPC-protokollan tarvitsemat luokat Java:sta Delphi:lle. Jotta sovelluspalvelinta käyttäviä tietokantakäyttöliittymiä voitaisiin tehokkaasti rakentaa 'delphimäisellä' tavalla, voitaisiin periä oma versio Delphin TDataSource-komponentista, joka käyttäisikin käännettyjä tietoliikenneluokkia yhteyden luomiseen sovelluspalvelimeen tavallisen Delphi-tietokantayhteyden sijasta.
Tulkattavan Java:n tehottomuus herättää toisinaan epäilyksiä, onko Java:lla tehty järjestelmä riittävän tehokas vaativassa käytössä. Käytännössä on osoittautunut, ettei Javalla tehdyn ja perinteisen käännetyn käyttöliittymän suorituskyvyssä tai graafisten elementtien piirtonopeudessa ole silmin havaittavaa tai sekuntikellolla mitattavissa olevaa eroa. Toistaiseksi Java siis on vaikuttanut riittävän tehokkaalta, mutta vaihtoehtojakin on mietitty. Lupaavimmalta sellaiselta vaikuttaa C++:n ja QT-käyttöliittymäkomponenttikirjaston yhdistelmä.
Java:n tapaan C++ on oliopohjainen kieli, josta löytyvät samat ominaisuudet kuin Java:stakin. C++:ssa on lisäksi joitain hyödyllisiä ominaisuuksia, jotka Java:sta puuttuvat, kuten moniperintä. Koska Java on jossain määrin kehitetty C:n ja C++:n pohjalta, saattaisi sovelluspalvelimen tai client-puolen kääntäminen C++:lle olla melko suoraviivainen operaatio.
Käyttöjärjestelmäriippumaton olioajatteluun vahvasti tukeutuva QT-kirjasto on monissa kohdin Swing-kirjaston kaltainen. Siinä käytetään samantapaisia käsitteitä, kuten layout-managerit, Look & Feel:it ja elementtien laajentaminen perimällä. QT:n tarjoaa myös hieman Java:n kaltaisen säikeidenkäsittelymahdollisuuden.
Toisaalta myös Javaa tietyn prosessori- ja käyttöjärjestelmäalustan natiiviksi konekieleksi kääntävien kääntäjien kehitys kulkee jatkuvasti eteenpäin, joten voi olla ettei tehokkuussyistäkään C++:n käyttöön siirtyminen ole enää tarpeellista.
Ylivoimaisesti suurin osa käyttöliittymän kehitystyöstä on mennyt graafisen Java-käyttöliittymän kehittämiseen. Toisaalta on olemassa monia muita tahoja, jotka kehittävät pääosin HTML-pohjaisia käyttöliittymiä hieman samantapaisella arkkitehtuurilla. Eli mallilla, jossa tietokannan käsittelylogiikka ja käyttöliittymän muodostuslogiikka on sen verran selkeästi erotettu toisistaan, että niiden sijoittaminen eri koneille olisi mahdollista.
Esimerkiksi melko suosittua on tehdä samantapaisella arkkitehtuurilla HTML-käyttöliittymiä PHP:lla tai Perlillä [2] . Siten saattaisi olla hyödyllistä kehittää esim. SOAP-protokollaa käyttävä yhteyskanava, jolla tarjottaisiin mahdollisuus kehitysvaiheessa vielä tuntemattomille tahoille tehdä omia käyttöliittymiään samaan sovelluspalvelimeen.
Laajalti levinneiden kännyköiden sulkeutuneisuus tekee hyvin hankalaksi niiden hyödyntämisen yritysten operatiivisten järjestelmien 'mobiili-päätteinä'. Vaikkakin tavallinen GSM-kännykkä sisältää paljon ohjelmistoja, niiden muuttaminen omiin tarpeisiin ei ole mahdollista.
Saattaa olla, että tulevaisuudessa kännyköihin voi ladata omia Java-ohjelmiaan, mutta sitä odotellessa ovat WAP ja SMS ainoat vaihtoehdot tietojärjestelmien käyttämiseen kännyköiden kautta. Monipuolisempi vaihtoehto on aina soittaa kännykällä toimistolle (tai lähettää kysely tekstiviestinä), jossa hyvien yhteyksien ja päätteen ääressä oleva henkilö voi selvittää tarvittavan tiedon.
Käytännössä vaihtoehtoja WAP tai SMS liittymän tekemiseen voisivat olla esim. Nokia Data Suiten korvaavan open source -työkalun modifiointi omiin tarpeisiin, open source WAP/SMS -gateway tai WAP/SMS reitityspalvelun ostaminen. Oman WAP-gatewayn hankkiminen taitaa käytännössä olla liian kallis vaihtoehto. Esim. WAP/SMS reitityspalvelua käyttämällä viestit välittyisivät TCP/IP-pohjaisella protokollalla reitityspalveluntarjoajan koneelta yrityksen omaan järjestelmään.
Hyvä käytettävyys edellyttää ohjelmiston sopimista täsmälleen käyttäjän tarpeisiin [16] . Toisaalta myös katsotaan, että laadukas tuote täyttää asiakkaan tarpeet [21] . Asiakkaiden tarpeiden ollessa aina hieman erilaisia, muodostuvat tuotteen asiakaskohtaiset sovitusmahdollisuudet tärkeiksi tuotteen laadun ja käytettävyyden kannalta. Ohjelmiston muokkausmahdollisuudet nopeuttavat myös järjestelmän opettelua ja hyväksyntää organisaatiossa, jos ohjelman käyttämät käsitteet voidaan vaihtaa sellaisiksi, joihin asiakas on tottunut.
Pyrkimys kustannusten alentamiseen jakamalla koodia eri asiakkaiden kesken ja toisaalta pyrkimys tarjota asiakkaille mahdollisuuksia tuotteiden tapauskohtaiseen räätälöintiin saattavat muodostaa hankalasti ratkaistavan yhdistelmän. Tavoitteena ohjelmistokomponenttien tekemisessä on pyrkiä siirtämään mahdollisimman paljon eri sovellusten yhteistä toiminnallisuutta yleiskomponentteihin, jolloin varsinaisen sovelluksen tekeminen alkaisi muistuttaa yhä enemmän valmiiden osien yhteensovittamista.
Tavoitteena on, että useimmat valmiit sovellukset muodostuisivat kuvan 9.1 mallin mukaisesta periytymispuusta. Ylimällä tasolla ovat käytetyn kielen (Javan) mukana tulevat standardikomponentit. Niistä on periytetty yleiskomponentit, joihin on pyritty sisällyttämään yleisesti tietyntyyppisellä käyttöliittymällä varustettujen tietokantasovellusten yhteiset osat. Tästä peritään edelleen tietyn sovellusalueen (kuten asiakasrekisteri tai laskutus) yhteiset ominaisuudet sisältävät luokat. Asiakkaalle toimitettava järjestelmä koostuu näistä periytetyistä räätälöidyistä komponenteista.
Kuva 9.1: Yleinen sovellusten osien periyttämismalli.
Samaan tietokantaan ja samaan sovelluspalvelimeen on mahdollista yhdistää eri asiakkaille eritavoin räätälöityjä sovelluksia. Tämä on mahdollista, koska sovelluspalvelin luo jokaista yritystä (YRITYSID:tä) varten oman instanssin TauluRakenne-tyypin luokista. Niinpä sovelluspalvelinta käynnistävissä metodeissa voidaan luoda eri yrityksille instanssit hieman eri tavoin perityistä luokista.
Vastaavasti client-puolella voidaan käynnistää YRITYSID:n mukaan eri tavoin peritty versio esim. Paaikkuna-luokasta. Sitä mikä versio mistäkin luokasta on näkyvillä milläkin yrityksellä, voitaisiin kontrolloida sopivalla tietokannan taululla ja siten olisi mahdollista vaihtaa räätälöintivaihtoehtoa 'lennosta' käynnistämättä sovelluspalvelinta uudestaan. Mutta tätä ominaisuutta ei ole vielä toteutettu.
Kuitenkin ohjelmointityötä edellyttävä viimeinen periyttämis- ja räätälöintivaihe saattaa toisinaan muodostua asiakkaalle liian suureksi kustannukseksi. Tällöin ohjelmaversion kustannuksia voidaan alentaa käyttämällä erilaisia parametrointimenetelmiä.
Omaan tietokannan tauluun voidaan varastoida muuttuja-tyyppisiä parametreja. Tällöin sovellus voi toimia eri tavalla, riippuen muuttujan arvosta. Näiden parametrien käyttö on rakennettu siten, että kaikki järjestelmän muuttuja-parametrit täytyy luetella tietyssä lähdekooditiedostossa. Tällä tavoin on helppoa päästä selville, millä kaikilla parametreilla järjestelmän toimintaa voi säätää.
Tietokannan taulujen kenttien nimistä on ohjelmaan varastoitu erikseen käyttäjälle näytettävät nimet ja ohjelman sisäisissä viittauksissa käytetyt nimet. Näin käyttäjän näkemät käsitteet voidaan tallettaa tietokannan tauluun ja niitä on mahdollista muuttaa muuttamatta ohjelman lähdekoodia.
Samoin usein käytetyissä pienissä tauluissa, joissa on arvoja, joilla säädellään ohjelman toimintaa, on olemassa erikseen sarake käyttäjälle näytettävästä arvosta ja ohjelman käyttämästä arvosta. Käytännössä tälläiset usein käytetyt pienet 'tyypittely' taulut on tietokantarakenteen yksinkertaistamiseksi yhdistetty samaan tauluun.
Raporttieditoreille tehtävät raportit talletetaan tietokannan tauluun ja ne ovat siinä mielessä helposti täysin asiakaskohtaisesti räätälöitävissä. Uudessa järjestelmässä voi olla pohjana joukko malliraportteja raporttitaulussa. Raportin käynnistäminen esim. jonkun massa-ajon päätteeksi vaatii silti räätälöintiä ohjelmaan.
Lisäksi järjestelmässä on mahdollisuus lisätä päätaululle dynaamisesti kenttiä muuttamatta ohjelmaa tai tietokantarakennetta. Näiden erittelykenttien perusteella voidaan hakea tietoja, mutta niitä ei voida listata hakusivun tulosjoukkotaulukossa. Todellisuudessa nämä erittelykentät sijaitsevat omassa taulussaan ja niiden näkyvyys- ja muotoilumääritykset ovat toisessa taulussa. Käyttäjälle ne kuitenkin näkyvät kuvan 9.2 tapaan dynaamisesti lisättävinä, 'tavallisenoloisina' lomakkeen kenttinä.
Kuva 9.2: Erittelyalue-komponentti.
Käyttäjän näkökulmasta tämä erittelyalue-komponentti toimii siten, että painettaessa erittelyalueen Lisää-nappia tulee näkyviin LookupIkkuna, jossa on lueteltu sivulle lisättävät mahdolliset erittelyt. Kun haluttu erittely on valittu, ohjelma piirtää lomakkeen uudestaan siten, että sinne on ilmestynyt juuri valittu erittelykenttä. Halutut erittelykentät voidaan määritellä lisättäväksi lomakkeelle oletusarvoisesti uutta tietuetta tehtäessä, jolloin erittelykentät eivät juurikaan eroa tavallisista kentistä.
Toteutetun kaltaisen sovelluskehitystä tukevan komponenttikirjaston sekä projektinhallintajärjestelmän olisi voinut tehdä ilman sovelluspalvelintakin. Olisiko kehitystyö ollut nopeampaa, helpompaa tai lopputulos parempi ilman sovelluspalvelinta? Eräs keskeisimmistä perusteista kokeilla kolmitasoarkkitehtuurin käyttöä oli mahdollisuus liittää samaan järjestelmään hyvin erilaisia, mutta samoja toimintoja sisältäviä käyttöliittymiä.
Kuitenkin käytännössä on käynyt ilmi, että useissa järjestelmissä ei ole kovin suurta tarvetta aivan erityyppisiin käyttöliittymiin. Ja toisaalta tietyn tyyppisen käyttöliittymän voimakas kehityspanostus vähentää haluja tuoda samaan järjestelmään rinnakkaisia erilaisia käyttöliittymiä. Näin esim. järjestelmän www-käyttöliittymä saattaa muodostua 'hauskaksi pieneksi lisäpalikaksi', joka ei ole kovin monimutkainen, jota ei kaikkiin toimituksiin ehkä edes oteta mukaan ja joka voitaisiin rakentaa melko nopeasti myös puhtaalta pöydältä ottamalla suoraan yhteyttä tietokantaan. Siten mahdollisuus tehdä hieman nopeammin erikoisia lisäkäyttöliittymiä ei välttämättä puolla panostusta sovelluspalvelimen, säikeidenhallinnan, tietoliikenteen ja salauksen kehittämiseen.
Sen sijaan sovelluspalvelimesta on ollut suuri etu esim. rinnakkaisuus- ja lukitusongelmien hallinnassa. Perinteisellä tietokantaa suoraan käyttävällä client/server -arkkitehtuurilla hankalat kysymykset 'Mitä jos kaksi käyttäjää yrittää samaan aikaan päivittää samaa tietuetta?' muuttuvat melko suoraan rinnakkaisuuden hallinnan yksinkertaisten 'perusharjoitusten' kaltaisiksi ongelmiksi. Perinteisellä tavalla rinnakkaisuusongelmia ratkaistaan esim. tekemällä tietokantaan apukenttiä, joihin merkittään 'lukitusaikoja' ja päivittämällä näitä kenttiä sopivasti transaktioiden sisällä. Sovelluspalvelimen avulla saman ongelman voi ratkaista pienehköllä tietorakenteella ja yhdellä lukolla.
Sovelluspalvelin parantaa rakennettavien ohjelmistojen laatua pakottamalla erottamaan toisistaan tietokantakäsittelylogiikan ja käyttöliittymälogiikan. Tietokantakäsittelyssä tehdään SQL-lauseita ja sitä varten täytyy parsia ja käsitellä merkkijonoja; siis melko perinteistä ohjelmointia. Graafisten käyttöliittymien tekeminen taas on pitkälti oliopohjaista ohjelmointia. Muodostamalla sovelluspalvelimen avulla tietokannasta käyttöliittymään päin oliomaisen kokonaisuuden, voidaan käyttöliittymän puolella toimia puhtaasti oliomaailman käsittein ja saavuttaa näin siistimpi ja ylläpidettävämpi ohjelmisto.
Lisäksi sovelluspalvelin tarjoaa erinomaisen mahdollisuuden valvoa käyttöliittymien toimintaa ja estää kannan tietojen vioittumisen tai joutumisen vääriin käsiin käyttöliittymän virheiden seurauksena. Näin on mahdollista tarjota melko vapaasti halukkaiden tahojen käyttöön rajapinta, jonka avulla he voivat tehdä haluamiaan pienehköjä laajennuksia ja erikoiskäyttöliittymiä järjestelmään, ilman että heidän tarvitsee laaja-alaisesti ja yksityiskohtaisesti ymmärtää järjestelmän kokonaistoiminnallisuutta.
Mahdollisuus suojata tieto mahdollisilta virheiltä käyttöliittymien toteutuksissa nousee erityisen tärkeäksi tarjottaessa sovelluksia ASP-tyyppisenä palveluna julkisen Internetin yli, koska silloin on mahdollista hyökätä palvelua vastaan muuttamalla saatavilla olevan, käännetyn client-osan konekielistä koodia. Tämän tekee tavallista helpommaksi Java:n tavukoodi: se on nimittäin mahdollista muuntaa takaisin lähes samaksi lähdekoodiksi siten, että ainoastaan kommentit ovat kadonneet ja metodin sisäisten ja private-muuttujien nimet ovat tunnistamattomia.
Työssä on käsitelty monimutkaisten tietokantajärjestelmien toteuttamista sovelluspalvelinta käyttävän monitasoarkkitehtuurin avulla. Tätä varten on kehitetty yleinen komponenttikirjasto, joka tukee ja nopeuttaa mallin mukaisten järjestelmien tekemistä. Konkreettisena esimerkkinä on käytetty laajahkon projektinhallinta ja -laskutus järjestelmän toteuttamista mallin mukaisesti.
Laajahkossa ja monimutkaisessa järjestelmässä on paljon hyvin erilaisia osia ja elementtejä, jotka kuitenkin kaikki on syytä käydä läpi, jotta voitaisiin arvioida kokonaisratkaisun toimivuutta. Muutoin ei ole mahdollista perusteellisesti tarkastella kysymystä, onko tämäntyyppinen arkkitehtuuri käytännössä soveltuva ja perinteistä tyyliä tehokkaampi laajojen ja monimutkaisten järjestelmien toteuttamiseen.
Prosla-ohjelmiston uudistettu versio olisi hyvin voitu tehdä myös perinteisellä arkkitehtuurilla. Uudistettu versio olisi saattanut syntyä nopeammin perinteisellä tavalla, sillä oltaisiin voitu suoraviivaisesti käyttää perinteisiä menettelytapoja eikä olisi tarvinnut miettiä, miten mikäkin asia näppärämmin sujuu uudenlaisessa ympäristössä.
Pitäisin lopputulosta kuitenkin huomattavasti siistimpänä, paremmin ylläpidettävänä ja laajennettavana kuin perinteisellä tavalla tehtynä. Samalla tämä Prosla for Java-järjestelmä toimii esimerkkinä miten voidaan tehdä hyvin hallittavia monimutkaisia järjestelmiä tällä tekniikalla ja kehitetyillä yleisillä komponenttikirjastoilla. Uskoisin seuraavien järjestelmien toteutuksen sujuvan nopeammin kuin tämän Prosla for Java toteutuksen ja ehkä huomattavasti nopeammin aiempiin client/server -arkkitehtuurilla toteutettuihin laajoihin tietokantajärjestelmiin verrattuna.
ISessio-rajapintaan on koottu metodikutsut, joita client-osa voi kutsua sovelluspalvelimelta. Session saa avattua jäljempänä liitteessä VetoRPC-protokollan kuvaus kerrotulla tavalla.
Tällä proseduurilla suoritetaan käyttäjän tunnistus ja oikeuksien selvitys. (Authentication ja Authorization). Eli tarkastetaan tunnus ja salasana. Metodi palauttaa KayttajaException-keskeytyksen, jos tunnus ja salasana -yhdistelmä ei täsmää tai tunnuksella ei ole käyttöoikeuksia ao. sovellukseen.
Tällä proseduurilla vaihdetaan käyttäjän salasana.
Metodi sulkee session, kaikki session taulut ja kantayhteyden, jos se on sessiokohtainen.
Clientit avaavat tällä proseduurilla tarvitsemiaan päätauluja. Parametri sTaulu on avattavan päätaulun ohjelmoijanimi.
Tällä proseduurilla voi toteuttaa sovelluskohtaisia erikoispalveluja. Myös useita hieman harvemmin käytettyjä yleiskäyttöisiä sovelluspalveluja kutsutaan tätä kautta. Parametri sNimi on sovelluspalvelun tunniste ja parametri p sisältää palvelun parametrit (p voi olla myös taulukko). Metodi voi myös palauttaa taulukon.
IHakutaulu-rajapinta on IPaataulu ja IAlataulu-rajapintojen yläluokka, johon on koottu alaluokkien yhteiset metodit. Siten kaikki sovelluspalvelimen taulu-instanssit toteuttavat tämän rajapinnan.
Palauttaa taulun status-informaation.
Palauttaa taulun kenttien rakenteellisen informaation ClientKentta-taulukkona.
Selvitetään, kuinka monta riviä on tulosjoukossa.
Palauttaa parametrina annettavan määrän rivejä tulosjoukosta kaksiulotteisena taulukkona.
Palauttaa lookupkenttään liittyvän lookuptaulun kentän ohjelmoijanimen perusteella.
Tällä proseduurilla voi toteuttaa sovelluskohtaisia erikoispalveluja. Myös useita hieman harvemmin käytettyjä yleiskäyttöisiä sovelluspalveluja kutsutaan tätä kautta. Parametri sNimi on sovelluspalvelun tunniste ja parametri p sisältää palvelun parametrit (p voi olla myös taulukko). Metodi voi myös palauttaa taulukon.
Tämä metodi sulkee tämän taulun sovelluspalvelimen puolelta.
IPaataulu-rajapinta vastaa sovelluspalvelimella sijaitsevaa Paataulu tai Lookuptaulu-luokasta perittyä instanssia.
Alustetaan tulosjoukon haku eli suoritetaan SQL-lause. Parametrina annetaan käyttäjän hakukenttiin kirjoittamat hakuehdot taulukkona, jonka pituus on taulun kenttien määrä.
Tämä proseduuri hakee tietyn rivin kannasta. Rivi on haettava ennen paivita()-kutsua. Parameterina annetaan haettavan rivin ID. Jos se on null, niin palautetaan nykyinen rivi. Metodi palauttaa taulukkona yhden taulun rivin.
Lisää uuden rivin tauluinstanssiin eli siirtää taulun lisäystilaan. Varsinainen lisäys kantaan INSERT-lauseella tapahtuu talletuksen yhteydessä.
Siirtää taulun päivitystilaan ja lukitsee nykyisen rivin.
Tallettaa parametrina saatavat arvot kantaan. Taulun on oltava päivitys- tai lisäystilassa.
Perutaan päivitys- tai lisäystila.
Poistetaan rivi kannasta. Taulun on oltava päivitystilassa.
Palauttaa päätaulun alataulut IAlataulu-taulukkona.
Palauttaa päätaulun erittelytaulut IAlataulu-taulukkona.
Tämä proseduuri tekee raportin. Jos raportti on editorilla tehty, niin haetaan rakennemäärittely kannasta.
Parametrina sTyyppi kerrotaan raportin tyyppi (esim. perusraportti, tietyllä editorilla tehty
raportti tai ohjelmallisesti räätälöity raportti ). Parametrina sNimi on editoriraportin
nimi. Parametri options välittää erilaisia tulostusoptioita.
Metodi palauttaa HTML-raporteilla URL:n, mistä raportin voi hakea ja graafisilla raporteilla
IPaataulu-instanssin, jota voidaan käyttää raportoinnissa.
Tarkistetaan lookupkentän arvon oikeellisuus. Parametri sKentta on lookupkentän ohjelmoijanimi ja oArvo on tarkistettava arvo. Metodi palauttaa lookupkentän asetettavien kenttien arvot taulukkona.
Tämä proseduuri asettaa välimuistissa tietyn lookupkentän asetettaviin kenttiin annetut arvot. Tätä käytetään lookupikkunoista: kun ne voivat antaa validointimääräyksen, ei arvoa enää tarvitse tarkistaa kannasta talletuksen yhteydessä.
IAlataulu-rajapinta vastaa sovelluspalvelimella sijaitsevaa Alataulu-luokasta perittyä instanssia.
Alustaa alataulun hakujoukon; alataululla ei ole hakukenttiä.
Tällä proseduurilla client lähettää muuttuneen rivin arvot alataululle. Näitä kutsuja tulee sitä mukaan, kun käyttäjä muuttaa alataulurivien arvoja.
Lisätään uusi rivi alataulun ensimmäiseksi riviksi.
Tällä proseduurilla client ilmoittaa rivin poistamisesta lomakkeella. Alataulu poistaa rivin välimuistista ja jos riviä ei ollut lisätty samalla päivityskierroksella, niin lisätään rivi talletuksen yhteydessä poistettavien rivien listaan.
Clientit kutsuvat tätä proseduuria halutessaan tarkistaa lookupkentän arvon.
Tämä proseduuri asettaa lookupkentälle validoidut arvot asetettaviin kenttiin tietylle riville. Lookupikkuna käyttää tätä kutsua tehokkuussyistä.
Protokolla toimii kuten HTTP: jokaista eri sovelluspalvelinkutsua varten avataan oma TCP/IP -yhteys.
Erilaiset kutsut ja parametrit välitetään seuraavalla tavalla:
Ensin lähetetään 1-n -merkkiä pitkä parametrin tunnisteosa.
Sitten parametrin data merkkijonoksi muutettuna.
Loppumerkkinä 8-bittinen luku 0 eli ns. '\0'.
Perustyyppien tunnisteet ovat:
S merkkijono
I kokonaisluku
F liukuluku (desimaalierottimena piste)
D aika (PP.KK.VVVV HH:MM:SS)
O (Object) == null == O\0
d Double
L Long
b Boolean
Taulukko-tyypeillä muoto on: 'tunniste + arrayn pituus (rivimäärä) + \0'.
Minkä jälkeen seuraa jokainen array-elementti ikäänkuin se olisi itsenäinen
parametri. Näin voidaan helposti välittää n-ulotteisia (tyypittämättömiä)
arrayitä.
AS String[]
AO Object[]
AA Object[][]
Ai int[]
AI Integer[]
AC ClientKentta[]
Binäärimuotoisella datalla tunniste toimii hieman samaan tapaan kuin array:llakin, eli: 'AB + datan pituus (tavuina) + \0 + byte-data (ilman loppumerkkiä)'.
Luokat ja keskeytykset välitetään kuin ne olisivat tietueita: 'tunniste + \0 + perustyypit luokan määrittelyjärjestyksessä'.
RCK ClientKentta
RCLK ClientLookupKentta
RTS TauluStatus
RKS KayttajaStatus
RKE KayttajaException
RSE SysteemiException
RPE ParametriException
RELE EiLoydyException
Kaikki metodikutsut palauttavat arvon. Jos ne ovat void-tyyppisiä, niin paluuarvo on null eli O\0. Jos metodi heittää keskeytyksen, niin tällöin paluuarvo on ao. keskeytys.
Metodikutsun muoto on 'P + kutsun nimi + \0 + parametrit'.
P tarkoittaa ns. blokkaavaa proseduurikutsua; periaatteessa N on varattu
ei-blokkaavalle kutsulle, mutta sitä käytetään toistaiseksi vain
soveluspalvelin -> client -suuntaisessa kommunikaatiossa.
Jokaiselle sessiolle arvotaan yksikäsitteinen ID, jolla client viittaa ao. sessioon. Session sisällä jokaiselle taulu:lle tulee yksikäsitteinen ID. Jos metodikutsu palauttaa viittauksen sovelluspalvelimen olioon, tällöin ovat tyyppeinä (muutoin kuten Integer-tyyppi):
p Paataulu
a Alataulu
Client-puolen tulee luoda vastaavan tyyppinen rajapintaluokka, jonka ominaisuutena on ao. ID.
Kokonaisen metodikutsun rakenne on 'iSessioID + iTauluID + P + metodinimi + \textbackslash0 + parametrit'.
iSessioID on session ID (perustyyppinä Integer)
iTauluID on taulun ID (perustyyppinä Integer) (== 0, jos session metodi)
Paluuarvon rakenne on 'infotavu + paluuarvo'.
Infotavu on 8-bittinen luku:
0: jos session tunnistus (salauksen tunnistus) ei onnistunut;
vastaus (keskeytys) on tällöin salaamaton (ciphertype = 0).
1: jos session tunnistus onnistui.
Alustettaessa yhteyttä client lähettää kutsun 'iSessioID + sJarjestelmanTunnus + ciphertype'.
iSessioID on Integer-tyypitetty 0 eli 'I0\0'
sJarjestelmanTunnus on merkkijono-tyypitetty järjestelmän tunnus.
ciphertype on 8-bittinen luku, ks. alla.
Jos sovelluspalvelin pyöriikin eri portissa vastauksena tulee 8-bittinen luku 0 ja uusi portti Integer-tyypitettynä, esim. 'I1234\0'. Tällöin client:in tulee yrittää yhteydenottoa uudestaan tähän uuteen portiin.
Muutoin jos vastauksena on 8-bittinen luku 1 jatketaan salaustietojen vaihdolla. Eli aiemmin saapunut ciphertype on 8-bittinen luku:
0: ei salausta
1: DES
2: Triple-DES
3: Blowfish
4: IDEA
5: RC4
Yleensä käytetään joko arvoa 0 tai 3. Jos ciphertype on 0, niin seuraavana tulee 'PavaaSessio\textbackslash0+parametrit'. Muutoin sovelluspalvelin lähettää julkisen RSA-avaimensa: [ 8-bittinen luku N-osan pituus tavuina ; N-osa ; 8-bittinen luku E-osan pituus tavoina ; E-osa ].
Johon client vastaa symmetrisen avaimensa: [ 8-bittinen luku avaimen pituus tavuina ; avain ]. Tämän jälkeen yhteys on salattu ja salauksen sisällä seuraavana tulee 'PavaaSessio\textbackslash0+parametrit'.
Jos yhteys on salattu, niin sovelluspalvelimella on talletettuna tietorakenteeseen jokaisen client-session symmetrinen avain. Tällöin client lähettää iSessioID:n ilman salausta ja tämän jälkeen kaikki data on salattua.
Tällöin ylläolevan spesifikaation mukainen data muokataan siten, että se jaetaan max. 256-merkkisiin osiin ja jokainen osa lähetetään muodossa: '8-bittinen luku: osan pituus + osa (max. 256 merkkiä)'. Jos osan pituus ei ole jaollinen 8:lla, niin osan loppuun lisätään tarvittava määrä 0:ia. Jokainen osa on salattu käytetyllä salaustavalla (saman session eri kutsut samalla Cipher-instanssilla).
Tämänsuuntaista kommunikaatiota varten client kysyy sovelluspalvelimelta portin, johon client avaa jatkuvasti auki pysyvän TCP/IP yhteyden. Client välittää (ylläolevan tavan mukaisesti Integer-tyypitettynä) sovelluspalvelimelta saamansa koodin ja jää odottamaan (omassa säikeessään) sovelluspalvelimelta tulevia ilmoituksia.
Käytetty salaustapa ja avain on sama kuin varsinaisilla sovelluspalvelinkutsuilla (oma Cipher-instanssi).
Proseduurikutsujen ja parametrien tyypitykset toimivat kuten varsinaisilla sovelluspalvelinkutsuilla, paitsi että kaikki metodikutsut ovat N-tyyppisiä ja paluuarvoja ei lähetetä.
Tällä hetkellä on olemassa vain yksi metodi: nimi: Viesti, parametrina
Object-array: [ new Date(), sLahettaja, sViesti ] eli esim.
'NViesti\0AO3\0D12.7.2001 10:50:05\0ATEST\0AHello World\0'.