J2EE – a nagy aknamező

Hát, megvan egy ideje, hogy utoljára írtam. Pedig magamban már többször megfogadtam, hogy rendszeresebben írok. Úgy volna értelme csinálni az egészet, hogy hetente legalább egy bejegyzés születik. Persze ez így hiú ábránd ennyi házi feladat mellett.

Ez az UML házi kész volt. 80 órát egy hét alatt beletolni abba, hogyan kell leimplementálni egy hello world-nél egy szinttel bonyolultabb feladatot J2EE alapon, na ez teljesítmény. És örülök, hogy ennyi idő alatt összeállt…

Hát, megvan egy ideje, hogy utoljára írtam. Pedig magamban már többször megfogadtam, hogy rendszeresebben írok. Úgy volna értelme csinálni az egészet, hogy hetente legalább egy bejegyzés születik. Persze ez így hiú ábránd ennyi házi feladat mellett.

Ez az UML házi kész volt. 80 órát egy hét alatt beletolni abba, hogyan kell leimplementálni egy hello world-nél egy szinttel bonyolultabb feladatot J2EE alapon, na ez teljesítmény. És örülök, hogy ennyi idő alatt összeállt…

Nem véletlen tartott eddig. Van benne egy gyönyörű implementált objektumrelációs leképezés, néhány tag elhelyezése, egy xml-fájl és még néhány sor kód megírása után az objektumokat szépen kimenti az adatbázisba, illetve visszaolvassa onnan igény szerint. Tényleg szép. Csak az ember el ne szúrja a tagelést, mert olyan exception-trace-t kap futáskor, hogy öröm nézni. A legnagyobb, amit sikerült kapni, 40 kB méretű volt. Iszonyatosan redundáns, gyakorlatilag az egész háromszor szerepel, az értelmes tartalom másfél-két sor. Szűrd ki…

A fejlesztés során mi RAP-t használtunk GUI-készítéshez. Nem gyenge technológia: Eclipse plugineket AJAX-szal támogatott weblapokra fordít. De azért ezt több projektből összefejleszteni szép teljesítmény. Például nem mindegy, hogy hol kapcsoljuk össze a projekteket. Ha az Eclipse projekt tulajdonságainál fogjuk, és beikszeljük a Referenced projects résznél (hogy szerepeljen a build path-ban), az nem jó. A plugin.xml fájlban kell a depencencies blokkban bejelölni.

Remek, most már lefordul, elindul, és gyönyörű exception trace megint. Most az a baja, hogy nem töltötte be a futás közben a hivatkozott projekteket. Némi szórakozás után kiderült, hogy a megoldás az, hogy még a futtatási konfigurációnál is fel kell venni a hivatkozott projekteket, mint bundle-t. Eredetileg ezt nyersen az xml-be hakkoltam bele, később hívta fel valaki a figyelmemet, hogy a futtatási konfigurációnál is fel lehet venni.

Hasonló szépségek vannak az APIban is. A RAP1.1M1 és az 1.1M3 között megváltozott az alkalmazás belépési pontjának szintaktikája: az M1-ben Display típusú, míg az M3-ban int típusú visszatérési értéket vár. Érdemes megnézni a sorrendet, Display-ből int.

Beletelt némi időbe, amíg rájöttem, hogyan kell megváltoztatni a mintakódot, hogy lefusson. Gyakorlatilag a Display egy azonosítóját kell visszaadni a metódus végén. Szóval minden érdekes.

Hasonlóan jópofa volt az, hogy amikor beraktuk a szükséges webservice meghívásához szükséges fájlokat, akkor kb 25-30 MB méretben kellett jar-fájlokat a lib könyvtárba tenni. Ami problémássá teszi a dolgot, hogy ez csoportmunkában készült házi feladat, azaz fel kellett tölteni egy svn szerverre, és a többieknek le kellett szedni. Hab a tortán, hogy az svn csak fájlok között frissíti a status bart, így a 10 megás jarnál úgy néz ki a dolog, mintha meghalt volna menet közben. A csúcs az volt, amikor ezt upload közben sikerült valakinek fagyásnak értelmeznie, és kilőtte az Eclipse-et. Ezután egy órába került, amíg sikerült rendbe tennie a rendszert…

Érdekes ez az Enterprise Java technológia. Ekkora aknamezőt még nem láttam… Elég valami apró hiba, és hihetetlen mennyiségű hiba bukkan fel, és a hibaüzenetekből is alig lehet kikövetkeztetni, hogy mi lehetett az ok. Elég bonyolult architektúra, rengeteg 3rd party lib, és nagyon korlátozott tapasztalat: ez elég ahhoz, hogy a nem túl bonyolult feladat megoldását nagyon megnehezítse.

Distributed Connector

A Linux Programozása nevű tárgyra adtam be egy helyi hálózatra tervezett elosztott kommunikációt megvalósító rendszert, és példaalklamazásként elosztott quicksort algoritmust. A rendszer tökéletesen elosztott, ami annyit tesz, hogy a helyi hálózatra csatolt gépek mindegyikén fut egy szolgáltatás, ami UDP üzenetek segítségével tartja a kapcsolatot a többi számítógéppel, és felületet nyújt a kommunikációhoz a felhasználói programoknak.

Letöltés

A Linux Programozása nevű tárgyra adtam be egy helyi hálózatra tervezett elosztott kommunikációt megvalósító rendszert, és példaalklamazásként elosztott quicksort algoritmust. A rendszer tökéletesen elosztott, ami annyit tesz, hogy a helyi hálózatra csatolt gépek mindegyikén fut egy szolgáltatás, ami UDP üzenetek segítségével tartja a kapcsolatot a többi számítógéppel, és felületet nyújt a kommunikációhoz a felhasználói programoknak.

Letöltés

Linux architektúrán legegyszerűbben a következő parancsok végrehajtásával tölthetjük le a forráskódot, és fordíthatjuk le a rendszert:


wget http://users.hszk.bme.hu/~gb606/disco/Makefile
make all

Dokumentáció

Disco Architektúra

A létrehozott rendszer feladata egy helyi hálózatra csatlakoztatott számítógépek kommunikációjának támogatása, anélkül, hogy ehhez szükség lenne központi kiszolgáló segítségére. A központi kiszolgáló feladatait (felhasználók követése, üzenetek továbbítása) szét kell osztani a résztvevő számítógépek között. A legegyszerűbb megoldás az, ha az összes számítógép ismeri a résztvevőket, és kommunikációra UDP üzeneteket, szükség esetén UDP üzenetszórást alkalmazunk.

DisCo architektúra

Minden résztvevő számítógépen fut egy DisCo kiszolgáló, amely a többi számítógéppel tartja a kapcsolatot, és felületet biztosít a felhasználói programok (továbbiakban szolgáltatások, Service-ek) számára Unix Domain Socket-en keresztül.

Lényeges kikötés, hogy egy gépen egyféle szolgáltatásból csak egy futhat egy időben és az egyes szolgáltatások a többi résztvevő gépen csak azonos szolgáltatással kommunikálhat (ez nem jelent korlátozást, hiszen az egyes szolgáltatások maguk is biztosíthatnak felületet a helyi gépen más szolgáltatások számára).

Disco protokoll

Közös csatorna

A résztvevő számítógépek között meg kell oldani azt, hogy az elosztott résztvevők mindegyike egységes képet kapjon a hálózatban szereplő gépekről, és a rajtuk futó szolgáltatásokról. Ezen felül továbbítani kell a szolgáltatások irányított vagy szórt (single-/broadcast) üzeneteit.

A közös csatornán használt üzenetek a következők. A kommunikáció UDP/IP felett történik, minden üzenetet sorvégjel (‘\n’) zár.

Üzenetformátum Paraméterek Jelentés
(%s Számítógép szöveges azonosítója A küldő fél bejelentkezik a hálózatba
=%d %s A rendelkezésre álló szolgáltatások kódolva; szöveges azonosító Bejelentkezésre válasz: a küldő gép szolgáltatásai, és azonosítója
) Kijelentkezés
+%d Szolgáltatás azonosító A küldő számítógépen új szolgáltatás indult
-%d Szolgáltatás azonosító A küldő számítógépen egy szolgáltatás leállt.
!%d %s Szolgáltatás azonosító, üzenet Irányított üzenet szolgáltatások között
.%d %s Szolgáltatás azonosító, üzenet Szórt üzenet szolgáltatások között

Helyi kommunikáció

Kiszolgáló -> Szolgáltatás

Üzenetformátum Paraméterek Jelentés
(%s Helyi gép szöveges azonosítója A kiszolgáló elküldi a helyi gép azonosítóját
+%d %s Távoli gép szám azonosítója, távoli gép szöveges azonosítója Egy távoli gépen elindult az adottal kompatibilis szolgáltatás
-%d Távoli gép azonosítója A távoli gépen leállították az adott szolgáltatást
!%d %s Távoli gép azonosítója, üzenet Irányított üzenet érkezett
.%d %s Távoli gép azonosítója, üzenet Szórt üzenet érkezett

Szolgáltatás -> Kiszolgáló

Üzenetformátum Paraméterek Jelentés
%d Szolgáltatástípus azonosítója Szolgáltatás azonosítása a helyi kiszolgáló számára
!%d %s Címzett azonosítója, üzenet Üzenet küldése a megjelölt számítógépen lévő azonos szolgáltatás számára
. %s Üzenet Üzenet küldése az összes azonos szolgáltatásnak a hálózatban

Protokoll folyamatok

Bejelentkezés

Amikor egy új számítógépen elindul a DisCo kiszolgáló, egy bejelentkezés (‘(%s’) üzenetet küld minden számítógépnek a hálózatban. Nyilvánvaló, hogy kezdetben semmilyen szolgáltatás nem fut az újonnan indult kiszolgáló mellett. A bejelentkezés hatására minden számítógép visszaküldi a saját azonosítóját és a rajta futó szolgáltatások azonosítóit kódolva.

Szolgáltatás indítása, leállítása

Minden távoli szolgáltatás indulásakor vagy leállításakor az eseményt jelezni kell az esetleges azonos típusú helyi szolgáltatásnak. Illetve a helyi szolgáltatásokban történt változást szórt üzenetként továbbítani kell a többi számítógépnek.

Egy példa alkalmazás: quicksort

A bemutatott példában a 2-es azonosítóhoz rendeljük a sort szolgáltatást, amely gyorsrendezést valósít meg az elosztott rendszerben. A hálózat bármelyik gépén beadott rendezési feladatot a rendszer autonóm módon szétosztja a feladatot, majd a végeredmény ott lép ki, ahol a feladatot beadtuk.

Pontosítva az algoritmust, (a továbbiakban node-nak hívjuk a sort szolgáltatással rendelkező számítógépeket) ha egy node kap egy rendezési feladatot (egy másik node-tól, vagy a rendszeren kívüli felhasználótól) azt két részre osztja, majd kiválaszt véletlenszerűen két node-ot, akiknek elküldi a két részfeladatot. Minden node oda küldi vissza az eredményt, ahonnan kapta. Ha a végeredményről van szó, akkor azt a részeredmények összerakása után a helyi fájlrendszerben output.txt fájlba rakja.

Protokoll

A quicksort szolgáltatás a DisCo kiszolgáló felületét használva, a fent leírt protokollra épít, az üzeneteit tehát DisCo protokoll szerint felcímezve küldi. Alant csak a DisCo protokoll üzenetrészében szereplő tartalmat fejtem ki, bár az is fontos információt tartalmaz, hogy ki az üzenet címzettje.

Üzenetformátum Paraméterek Jelentés
?%d%c%d,%d,… Feladatazonosító (aminek szerepelnie kell a válaszban); részjelölő karakter: ‘< ' vagy '>‘ attól függően, hogy a feladat a teljes feladat alsó, vagy felső részfeladata; majd a rendezési feladatot leíró vesszővel elválasztott számsorozat (első eleme az adatok száma, majd jönnek a számok) A küldő node feladatot ad a címzettnek.
!%d%c%d,%d,… A feladatkiírásban szereplő azonosító; a részjelölő karakter; és a rendezett számsorozat hasonlóan a feladatkiíráshoz A küldő node befejezte a feladatot, és küldi az eredményt.

Rendezés menete

A felhasználó bármelyik a rendszerbe csatlakozott számítógépen létrehoz egy feladatfájlt, benne a rendezésre váró számokkal, sorvégjellel elválasztva. E fájl nevét beírva a sort programba bekerül a feladat a rendszerbe. Ha minden jól megy, pár pillanat múlva a megoldás bekerül az output.txt -be.

Telepítés és futtatás

A DisCo kiszolgálót és a quicksort szolgáltatást a következő parancsok beírásával lehet a leggyorsabban telepíteni (minden előzetes letöltés nélkül):


wget http://users.hszk.bme.hu/~gb606/disco/Makefile
make all

A fent letöltött Makefile letölti az összes szükséges forrásfájlt, és előállítja a szükséges bináris állományokat, és generál egy azonnal használható input.txt -t. A kiszolgálót futtatni a


./disco _név_

-el lehet, ahol a _név_ egy szabadon választott szöveges azonosítója a számítógépnek. A rendezési feladat generálására alkalmas eszköz az


./inputgen _kimenetszám_

, ami stdout-ra a megadott számú véletlenszámot írja ki. Végül a sort szolgáltatást a ./sort paranccsal indíthatjuk el.

Java kimenet UTF-8 kódolásban

Csalódtam a rendszeremben. Pár nappal ezelöttig abban a szent meggyőződésben voltam, hogy a Kubuntu tetőtől talpig UTF-8 kódolással dolgozik. Nos ez többnyire igaz. A java VM esetén az stdout alapértelmezett kódolása latin-1, ami normális esetben nem tűnik fel. Önálló labor feladatom során merült fel, hogy egy java program kimenetét kellett böngészőben megjeleníteni. A program bemenetként egy UTF-8 kódolású XML fájlt kapott, fel sem merült bennem, hogy gond lehet a kódolással.

Csalódtam a rendszeremben. Pár nappal ezelöttig abban a szent meggyőződésben voltam, hogy a Kubuntu tetőtől talpig UTF-8 kódolással dolgozik. Nos ez többnyire igaz. A java VM esetén az stdout alapértelmezett kódolása latin-1, ami normális esetben nem tűnik fel. Önálló labor feladatom során merült fel, hogy egy java program kimenetét kellett böngészőben megjeleníteni. A program bemenetként egy UTF-8 kódolású XML fájlt kapott, fel sem merült bennem, hogy gond lehet a kódolással.

Meglepetésemre a program kimenetén minden ékezetes karaktert szorgalmasan kicserélt egy-egy kérdőjelre. Néhány óra bogarászás és kutatás után kiderült, hogy a Java belső kódolásként [[http://hu.wikipedia.org/wiki/UCS|UCS]]-t használ, minden bemenetet erre konvertál, és ebből alakítja át a kimenetet a megfelelő kódolásra.

További kutatással sikerült egy egyszerű módot találnom, amivel beállíthatom a sztandard kimenet kódolását. UTF-8 beállításához a következő néhány sorral kell kezdeni a main() függvényt:


try{
PrintStream out = new PrintStream(System.out,true,"UTF-8");
System.setOut(out);
}catch(Exception e){}

Rövid magyarázat: a PrintStream osztály egy egyszerű szűrőként dolgozik, ami a bemenetét UTF-8-ra átkódolva adja tovább a megadott Stream-re (jelen esetben a System.out). Ezután beállítjuk a létrehozott Stream-et alapértelmezett kimenetként. Voilá. Minden további kimenet UTF-8 kódolású lesz.

HP ipaq rx3715 és Linux

Érdekes, és mint kiderült, kissé veszélyes játékba fogtam ma. Miután feladtam, hogy értelmesen összerakjam a M$ Windows Mobile 2003 SE rendszert, eldöntöttem, hogy lesz ami lesz, kipróbálom a linuxot rajta az [[http://www.handhelds.org/moin/moin.cgi/HpIpaqRx3715InstallFromUbuntu|itt]] található leírás alapján.

Érdekes, és mint kiderült, kissé veszélyes játékba fogtam ma. Miután feladtam, hogy értelmesen összerakjam a M$ Windows Mobile 2003 SE rendszert, eldöntöttem, hogy lesz ami lesz, kipróbálom a linuxot rajta az [[http://www.handhelds.org/moin/moin.cgi/HpIpaqRx3715InstallFromUbuntu|itt]] található leírás alapján.

Az első nehézség nem is ezzel volt kapcsolatos, életem legnagyobb bakiját sikerült elkövetnem, és csak a szerencsén múlott, hogy helyre tudtam hozni. A tanulság: mielött beletörölsz a particíós táblába, alaposan nézd meg, hogy melyik lemezzel teszed. Én nem tettem meg, és mivel az említett tutorial /dev/sda-ról beszél, vidáman beírtam a végzetes “sudo fdisk /dev/sda” sort, és gondolkodás nélkül irtam át a partíciós táblát. Mielött magamhoz tértem, a GRUB zavarbaejtő “Error 17” üzenetével találtam szembe magam. Szerencsére találtam a fiók alján egy linux lemezt, amivel helyrehoztam. Pánik vége. Rövid pihenő, egy erős tea, folytassuk.

A fenti égő de tanulságos baki után nem ütköztem komolyabb ellenállásba a telepítés során. Feszült koncentrációval és minden lépést alaposan átgondolva sikeresen particionáltam az SD kártyámat, és felmásoltam a szükséges fájlokat. Pár pillanat múlva a PDA képernyőjén biztató apróbetűs konzol jelent meg, és azon boot-szagú feliratok. Rövid várakozás után pedig a hőn áhított [[http://opie.handhelds.org|OPIE]] felülete fogadott. Bizakodással és az izgalomtól remegő kézzel ragadtam meg a stylus-t, és kezdtem meg bátortalan lépéseimet az ismeretlen rendszerben. Az első kellemetlenség, ami megzavarta az újdonság izgalmában úszó lelkemet, az a nyílvánvaló tény, hogy bizony a képernyő fekvő helyzetbe van fordítva. Hamar megtaláltam a menüben a “rotate screen” feliratú gombot, ami a kecsegtető hangvétel ellenére a várakozással tökéletesen ellentétes irányba, immár fejjel lefelé fordította a képernyőt. Ez legyen e legkisebb probléma, gondoltam, ha más működik. Azonban további csalódásoknak lettem kitéve. Csak hogy párat említsek a WLan egyáltalán nem működik, a Bluetooth hasonlóképp, és komoly nehézséget okoz a ciril betűs képernyőklaviatúra.

De persze sikereket is értem el, némi szenvedés árán sikerült hálózatba kötnöm a laptopommal usb-n keresztűl. Így sikerült pár srceenshotot töltenem le a kütyüről, amiket a beépített képlopóval csináltam (ügyes, és nagyon hasznos kis eszköz). Általánosságban az interfésszel jók a tapasztalataim, a naptár alkalmazás, jegyzetelés, és dokumentumok kezelése határozottan jobb, mint amivel eddig WM kapcsán összefutottam.

Végeredményben eredményes kisérletet zártam, bár a komoly hiányosságok miatt egyelőre nem jelent használható alternatívát. Íme pár screenshot a miheztartás végett:

Az első képernyő
Az OPIE rendszer kellemesen lágy vonalai fogadtak induláskor.

Konzol
Beépített konzol, és a top program mutatja a rendszer terhelését.

Benchmark
Még egy beépített eszköz: leméri a PDA egyes elemeinek a teljesítményét, ami összehasonlítható más kütyük méréseivel.

Ciril betűk
Zavarbaejtő, mi több, kellemetlen. Ciril betűk a klaviatúrán.

Utóirat: közben megtaláltam a megfelelő beállítást, így már egy sokkal kellemesebb angol billentyűzet fogad, sőt, magyar kiosztást is tartalmaz.

Freemail problémára megoldást keresek

Érdekes problémával találkoztam a freemail kapcsán. Úgy nagyjából az előző egy-másfél hónaptól kezdve a Mail folyton panaszkodik, hogy nem fogadja el a freemail a jelszót, hiába adom be újból és újból, folyton előjön a probléma. Persze ez nem jelenti azt, hogy a jelszó el van írva, mert máskor simán belép.

Nem értem… A beállításokat ellenőriztem, azok stimmelnek (stimmelniük is kell, hiszen van, amikor megy). Esetleg más tapasztalt hasonlókat (esetleg más klienssel hasonlókat)? Ha igen, talált-e rá megoldást?

Érdekes problémával találkoztam a freemail kapcsán. Úgy nagyjából az előző egy-másfél hónaptól kezdve a Mail folyton panaszkodik, hogy nem fogadja el a freemail a jelszót, hiába adom be újból és újból, folyton előjön a probléma. Persze ez nem jelenti azt, hogy a jelszó el van írva, mert máskor simán belép.

Nem értem… A beállításokat ellenőriztem, azok stimmelnek (stimmelniük is kell, hiszen van, amikor megy). Esetleg más tapasztalt hasonlókat (esetleg más klienssel hasonlókat)? Ha igen, talált-e rá megoldást?

Sokat segítene ez az információ nekem, ezért kérem, hogy aki tud segíteni, az tegye meg. Kellemetlen lenne ezeket a címeket migráltatni valami másra – és már ebben gondolkozom…