Grafikus keretrendszer komponensalapú webalkalmazások fejlesztéséhez Székely István Debreceni Egyetem, Informatikai Intézet iszekely@inf.unideb.hu Kivonat Az Internet utóbbi években végbemenő nagymértékű fejlődése az alkalmazások egy új csoportjának létrejöttét eredményezte. Ezeket az alkalmazásokat összefoglaló néven webalkalmazásoknak nevezzük, mivel ezek a World Wide Web-et választották platformjuknak. A fejlesztők az évek során különféle módszertanokat alkottak és számos fejlesztőeszközt készítettek a programírás megkönnyítésére. A mai fejlesztői környezetek grafikus felülettel rendelkeznek, és a szövegszerkesztőn és a fordítóprogramon kívül számos kényelmi szolgáltatásuk van. Webalkalmazások esetén szintén szükség van ilyen eszközre. Cikkemben egy általam készített fejlesztőeszköz kerül bemutatásra, ami maga is egy webalkalmazás. A keretrendszeren belül weblapjainkat újrafelhasználható komponensekből építhetjük fel, amik a fejlesztés során leggyakrabban előforduló részfeladatokat végzik el. Cikkemben bemutatom, hogy hogyan került megvalósításra a kliens-szerver architektúrájú elosztott keretrendszer, valamint hogy hogyan történhet ebben egy alkalmazás elkészítése és abból működő JSP lapok előállítása. 1. Bevezetés Kezdetben a programokat egyedi igények kiszolgálására készítették. A számítógépek elterjedésével egyre többféle alkalmazást kellett készíteni, ami a korábban működő módszerekkel nem volt lehetséges. Új szempontok kerültek előtérbe: csapatmunka, újrafelhasználhatóság, minőségbiztosítás. Ezeket az igényeket csak megfelelő szervezéssel lehetett kielégíteni. Az alkalmazásokat jól elkülöníthető részekre, modulokra kellett bontani úgy, hogy az egyes modulok egymástól függetlenül fejleszthetők és tesztelhetők legyenek. A modulokat további részekre lehet bontani, míg végül eljutunk a komponensekig. 2. Komponensek Egy komponens az alkalmazások olyan atomi része, amely jól meghatározott feladatot lát el, valamilyen pontosan definiálható funkcionalitással rendelkezik, és együttműködésre képes az alkalmazás többi komponensével. 1
A komponenseket kétféle szempont figyelembevételével kell elkészítsük. Elsőként arra kell törekednünk, hogy komponenseink valamilyen gyakran előforduló feladatra adjanak megoldást. Célszerű lehet egy olyan komponens elkészítése, amely adatbázisban tárolt adatok alapján egy táblázatot jelenít meg. Amennyiben a feladatra sikerül elég általános megoldást találni, ugyanakkor mégsem érünk el túlzott bonyolultságot, komponensünk az alkalmazás másik pontján, sőt, másik alkalmazásban újra felhasználható lesz. Az újrafelhasználhatóságon kívül a cserélhetőséget is ki kell emelni. Elképzelhető, hogy ugyanarra a feladatra többféle implementációt is tudunk készíteni. A implementációk közül bármelyiket választjuk is, a többi komponensnek tudni kell kommunikálni vele. Ez legkönnyebben interfészek definiálásával érhető el. 2.1. A komponensek implementációja Webalkalmazások fejlesztése során gyakran előfordul, hogy valamilyen információhalmazt kell valamilyen esetleg többféle módon megjeleníteni. Az információhalmaz előállítása paraméterektől függ. Célszerű az adatok kezeléséért és a megjelenítésért felelős részeket különválasztani. Ennek az elvnek felel meg az MVC tervezési minta, melyben az adatok (modell, M), a megjelenítés (nézet, V) és az ezeket irányító vezérlő (kontroller, C) elkülönül egymástól. Az MVC mintára már nagyon sok rendszert építettek, például a Swinget, amely GUI alkalmazások készítésre szolgáló Java API [1]. A komponensek implementációja a keretrendszerben Java nyelven történt, és szintén az MVC tervezési mintát követi. Az összetevőknek megfelelően definiáltam három interfészt. A fő interfész a kontrollert írja le, melynek metódusai a paraméterek beállításának és a megjelenítésnek a módját definiálják. public interface Component { void init(string id, java.util.map properties); void print(java.io.printwriter out); } Minden, a rendszerbe illeszkedő komponensnek ezt az interfészt kell implementálni. A modellhez és a megjelenítéshez társuló interfészek implementálásáról a komponens készítője szabadon dönthet, ám ezek használata is ajánlott. public interface Model { void init(java.util.map properties); boolean hasmoreitems(); Object[] nextitem(); } public interface View { void print(java.io.printwriter writer); } A előbb interfészek implementálásán túl néhány formai követelménynek is meg kell felelni. Ezek a szabályok nem szintaktikai, hanem szemantikai szabályok, így pusztán interfészekkel nem definiálhatók. Ezen szabályoknak megfelelő komponensek készítése automatizálható, amivel a fejlesztés menete leegyszerűsíthető és felgyorsítható [2]. 2
2.2. Konténerek A konténerek speciális komponensek, mégpedig azért, mert tartalmazhatnak más komponenseket. Ezek a komponensek természetesen szintén lehetnek konténerek, így a komponenseknek egy tartalmazási hierarchiája hozható létre. A konténerekhez szintén tartozik egy interfész, ám ez nem tartalmaz egyetlen metódusdeklarációt sem, csupán jelölőinterfész szerepét tölti be. 3. Komponensszerver A fejlesztőrendszer kliens-szerver architektúrára épül. A komponenseket egy szerver szolgáltatja a böngészőben működő kliensnek. Az implementáció a Java Servlet technológián [3] és a JavaServer Pages technológián [4] alapul. 3.1. Konfiguráció A szerver a rendelkezésre álló komponensek listáját egy XML [5] állományból olvassa be az összes olyan információval együtt, ami a grafikus módban való szerkesztéshez szükséges. Ide tartozik a komponens azonosítója, ami a későbbiekben egy komponens típusát jelöli ki. Fel kell sorolni a komponenseink összes jellemzőjét, ami a működéshez szükséges (a paraméterek), de nem hagyhatók ki a GUI-n való megjelenéshez szükséges információk sem, mint például a rövid leírás, ami eszköztippként (tool tip) jelenhet meg, vagy a komponenst ábrázoló ikon. Mindezek mellett a leglényegesebb információ a komponenst implementáló osztály teljes minősített neve. Egy XML konfigurációs állomány tehát a következőképpen nézhet ki: <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE components SYSTEM "components.dtd"> <components> <component id="table"> <description>table</description> <class>components.table</class> <image-url>/editor/images/table.gif</image-url> <property name="rows" desc="number of rows"/> <property name="cols" desc="number of columns"/> </component> <container id="borderlayout"> <description>container with border layout</description> <class>components.borderlayout</class> <image-url>/editor/images/borderlayout.gif</image-url> </container> </components> A szerver induláskor beolvassa és feldolgozza ezt az állományt, és ez alapján összeállítja a komponensek és a konténerek listáját. 3
3.2. A szerver szolgáltatásai Működés közben a szerver a következő információkat tudja szolgáltatni a kliensnek: a rendelkezésre álló komponensek listája a rendelkezésre álló konténerek listája egy komponens összes információja (beleértve a konténereket is) egy adott típusú komponens konténer-e egy komponens példány 4. A kliens A kliens implementálása szintén JSP technológiával történt, de a Javascript is nagy szerephez jutott, mivel a böngészők nagy részét ezen a nyelven lehet programozni. A felhasználói felület felső részén egy eszköztár található, amely az alapvető funkciókat (új weblap, mentés, előnézet stb.) irányító gombokat tartalmazza. Az eszköztár alatt a böngésző ablaka két részre van osztva. A jobb oldali rész a szerkesztőterület, amely szinte az egész ablakot kitölti. Weblapjainkat ezen a területen hozhatjuk létre. A baloldali sávban legfelül a komponenseket, majd azok alatt a konténereket ábrázoló ikonokat találjuk meg. A középső rész a szerkesztés alatt álló weblapon elhelyezett komponensek hierarchiáját tartalmazza, faként ábrázolva azt. A bal alsó sarokban egy komponens tulajdonságait találhatjuk meg táblázatba rendezve. 4.1. Komponens elhelyezése a weblapon Új komponenst a következőképpen illeszthetünk be a szerkesztett weblapba. A megfelelő ikonnal kiválasztjuk a komponens típusát, majd a szerkesztőterületen az egérrel kijelöljük a helyét. Ezután ki kell tölteni egy űrlapot, amely a komponens azonosítóján (ID) kívül annak összes tulajdonságát is tartalmazza. A későbbi szerkesztés során egy komponens az ID-vel egyértelműen azonosítható. A szükséges paraméterek kitöltése után a szerver elküldi a komponens megjelenítéséhez szükséges HTML kódot a kliensnek. Ezt felhasználva a komponens megjeleníthető a szerkesztőben. A HTML kód beillesztéséhez az alkalmazás a DOM-ot használja. 4.1.1. DOM A DOM (Document Object Model) a W3C által specifikált, platform- és nyelvfüggetlen API, amellyel érvényes HTML és jól-formázott XML dokumentumok kezelhetők [6]. A DOM definiálja a dokumentumok logikai szerkezetét és a dokumentumokhoz való hozzáférés és kezelés módját. Segítségével dokumentumok építhetők fel, navigálhatunk a struktúrában, valamint elemek adhatók hozzá, módosíthatók és törölhetők. A böngészők a weblapokat HTML dokumentumként kezelik, és elemeit elérhetővé teszik a specifikációban leírtak szerint. Az elemeknek megfelelő Javascript objektumok implementálják az API-ban definiált interfészeket. Így válik lehetővé a szerkesztőterület interaktív módon való szerkesztése. 4
4.2. Szinkronizáció a kliens és a szerver között Az elkészült lapok mentéséről, tárolásáról a szerver gondoskodik. Biztosítani kell, hogy az elmentett lapok további szerkesztésre visszatölthetők legyenek, ami a lapok HTML formátumban való tárolása esetén nem valósítható meg. A megoldást az jelenti, ha a szerveren is felépítünk egy DOM dokumentumot, ami azonban sokkal egyszerűbb, mint a böngészőben megjelenített HTML dokumentum. Csupán a komponensek hierarchiáját kell tárolnunk. A DOM API lehetőséget ad a szerveren felépített dokumentum XML állományban való tárolására. Egy olyan lap, amin egy konténer, azon belül egy komponens van, a következőhöz hasonló XML állománnyal adható meg: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-page SYSTEM "web-page.dtd"> <web-page> <container id="layout" type="borderlayout"> <component constraint="center" id="content" type="table"> <property name="rows" value="3"/> <property name="cols" value="4"/> </component> </container> </web-page> A szerveroldali dokumentum elkészítése csak úgy lehetséges, ha szerkesztés közben folyamatosan nyomon követjük a kliensen végbemenő módosításokat. A kliens minden változtatásról értesíti a szervert, hogy a megfelelő adminisztráció elvégezhető legyen. 5. Az elkészült lapok megjelenítése A lapok XML formátumban való tárolása biztosítja a további szerkeszthetőséget, de nem támogatja a megjelenítést. Megjelenítés előtt a lapok konverziójára van szükség, mégpedig olyan módon, hogy dinamikus voltuk megmaradjon, és a tartalmazott komponensek megjeleníthetők legyenek. Megoldást jelent az XML állományok transzformálása JSP oldalakká. Ebben elhelyezhetünk HTML elemeket, de a komponensek beillesztéséről is tudunk gondoskodni. Minden komponens helyét egy saját JSP tag jelzi, melynek a komponens létrehozása és a tartalom előállítása a feladata. Az erre szolgáló eszközkészlet része a JSP technológiának. Létrehozhatunk saját tagkönyvtárakat, melyek funkcionalitását Java osztályokkal implementálhatjuk. A transzformált lapok az alábbihoz hasonló elemeket tartalmazhatnak: <%@ taglib uri="component.tld" prefix="component" %> <%@ page contenttype="text/html" %> <html> <body>... <component:show id="content" type="table"> 5
<component:property name="rows" value="4" /> <component:property name="cols" value="5" /> </component:show>... </body> </html> 6. További lehetőségek A jelenlegi rendszerben lehetőség van dinamikus weblapok grafikus felületen való elkészítésére. A lapokat egy előre elkészített komponenskészlet segítségével hozhatjuk létre, amik aztán elmenthetők és később szerkesztés céljából betölthetők. A komponensek elkészítését a keretrendszer nem támogatja, azokat tőle függetlenül kell létrehozni, elhelyezni a szerveren és felvenni a konfigurációs állományba a megfelelő bejegyzéseket. Egyfajta továbbfejlesztési lehetőség ennek a hiányosságnak a megszüntetése. A kész weblapok közötti navigáció szintén nem adható meg a keretrendszerben, ami az előzőtől nagyobb hátrány. Egy igazi webalkalmazás sok weblapból áll, és a működés az ezek közötti navigáción alapul. Éppen ezért ez a fejlesztési irány sokkal lényegesebb. Hivatkozások [1] Sun Microsystems, Inc.: Java Foundation Classes (JFC/Swing), http://java.sun.com/products/jfc/, 1999 [2] Jónás Richárd: Komponensalapú webalkalmazás-fejlesztő rendszer, Networkshop 2003, Pécs [3] Sun Microsystems, Inc.: Java Servlet Technology, http://java.sun.com/products/servlet/index.jsp [4] Sun Microsystems, Inc.: JavaServer Pages Technology, http://java.sun.com/products/jsp/index.jsp [5] T. Bray, J. Paoli, C. M. Sperberg-McQueen, E. Maler, F. Yergeau: Extensible Markup Language (XML) 1.0 (Third Edition), World Wide Web Consortium, 2004 http://www.w3.org/tr/2004/rec-xml-20040204 [6] L. Wood, A. Le Hors, V. Apparao, S. Byrne, M. Champion, S. Isaacs, I. Jacobs, G. Nicol, J. Robie, R. Sutor, C. Wilson: Document Object Model (DOM) Level 1 Specification (Second Edition), World Wide Web Consortium, 2000 http://www.w3.org/tr/2000/wd-dom-level-1-20000929 6