2013. május 20., hétfő

Út a szőlőbe

Biztosan sokan voltatok már úgy egy-egy éjszakába nyúló debugolás közben, hogy most leteszitek a billentyűzetet, és soha többet nem veszitek a kezetekbe. Esetleg vesztek ezer birkát, és elmentek birkapásztornak Írországba. Legtöbbünknek ez azonban csak álom marad, és újra visszatérünk a fejlesztés néha egyhangú, néha azonban sok izgalmat kínáló világába. Viszont van közülünk, aki tényleg megtette, egy fiatal, nagyon tehetséges fejlesztő, egy ifjú titán, aki felhagyott eddigi életével, hivatásával, elköltözött Pestről a Balatonra, a Szent György-hegyre, hogy vidéki szőlész-borász legyen. Olvassátok szeretettel a blogját erről az útról, és drukkoljunk együtt neki.

2013. március 25., hétfő

Szuperdiák Verseny

A Mark My Professzor oldal Szuperdiák Versenyt szervez olyan hallgatóknak, akik Javát tanulnak vagy tanultak. A jelentkezéshez mindössze egy önéletrajzot kell elküldeni. Ezután egy szakmai zsűri választja ki a döntőbe jutottakat, ahol Java programozással kapcsolatos feladatot kapnak. A legjobb diákokat Apple termékekkel díjazzák. A rendezvény helyszíne a Miskolci Egyetem, ahová a döntőbe jutott, nem miskolci diákok útiköltségét fedezik. A verseny jelentkezési határideje 2013. április 10., időpontja 2013. április 17., további információk a http://markmyprofessor.com/szuperdiak.html címen érhetőek el.

2013. március 17., vasárnap

JPA több one-to-many kapcsolat

Felhasznált technológiák: Spring 3.2.2, Hibernate 4.1.10

Már írtam egy postot a JPA teljesítményhangolásával, valamint a lazy loadinggal kapcsolatban. Ott egy entitáshoz egy másik kapcsolódott, one-to-many kapcsolattal. Ott folytatom, ahol abbahagytam, de most egy entitáshoz két másik entitás kapcsolódik ugyanazon, one-to-many kapcsolattal. Egyrészt megvizsgálom a Hibernate egy jellegzetes hibaüzenetét, valamint elemzek több megoldást is performancia szempontból.

Az adatmodell a következő osztálydiagramon látható. Egy Employee példányhoz több Phone és több Address példány kapcsolódik.

A posthoz tartozó példaprogram letölthető a GitHub-ról. A projekt letöltése után az 'mvn test' paranccsal futtatható a teszt eset. Ez egy JUnit teszt eset, mely felépíti a Spring contextet, elindít egy beépített HSQLDB adatbázis-kezelőt, létrehozza a táblákat, feltölti adatokkal, majd meghívja a service-t, mely JPA lekérdezéseket használ, és a visszatérési értéket Hamcresttel ellenőrzi. A projekt ebben a postban bemutatott legutolsó megoldást tartalmazza, de megjegyzésben ott van a többi megoldás is.

Amennyiben elkészítjük a három entitást, és csak a kötelező annotációkkal látjuk el, és azok kötelező paramétereivel, a következő kivételt kapjuk: "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: jtechlog.descartes.Employee.phones, could not initialize proxy - no Session". Az előző postból tudhatjuk, hogy ez azért van, mert a @OneToMany annotáció használatakor a kapcsolódó entitásokat csak akkor tölti be, mikor szükség van rá (default a lazy loading). De mivel a teszt eset kéri le először a kapcsolódó entitásokat, a persistence context már zárva, a session zárva, így a Hibernate ezeket már nem tudja lekérdezni.

Első megoldás, mely eszünkbe juthat, hogy egészítsük ki a @OneToMany annotációkat a fetch = FetchType.EAGER paraméterrel. Ekkor a következő kivételt kapjuk, már akkor, mikor elindul a Hibernate: "Deploy time: Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags".

Ennek az az oka, hogy a Hibernate ebben az esetben egy joint tartalmazó select utasítást ad ki, és nem tudja kiválasztani, hogy melyik rekord melyik entitáshoz tartozik. A select a következő.

SELECT ...
FROM Employee employee0_
LEFT OUTER JOIN Address addresses1_ 
  ON employee0_.id = addresses1_.employee_id
LEFT OUTER JOIN Phone phones2_ 
  ON employee0_.id = phones2_.employee_id
WHERE employee0_.id = ?

Ezen kivétel mögött igen nagy irodalom áll, és több megoldási javaslatot is találhatunk. Egyrészt használjuk a Hibernate @IndexColumn annotációját, vagy ha nem akarunk provider függőek lenni, akkor a JPA 2.0-ban megjelent szabványos @OrderColumn annotációt. Ezt a @OneToMany annotációk mellé kell tenni, valamint a phone és az address táblába kell egy-egy új mező, mely az adott entitás listában elfoglalt pozícióját jelzi, és a JPA provider automatikusan karbantartja (, ahogy a példaprogramban is látható).

A másik megoldás, hogy mind a két esetben a List típust átírjuk Set-re. Az előbbi és ezen megoldás esetében is megmarad a join a lekérdezésben.

Van még egy megoldás. A @OneToMany annotációk mellé Hibernate specifikus @Fetch annotációt helyezünk el. Ez azt mondja meg, hogy a kapcsolódó rekordokat hogyan töltse be. Paraméterként több módot is meg lehet adni, az alapértelmezett mód a fentebb leírt JOIN, de használhatunk SELECT vagy SUBSELECT értékeket is.

Mindkettő használata esetén a persistence provider három select utasítást ad ki.

select ... from Employee employee0_ where employee0_.id=?
select ... from Phone phones0_ where phones0_.employee_id=?
select ... from Address addresses0_ where addresses0_.employee_id=?

Itt tehát a két mód között nem látszik különbség. Azonban ha azt a metódust nézzük, mely az összes Employee példányt visszaadja (findEmployees()), azonnal láthatjuk a különbséget. A SELECT mód esetén a phone és az address táblára annyi select utasítást ad ki, amennyi rekordot az employee tábla tartalmazott. A SUBSELECT mód esetén mindig három select utasítást futtat, méghozzá a következőket.

select ... from Employee employee0_ order by employee0_.id
select ... from Phone phones0_ 
  where phones0_.employee_id 
    in (select employee0_.id from Employee employee0_ )
select ... from Address addresses0_ 
  where addresses0_.employee_id 
    in (select employee0_.id from Employee employee0_ )

Láthattuk, hogy hogy működik az eager fetch esetén de én ezt nem szeretem használni, mert ilyenkor mindig eager jönnek le a kapcsolódó entitások, nem tudok választani. Viszont finomabban szabályozható, ha a lekérdezésben adom meg, hogy mit akarok betölteni. Erre a join fetch való. Írjuk is át a lekérdezést, hogy a következő lekérdezést használja:

select distinct e from Employee e 
  join fetch e.phones 
  join fetch e.addresses where e.id = :id

A helyzet ugyanaz, mint az eager fetch esetén, MultipleBagFetchException-t kapunk. Persze megint átállhatunk Set-re, és ekkor ugyanoda lyukadunk, hogy joint tartalmazó select utasítást kapunk. Mi ezzel a probléma?

select distinct ... from Employee employee0_ 
  inner join Phone phones1_ 
    on employee0_.id=phones1_.employee_id 
  inner join Address addresses2_ 
    on employee0_.id=addresses2_.employee_id 
  where employee0_.id=?

Igen, jól látható, hogy a fenti select utasítás eredménye egy Descartes-szorzat. Azaz ha a phone táblában van tíz rekord, és a address táblában is van tíz rekord egy adott employee rekordhoz, a lekérdezés száz rekordot fog visszaadni. Ez a probléma az eager fetch-nél is fennáll JOIN mód esetén.

Mi lehet erre a megoldás? Tudjuk azt, hogy amíg él a persistence context, addig a JPA provider a memóriában tárolja, hogy mik lettek betöltve, és azokat nem kéri be újra. Tehát egyrészt lekérdezzük az Employee entitást joinnal összekötve a Phone entitásokkal, majd egy külön lekérdezésben az Employee entitást joinnal összekötve az Adress entitásokkal. Ez a következőkben látszik.

@Transactional(readOnly = true)
public Employee findEmployeeById(long id) {
    em.createQuery("select e from Employee e " +
      "join fetch e.phones where e.id = :id", Employee.class)
        .setParameter("id", id)
        .getSingleResult();
    return em.createQuery("select e from Employee e " +
      "join fetch e.addresses where e.id = :id", Employee.class)
        .setParameter("id", id)
        .getSingleResult();
    }

Megfigyelhetjük, hogy az első lekérdezés eredményével nem csinálunk semmit. Csupán csak arra való, hogy az Employee és a Phone entitásokat a persistence contextbe töltse. A második query igaz, hogy csak a Address entitásokat kéri le, de mivel a Phone entitások már a persistence contextben vannak, hozzáköti őket. Ehhez persze kell a @Transactional annotáció (readOnly = true paraméterrel a sebesség érdekében), különben mindkét lekérdezéshez külön persistence contextet nyitna, így ugyanúgy LazyInitializationException lenne a jutalmunk. A lefuttatott két select utasítás a következő.

select ... from Employee employee0_ 
  inner join Phone phones1_ 
    on employee0_.id=phones1_.employee_id where employee0_.id=?
select ... from Employee employee0_ 
  inner join Address addresses1_ 
    on employee0_.id=addresses1_.employee_id where employee0_.id=?

Látható, hogy két select fut le, mindegyik eredménye tíz-tíz rekord, szemben a join változattal, ahogy egy select adott vissza száz rekordot.

A performancia hangolás érdekében még jó tisztában lenni a kiadható hintekkel is, mely persistence providerenként más és más, Hibernate esetén hasznos lehet a "org.hibernate.fetchSize" hint, amivel azt állíthatjuk be, hogy hány rekordonként forduljon az adatbázishoz, azaz egyszerre mennyi rekord menjen át Java oldalra. Ennek használatával sikerült akár kétszeres sebességjavulást is elérnem.

2013. február 2., szombat

Az Apache Flex múltja, jelene, jövője

Technológiák: Apache Flex 4.9.0

Sokakat megosztó témáról fogok írni, méghozzá a felhasználói felület technológiákat illetően. Ezeken belül is az Apache Flex a vizsgálat tárgya. Próbálok elfogulatlan maradni, de bizonyos kérdésekben óhatatlanul szubjektív leszek. Akár egyetértesz, akár nem, kérlek oszd meg a véleményedet a megjegyzések között.

A post apropója, hogy az utóbbi pár évben több projektben is használnom kellett az Flexet, valamint érdekelnek és folyamatosan nyomon követem, hogy felhasználói felületek fejlesztésére milyen technológiák vannak, melyek könnyen illeszthetőek a Java platformhoz. A Flex 4.9.0 új verziója 2012. decemberében jelent meg. Ez már a második kiadás, mely új fejlesztéseket is tartalmaz. Az Adobe 2011 novemberében jelentette be, hogy az Apache közösségnek adja a Flex SDK forráskódját. A 4.8.0 verzió még Apache incubator projektként jött ki, az Apache Licence v2 alatt, és nagy újdonságot még nem tartalmazott, főleg az átadás lett formalizálva. Az új verzió azonban már un. top level projectként jött ki. Sőt a cikk írásának pillanatában élesítették az új oldalt is.

A Flex világra jöttét a RIA (Rich Internet Application) segítette, azaz a cégek olyan eszközöket próbáltak előállítani, melyekkel a desktop alkalmazásokhoz hasonló gazdag felhasználói élményt nyújtó webes alkalmazásokat lehetett készíteni. A Flex eredetileg a Macromedia terméke volt, melyet az Adobe megvásárolt. A Flex 1.0 és 1.5 még komoly szerver oldali komponensekkel járt, de már jelen volt a megjelenítést leíró MXML XML alapú nyelv (Macromedia vagy Magic XML?) és a model és a controller komponensek megírására való ActionScript. A Flex 2 esetén azonban az SDK ingyenesen letölthető volt, csupán a fejlesztőeszközért, a Flex Builder-ért kellett fizetni (, mely Eclipse alapokra épült). Ebben a verzióban már nem volt szükség szerver oldali komponensre, lokálisan buildelhető volt az SWF fájl. A Flex 2-ben került bevezetésre az ActionScript 3 nyelv. A futtatókörnyezete a Flash Player volt.

A Flex 3 SDK már Mozilla Public License alatt jött ki, és itt jelent meg az AIR (Adobe Integrated Runtime) támogatása. Az AIR nem más, mint egy futtatókörnyezet, mely képes a Flash, Flex alkalmazásokat különböző operációs rendszereken futtatni, desktop alkalmazásként. Sőt, mobilra is elérhető. Az AIR-be telepített alkalmazások persze már több jogosultsággal rendelkeznek, mint a böngészőben futó társaik, pl. elérik a fájlrendszert, nyomtatót, vágólapot, stb. Rendelkezik egy beépített adatbázis kezelővel (SQLite), valamint egy WebKit alapú böngésző komponenssel is. 2010 márciusában jött ki a Flex 4, melynek fejlesztőkörnyezete már Flash Builder néven futott. Fő újítása, hogy megpróbálták közelebb hozni a designert és a fejlesztőt, hogy az előbbi által készített munkák újrafelhasználhatóak legyenek. Lehetővé tette a komponensek egyszerűbb skinezhetőségét is (megjelentek a Spark komponensek). A Flash Builder Premium verziójában már unit tesztelésre alkalmas eszköz is megjelent. A Flex 4.5 újításai a különböző mobil eszközökre való fejlesztést tették lehetővé (Android, BlackBerry Tablet OS és Apple iOS).

A Flex tehát élt és virágzott, mikor az Adobe sokak meglepetésére az Apache-nak adta a Flex SDK-t. Az ok talán a HTML 5 térnyerése volt, melyet az Adobe is jó iránynak tart. Valamint a Flash platformot akarják speciálisabb irányba vinni, úgymint a játékok (3d támogatás), valamint a prémium kategóriás videólejátszás. Az Adobe azonban nem temeti a Flexet, a nagyvállalati alkalmazások elsődleges platformjaként gondol rá. A nagyvállalati alkalmazásfejlesztésben az érvek a Flex mellett a következők:

  • Gazdag felhasználói felület építhető, mely nem mellesleg tehermentesíti a szerver oldalt.
  • Gazdag komponenskészlet, és a komponensek újrafelhasználhatósága a magas fejlesztői produktivitásért.
  • Jó beépített és 3rd party komponensek: pl. charting, data visualization, dashboard, OLAP, stb.
  • A MVC modell és a binding-ok miatt rendkívül alkalmas data driven alkalmazások kifejlesztésére.
  • Modularizáció.
  • Nagyvállalati fejlesztésre alkalmas ActionScript nyelv és egységes futtatókörnyezet.
  • Nagyvállalati technológiákhoz, mint Java EE, .NET könnyen illeszthető.
  • Kifinomult unit és integrációs teszt eszközök.
  • Parancssori alkalmazások (fordító, parancssorból futtatható teszt framework) segítségével könnyen illeszthető continuous integration környezetbe.
  • Fejlett fejlesztőeszközök (IDE kódszerkesztésre, debug, profile, test, stb.).

Talán érdemes egy kicsit azon elmerengeni, hogy miért is jó az ActionScript nyelv, és a sokak által szidott Flash Player vagy AIR környezet. Az ActionScript egy ECMAScript 262 Edition 4 (ES4) szabványon alapuló imperatív, biztonságos, szigorúan típusos, objektumorientált nyelv. Ennek az ECMAScript változat fejlesztése megszakadt, mindenféle csatározások miatt. A mostani böngészők által értelmezett JavaScript amúgy az Edition 5-nek felel meg, és talán már dolgoznak a következő változaton (Harmony). Fontos megjegyezeni, hogy az Adobe aktívan részt vett az ECMAScript szabványok specifikálásában. Az ActionScript ActionScript Byte Code-ra fordul (ABC). A lefordított ActionScript és MXML vagy SWC állományba állítható össze (ShockWave Component) - mely később az SWF-be építhető, vagy közvetlenül SWF állományba (ShockWave File). Ezeket a formátumokat az Open Screen Project keretében tette az Adobe nyílt formátummá). Ide tartozik még az AMF (Action Message Format) is, mely bináris formátum az ActionScript objektumok hálózaton átvitelére. A fordításkor nyert bájtkód azonban visszafejthető (decompile), obfuszkátorok használata jelenthet részleges megoldást. Ezt a bájtkódot futtatja a Flash Playerbe, vagy az AIR-be épített virtuális gép. Érdekesség, hogy ezekben két virtuális gép van. Az AVM1 az ActionScript 2, míg az AVM2 az ActionScript 3 forrásból fordított bájtkódot futtatja. Az AVM2-ből az Adobe a virtuális gépet, és a benne lévő JIT (Just in time compile-ert) 2006-ban a Mozilla Foundation számára átadta (Tamarin), így nyílt forráskódú. Modern VM-ről beszélünk, hiszen a JIT-tel (, ami futás közben az adott platform gépi kódjára fordít) hatalmas sebességnövekedést értek el (és bevezetésekor a JavaScript interpreterekbe még nem volt ilyen), valamint komplex szemétgyűjtővel is rendelkezik. Érdekes még a nyelvi szintű XML támogatás is, mely szintén szabványon alapul: ECMA-357, azaz ECMAScript for XML (E4X). A virtuális gép használatával nem kell a platformok különbségeivel foglalkozni, a kód hordozható marad közöttük.

Az Adobe közzétette a terveit a Flex jövőjével kapcsolatban. Továbbra is teljes állású fejlesztőket biztosít a Flex továbbfejlesztésére. Valamint a Flash Buildert továbbra is kereskedelmi termékként árulja, és frissíti, hogy együttműködjön az Apache Flexszel . Az Adobe ígéri, hogy a további öt évben megőrzi a Flash Player és az AIR visszafele kompatibilitását, azaz hogy továbbra is lehessen ezen futtatókörnyezetekben Flex alkalmazást futtatni. Azonban új funkciókat már nem tesz ezekbe a környezetekbe a Flex támogatására.

(Zárójelben jegyzem meg, hogy érdemes elolvasni az Adobe terveit a Flash platformmal kapcsolatban, mely magában foglalja a Flash Playert és az AIR-t. Természetesen mindkettőt viszi tovább a Windows platformon, és sok ellentétes állítással szemben Apple OS X-en is. Sőt, Adobe AIR alkalmazásokat Mac App Store-on keresztül is lehet értékesíteni. A Linux már kényesebb terület. Az Adobe együtt dolgozik a Google-lel a PPAPI - kódnevén "Pepper" kialakításán, mely egy közbülső réteg a böngésző és a különböző pluginok között. A Flash Player azon verzióját, mely ezen az API-n alapszik, a Google a Chrome-ba beágyazva terjeszti. A Google ezen technológiával sokkal biztosabb működést tud elérni, hiszen a plugin összeomlása nem vonja magával a böngésző összeomlását is. Az Adobe Linuxon a Flash Playert más formában nem fejleszti. Sőt, az AIR Linux-os fejlesztésével is leáll. Természetesen a mobil az továbbra is célterület, de kizárólag az Adobe AIR környezetben gondolkozik, de az összes fontosabb platformon - Android, iOS, Blackberry. Az Android browser plugint befejezi, szintén csak a Chrome-os megoldás marad.)

Nézzük merre tart az Apache fejlesztés. Az Adobe a következőket adta át:

  • A Flex SDK, mely legfőképp az osztálykönyvtárakat és a fordítót tartalmazza, valamint további eszközöket.
  • A Falcon következő generációs ActionScript fordítót.
  • A Falcon JS kísérleti fordítót, mely nem Adobe futtatókörnyezetre, hanem JavaScriptre fordít.
  • A Mustella funkcionális tesztelésre szolgáló keretrendszert.
  • Dolgoznak a BlazeDS átadásán is. Jelenleg a SourceForge-on elérhető LGPL alatt. A BlazeDS egy Java szerver oldali technológia, mely lehetővé teszi a Java szerver oldal és a Flex kliens oldal kommunikációját. Olyan kiváló képességekkel rendelkezik, mint különböző csatornák használata (http, https), Java és ActionScript objektumok automatikus mappelése, publish&subscribe kliensek között, szerver által kezdeményezett kommunikáció, JMS támogatás, Spring integráció. Úgy kell elképzelni, mint egy Flex-ből indított Java metódushívást. A kommunikáció a már említett AMF-ben történik. A BlazeDS korábban a Adobe LiveCycle Data Services ES része volt.
  • Text Layout Framework 3.0.33

A fejlesztés mögött a Open Spoon Foundation szervezet is ott áll. A 4.8.0-ban tehát eltávolításra kerültek a trademark bejegyzések, migrálva lett az Adobe issue trackerje JIRA-ra. A 4.9.0 SDK-t már Java 7-tel is lehet fordítani, és jelentős számú hibajavítást tartalmaz. A közösség nagyon pörög. Kijött az új weboldal, a Apache Flex SDK Installer 2.0. A dokumentáció Confluence Wikiben olvasható. Az újdonságokat a blogon lehet követni. A levelezési lista is nagyon aktív, a fejlesztői listán csak decemberben több, mint 1800 levél ment.

Tervek között szerepel még a forráskód Subversion-ről GIT-re átállítása, Maven plugin fejlesztése, dolgoznak a Falcon és Falcon JS fordítón, új komponensek készülnek és fejlődik a tesztelés is.

Időközben az Adobe is kijött a Flash Builder 4.7.0-val, mely Apache Flex 4.8.0 támogatást tartalmaz. Azonban a kompatibilitási problémák miatt kivették a Design View-t, Data Centric Development Toolst és a Flash Catalist Workflowt.

Milyen más kliens oldali technológiák vannak, és mikor érdemes az Apache Flexet választani ezek közül? Az Oracle nyomul a JavaFX-szel, a Microsoftnak van egy próbálkozása a Silverlighttal, valamint ott a legnagyobb kihívó, a HTML5/CSS3/JavaScript (innentől csak HTML5-ként hivatkozok rá). A JavaFX még nem elég kiforrott technológia, nagyon változik, bizonytalan még a jövője. A Microsoft felől is ellentmondó hírek jönnek a Silverlighttal kapcsolatban, valamint a Java platformba nehezebben beilleszthető lenne. Versenyben marad tehát a HTML5 irány.

Abban az esetben, ha speciális követelményeket nem támasztó webes alkalmazásról beszélünk (pl. a legtöbb Interneten megjelenő startup), vagy a fejlesztők már otthonosan mozognak a HTML5 világában, a HTML5 lehet a megfelelő irány. Azonban a Java platformon nevelkedett fejlesztők számára, valamint főként intranetes nagyvállalati vagy a speciális igényekkel rendelkező alkalmazások fejlesztésére (pl. videó, adatvizualizáció) a Flex lehet a legjobb irány.

A Java fejlesztők számára sokkal egyszerűbb a Flex irányába továbblépni, mint a JavaScript felé. A szigorú típusosság, az objektumorientáltság, a komponensek használata mind e mellett szól. Aki ráadásul esetleg Swingezett is, még egyszerűbb az átállás. Azon keretrendszerekben, melyek Java technológiára épülnek, de HTML5 interfészt generálnak, nem nagyon hiszek. Ott van egy átfordítás, ráadásul két teljesen más célra kifejlesztett technológia között (ne feledjük a HTML dokumentumleíró nyelv!). A HTTP protokoll szintén hatalmas gát, a kérés-válasz alapúságával, a szöveges formátumával, a késleltetéseivel. A HTML 5 nagyon friss, nem hiszem, hogy nagyvállalati alkalmazások fejlesztésére már jó irány. Az Adobe irányt sokan gyűlölik, nagyrészt indokolatlanul. Benne van ebben az, hogy ez volt az első platform, melyben rettentő idegesítő reklámokat lehetett készíteni. A Flash Player stabilitásával is voltak/vannak gondok (tegyük hozzá, hogy bármiben lehet erőforrás pazarló alkalmazásokat fejleszteni). Steve Jobs is célként tűzte ki a Flash eltörlését, melyben szintén sok követője akadt. De azért nézzük végig ezt a fenti történetet. Az Adobe feltűnően sokat tett a nyílt forráskódért rajongó közösségért, valamint a szabványosítási folyamatokért. A technológiai választások is mind logikusak, ha megnézzük, sokban hasonlítanak a Java platformhoz.

Összegezve úgy gondolom, hogy Java alapú nagyvállalati alkalmazások felhasználói felületének fejlesztésére az egyik leghatékonyabb, legkézenfekvőbb irány a Flex. De igen, benne van, hogy pár év múlva vagy egy nagy közösség által használt elterjedt technológia lesz, de az is lehet, hogy végleg eltűnik. De ez nincs másképp más UI technológiával sem, a verseny még tart, és az Apache Flexnek még vannak esélyei.

2012. december 26., szerda

Java API for JSON processing

Úgy tűnik, az Oracle eléggé felpörgeti a Java EE 7 (JSR 342) körüli munkálatokat, sorra jönnek ki a hírek az előrehaladásról. Erre szükség is van, hiszen bár a határidőt eltolták 2012 harmadik negyedévéről 2013 első negyedévére, még elég sok specifikáció Early Draftban van.

A Java EE 7 újdonságai a JCACHE Java Temporary Caching API (JSR 107), Concurrency Utilities for Java EE (JSR 236), Java API for JSON Processing (JSR 353), Java API for WebSocket (JSR 356) , és a már említett Batch Applications for the Java Platform (JSR 352). A többi specifikáció nem új, hanem csak egy új verzió jön ki belőlük.

A mostani post témája a Java API for JSON Processing (JSR 353), melynek Public Review-ja 2012. december 22-től zajlik. Az JSR oldalán a megszokottakkal ellentétben semmilyen specifikáció nem olvasható, helyette csak az API-t lehet letölteni. Szerencsére a frissebb JCP-nek megfelelően a szabvány fejlesztése átlátható, minden információ megtalálható a projekt honlapján. Az API-t a Batch Applications for the Java Platform szabványhoz hasonlóan szintén újra feltalálták, méghozzá Jitendra Kotamraju (Oracle) vezetésével, bár a támogatók között van a FasterXML cég, mely a Jackson streaming JSON parser-ért felelős, valamint Doug Crockford, kinek nagy szerepe volt a JSON elterjesztésében. Mivel specifikációról beszélünk, az implementációk cserélhetőek lesznek (plug-in provider), és külön referencia implementációval is rendelkezik.

A JSON kezelés elég gyakori manapság, ezért kívánják szabványosítani a Java berkein belül. Azonban a JSON kezelést két részre kell felbontani. Az egyik a feldolgozás és parse-olás, a másik a binding, mely Java objektumokat feleltet meg JSON struktúrákkal. (Ez a kettősség fennáll az XML esetén is, az előbbire a JAXP, az utóbbira a JAXB ad megoldást.) A Java API for JSON processing csak az előbbivel foglalkozik, ráadásul kétféle módon. Egyrészt áll egy Streaming API-ból, mely a StAX API-hoz hasonlít, valamint egy Object model-ből, mely a DOM API-ra hajaz. A Streaming API csak olvasásra használatos, és a JsonParser interfész a kulcs, ami egy pull parser, azaz mi tudjuk irányítani a feldolgozást, pl. a next() metódus segítségével. Az Object model esetén a JsonReader és JsonWriter használandó, mellyel írni és olvasni is tudunk, és a DOM-hoz hasonlóan a teljes reprezentáció felépül a memóriában. Modern API-hoz méltóan hemzseg tervezési mintáktól. Ritkán fogunk vele közvetlenül találkozni, hiszen általában valamilyen binding megoldást használunk, de amennyiben mégis natívan akarunk JSON-t feldolgozni, a Java EE 7-től kezdődően már szabványos módon tehetjük.

2012. december 22., szombat

Oracle Certified Expert, Java EE 6 Web Services Developer

2012. december 12-én tettem le a Oracle Certified Expert, Java EE 6 Web Services Developer (1Z0-897) vizsgát. Alapvetően a webszolgáltatások (mind SOAP, mind REST) alapfogalmaira, és a JAX-WS 2.2 és JAX-RS 1.1 specifikációkra koncentrál. Ahogy már korábban írtam róla, ez a Oracle Certified Professional, Java (SE 5, SE 6, vagy SE 7) Programmer vizsgára épül, de még a régebbi SCJP-vel is letehető.

A vizsgát a Training360-nál tettem, ők intézték a regisztrációt is. A változatosság kedvéért ez most Pearson VUE-nál történik, küldik is utána szépen a tudnivalókat és a számlát levélben. A vizsga ára jelenleg 63 185 Ft. Hogy ne legyen olyan egyszerű, a Pearson VUE-nál is kell regisztrálni, utána az Oracle CertView programjában is, ugyanis csak ott tudom az eredményt megtekinteni.

A vizsga menete alapvetően változatlan, készítenek rólad egy fényképet, beülsz egy terembe hatodmagaddal egy gép elé minden nélkül, és sorban válaszolsz a feltett kérdésekre. Teszt jellegű, 60 kérdés van, 90 perc alatt kell megoldani, és 60%-ot kell elérni. Bejelölhetők a kérdések, hogy még vissza akarsz rájuk később térni, és bármikor kérheted, hogy vigyen végig újra a bejelölt, vagy az összes kérdéseken. A 90 perc elegendő, belefért, hogy nagyon alaposan végigmenjek az összes kérdésen, majd a bejelölteken, majd gyorsan még átnéztem újra az összeset (a végén már pár kimaradt). Annyi változott mostanság, hogy nem ott nyomtatják ki az eredményt előtted, hanem e-mailben kapsz egy értesítést, és egy PDF-et tudsz letölteni a CertView oldaláról. Gyakorlatilag amint kijöttem, már kaptam az értesítést, annak ellenére, hogy 30 perc türelmet kértek.

A vizsgára felkészülni az SCJP-hez képest sokkal nehezebb volt, hiszen az utóbbihoz rettentő mennyiségű anyag, mock exam, könyv áll rendelkezésre, itt gyakorlatilag csak egy Oracle tanfolyam áll rendelkezésre, aminek nem is teljesen ugyanaz a tematikája, és el sem végeztem. Az eredményben azonban látható, hogy mely témakörben hány kérdést tettek fel, számomra kicsit meglepő:

  • Legjobb gyakorlatok: 9 kérdés
  • RESTful webszolgáltatások: 5 kérdés
  • RESTful webszolgáltatások megvalósítása EJB-kkel: 3 kérdés
  • SOAP webszolgáltatások EJB-kkel: 4 kérdés
  • SOAP webszolgáltatások: 4 kérdés
  • Alacsony szintű SOAP webszolgáltatások (Dispatcher): 4 kérdés
  • Kliensek implementálása: 4 kérdés
  • Java EE webszolgáltatások konfigurációja, biztonság beállítása, telepítése: 8 kérdés
  • SOAP üzenetszintű biztonság: 7 kérdés
  • MTOM/MIME: 7 kérdés
  • WS-Addressing: 7 kérdés

A DOM, SAX, StaX technológiákról csak koncepcionális szinten esett szó, mikor melyiket kell használni, tudjunk a StaX pull parser-jéről. JAX-B kérdésre nem emlékszem. Számomra az volt meglepő, hogy érzésre rengeteg biztonsággal, MTOM-mal és WS-Addressing-gel kapcsolatos kérdés volt, amit ráadásul a különböző könyvek nem jól tárgyalnak. Övön alulinak éreztem a Jersey kliens használatára vonatkozó kérdést is, hiszen az meg nem a szabvány része.

Felkészülésként mindenképpen érdemes felkeresni a JavaRanch ide vonatkozó oldalát, valamint Mikalai Zaikin felkészítő anyagát, ami kicsit hiányos ugyan, de megéri elolvasni. Kereskedelmi felkészítő anyaga az EPractize-nak és a Whizlabs-nak van, én egyiket sem használtam.

A következő könyvekből készültem: már írtam Mark D. Hansen: SOA Using Java Web Services (Prentice Hall) könyvéről, mely egy jó kiinduló alap, bár talán a vizsgához nem elég mély. SOAP fronton ezen kívül a Martin Kalin: Java Web Services Up and Running (O'Reilly) könyvből készültem. Ez utóbbi egy rendkívül jó könyv, és bár sokan ezt mondják magukról, ez tényleg gyakorlatias. Már az elején elmondja, hogy hogyan kell debugolni, hogy lehet a dróton átmenő üzenettartalmaz kiíratni, amit még egy könyvben sem láttam ilyen részletesen kifejtve, különböző operációs rendszereken. A felépítése is ilyen, szóval nem a specifikáció alapján, hanem egy természetes íve van, ahogy kellenek az újabb és újabb feature-ök. A mintapéldák sem voltak annyira mondvacsináltak. Egyedül az nem tetszett, ahogy mind a két könyv a REST-ről beszél, feltehetőleg akkr még nem volt ekkora hype, így egyrészt keveset írnak róla, másrészt a JAX-WS specifikációval próbálják megugrani, ami erre alkalmatlan, pláne a JAX-RS-hez hasonlítva. Az utóbbi könyv említi ugyan a Jersey-t, de nagyon felületesen, ennél a vizsgára jóval több kell.

Ezen kívül a következő dokumentációkat érdemes elolvasni. A Metro projekt dokumentációját mindenképp a security, MTOM, WSIT, WS-Addressing fejezetek miatt, máshol erre nem találunk jó dokumentációt. A Java EE 6 tutorial ide vonatkozó fejezete is elég rövid ahhoz, hogy érdemes legyen átlapozni. A SAAJ-ról ugyan nem ír, de az előző verzió igen. Amennyiben nem tiszta, hogy mi a különbség az RPC/Literal, Document/Literal, Wrapped Document/Literal között, itt egy gyakran idézett cikk. Ez a bejegyzés pedig a WS-Addressing használatáról ír a JAX-WS 2.1-ben.

A REST témával kapcsolatban a Bill Burke: RESTful Java with JAX-RS (O'Reilly) könyvet ajánlom. Kötelező olvasmány mindenkinek, aki JAX-RS-t fejleszt. Két részből áll. Az egyik leírja a teljes JAX-RS szabványt, 14 fejezetben, példákkal együtt, a másik pedig egy workbook, gyakorlatilag egy tutorial, 10 fejezeten keresztül. Olyan dolgokat mutatott be, melyek létezéséről nem is tudtam a JAX-RS-ben, mindezt példás részletességgel.

Még egy kis magyarázkodás, hogy mi értelme is volt letenni a vizsgát, hiszen közvetlen előnye nincs. Egyrészt én oktatom ezt az anyagot, ezért kapóra jött, hogy egyúttal a vizsgát is leteszem. Másrészt nem árt egy kis vizsgadrukk, az ember munkakörnyezetben már ritkán kerül olyan helyzetbe, hogy egy nagyobb átfogó témakört ilyen alaposan fel kelljen dolgoznia, megtanulnia úgy, hogy még számonkérés is van, ezt a rutint sem szeretném elveszíteni. Persze a papírgyűjtés is motivál, újabb achivement. Ha a munkahely meg támogatja, akár a vizsgadíj megfizetésével, akár felkészülési idővel, egyszerűen bűn kihagyni.

A további rész azoknak hasznos, akik vagy komolyan foglalkoznak a témával, vagy le akarják tenni a vizsgát. Megpróbáltam minden fogalmat összeszedni, nekem volt egy vázlat. Talán egy öntesztnek sem utolsó, hogy tényleg tisztában vagy-e mindennel.

SOAP webszolgáltatások JAX-WS-sel

  • Java EE 6 2009. dec. 10-én jött ki: JAX-WS 2.2 (JSR 224), JAX-RS 1.1, Web Services Metadata for the Java Platform 2.0 (JSR 181), SOAP with Attachments API for Java (SAAJ) 1.3
  • MEP: Message Exchange Pattern, típusai: request/response, oneway, async callback, async polling
  • SOAP: 1.2-től kezdve nem rövidítés
  • WSDL felépítése: definitions, types: adattípusok definíciója, message: üzenetek defincíciója, message part-(ok)ból áll, portType: operációk halmaza, binding: protokoll és adatformátum specifikációk, pl. soap, ezen belül operáció, input-tal, output-tal, majd service, port: portType (interfész) és binding (implementáció összekapcsolása)
  • WS-I: csak RPC/literal vagy document, de az utóbbinál body-n belül csak max egy elem lehet
  • WS-I Basic Profile 1.1 egy dokumentum, mely a SOAP 1.1 és WSDL 1.1 szabványokat

Style és encoding

  • RPC/Literal
    • Paramétereket tartalmaz a híváshoz
    • Mindig wrapped
    • Wrapper element az operation neve
    • Állhat több part-ból az input message
    • Part mindig type attribútummal van deklarálva (szemben a document element-tel)
    • csak a part-ok vannak a types részben leírva
    • Part-nak megfelelő elemek névtér nélkül
    • Válasz neve nem deklarált
  • Document/Literal
    • Dokumentumot tartalmaz a híváshoz
    • Lehet több part
    • Part mindig element-tel van megadva
    • A teljes body tartama a sémában van definiálva
    • Operation neve nem szerepel a soap üzenetben
    • Part-ok közvetlenül a body-ban vannak, nincs wrapper, névtérrel ellátottak
    • Response ugyanígy
  • Document/Literal wrapped
    • input message-nek csak egy gyereke van, a wrapper
    • element-ként leírva, sémával meghatározva
    • konvenció szerint operation neve = wrapper neve
    • ugyanígy a response-nál is, konvenció szerint a wrapper neve az operation neve + "Response"

JAX-WS

  • SEI
  • Kötelező: SIB
  • Nem muszáj a SIB-nek implementálnia a SEI-t, megadható az annotációban is, csak nem biztonságos -> futás idejű hiba
  • Ha annotációban sincs megadva, implicit SEI
  • Opcionális: SEI, WSDL, webservices.xml
  • Osztály, public, nem lehet final vagy abstract
  • Default public constructor-nak lennie kell, nem lehet finalize, nem tárolhat állapotot
  • Metódusai nem lehetnek static vagy final
  • Wsgen, wsimport
  • A JAX-WS 2.1.6-tól változott az implicit esetén, több esetben lesz kiajánlva a metódus
  • Explicit sei esetén az összes publikus metódust kiajánlja, a WebMethod csak további konfigurációkra való
  • A wsimport generál: SEI, service, fault-hoz tartozó osztályt, ha kell; paraméter osztályokat, ha kell; Async Reponse Bean, ha kell
  • external/embedded binding declaration: sei, exception, service neve, package neve, wrapper style
  • JAXB: sémában annotation/appinfo tag-en belül
  • JAX-WS kliens: Service.create(url, qname); service.getPort(SEI.class);
  • Deploy JDK-ban: Endpoint.publish, egyszálú
  • Default: Wrapped Document/Literal, RPC: @SOAPBinding(style = Style.RPC)
  • @WebService annotáció targetNamespace attribútuma adja meg a névteret, amúgy a package alapján
  • @RequestWrapper, @ResponseWrapper
  • WebParam.Mode.OUT, Holder
  • Ne wrapper-ek legyenek: customized binding, enableWrapperStyle
  • @SoapBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
  • Ha aszinkron klienst akarunk, akkor ismét customized binding: enableAsyncMapping
  • AsyncHandler
  • Response
  • wsimport -extension: SOAP 1.2 esetén
  • Overload-olt metódusok esetén problémás

Dynamic Invocation Interface (DII)

  • Dispatcher, Provider
  • @WebServiceProvider
  • public Source invoke(Source)
  • @ServiceMode: PAYLOAD - csak a tartalom, MESSAGE - az egész http kérés, fejlécestől
  • @BindingType() - http
  • Dispatch - Service.createDispatch
  • Https: HttpsURLConnection, HttpsServer
  • @WebService-t felismeri a Glassfish, de a @WebServiceProvider-t nem

Handler

  • Chain of responsibility tervezési minta
  • Logical handler: Source, JAXB - protokollfüggetlen - csak a payload-hoz tud hozzáférni
  • SOAP/protocol handler: SOAP, SAAJ, hozzáfér a teljes envelope-hoz
  • Kliens oldalon a handler chain-ben nem csak a konfig sorrend dönt, hanem előbb futnak le a logical handler-ek, és csak utána a soap handler-ek
  • Programozottan handler hozzáadása: HandlerResolver
  • SOAPFaultException
  • SOAP 1.2: BindingType annotáció
  • SOAP 1.2: mustUnderstand
  • Szerver oldalon: WebServiceContext.getMessageContext -> hozzáférés a context-hez (map), és abból a http header-ökhöz
  • Kliens oldalon: a port BindingProvider-ré cast-olható, van getRequestContext metódusa
  • Dependency injection: WebServiceContext

MTOM

  • MTOM: XSD, @BindingType, publikálásnál: ((SOAPBinding) endpoint.getBinding()).setMTOMEnabled(true);
  • Kliens: activation.DataHandler
  • Kliens file küldés: ((SOAPBinding)((BindingProvider) port).getBinding()).setMTOMEnabled(true);
  • @MTOM annotáció

WSIT

  • Metro: azon része mely az MS-sel való együttműködés: WSIT - Webservice Interoperability Technologies - Security, Reliability, Transaction, bootstrapping, optimalization (régen project Tango)
  • Bootstrapping: WS-MetadataExchange
  • Reliable messaging: egyszeri, pontosan egyszeri üzenettovábbítás - acknowledge-al, sorrend (opcionálisan bekapcsolható)
  • Atomic: AtomicTransaction, Coordination

Security

  • XML and WebServices Security Project (XWSS)
  • WS-Security: message content integrity and confidentality, Prompter, Verifier implements CallbackHandler
  • WS-Security (x) felett: WS-Policy felette WS-SecurityPolicy (x), WS-PolicyAttachment (x), WS-Trust (x), WS-Privacy, afelett WS-Secure Conversation (x), WS-Federation, WS-Authorization
  • WS-Secure conversation - shared security context, több kérés/válasz esetén nem kell mindig az összes security információt küldeni - new security token type
  • Trust: security token
  • SecurityPolicy, mely a Policy-ra épül: security követelmények és tulajdonságok leírására
  • WS-Trust: security token, Security Token Service - STS, az STS SAML tokent küld a kliensnek
  • Signing and encription: WSDL-be plusz tag-ek

WS-Addressing

  • WS-Addressing: protokollfüggetlen címzés
  • Kettő spec van: W3C WS-Addressing, Member Submission WS-Addressing, a Metro mindkettőt támogatja
  • Standard tag-ek: To, From, ReplyTo, FaultTo, MessageID, Action, RealtesTo
  • Végpont referencia: EPR
  • MI header: message information
  • Message Addressing Properties (MAPs)
  • Anonymous uri: nem címezhető, pl. request/response request párja
  • Annotáció: @javax.xml.ws.soap.Addressing, @Action, @FaultAction
  • WSDL-ben: wsdl11:port vagy wsdl11:binding tag-be új tag
  • Kliens oldal: WebServiceFeature -> AddressingFeature
  • BindingProvider.SOAPACTION_URI_PROPERTY-t kell kliens oldalon beállítani
  • Két paraméter: enabled, required

SAAJ

  • Új SOAPMessage létrehozásánál létrehozza a Part-ot, Envelope-ot és Header-t
  • Attachment Part, mime headers, Content
  • SOAPConnection
  • Attachment: Content-Type, -Id, -Location
  • Attachment setContent: String, stream, javax.xml.transform.Source vagy javax.activation.DataHandler
  • A SOAP 1.1 specifikáció közvetlenül a header-ben csak a következő attribútumokat engedi: actor and mustUnderstand
  • A SOAP 1.2 spec. ellenben: role (actor új neve), mustUnderstand, és relay
  • Ha van SOAPFault a Body-n belül, nem lehet más
  • code, string kötelező, lehet actor, SOAP 1.2-nél code, role, reasonText (locale-lal)
  • A kódok QName-ek - SOAP specifikáció definiálja

RESTful

  • Roy Fielding: Architectural Styles and the Design of Network-based Software Architectures, 2000 (HTTP specifikáció egyik írója), Apache Software Foundation egyik alapítója
  • Egyedileg címezhető erőforrások: resource, URI
  • Uniform, constrained interface for manipulate resources
  • Representation-oriented, content negotiation
  • Stateless
  • Hypermedia As The Engine Of Application State (HATEOAS): embedded links

JAX-RS

  • JAX-RS 1.1 (JSR 311)
  • Referencia implementáció: Jersey
  • POJO, annotation alapú
  • Annotációk öröklése: super-class előnyt élvez az interfészen lévővel szemben
  • Ha az implementáción van annotáció, akkor a többi helyen lévő annotációt nem veszi figyelembe
  • Application osztály, kiterjeszteni kell, osztályokat ad vissza, melyet a provider példányosít, illetve példányokat, melyeket singleton-ként használ. Mindkettőn elvégzi az injection-t.
  • Application erőforrásokat (@Path annotációval ellátott osztályokat), és provider-eket adhat vissza
  • A JAX-RS provider cserélhető, erre van a RuntimeDelegate, saját alkalmazásban nem kell használni

Provider

  • A provider, melyen rajta van a @Provider annotáció, és valamilyen JAX-WS interfészt implementál
  • Kell minimum egy publikus konstruktor, akár paraméterezett. Mindig a legtöbb paraméterrel rendelkező konstruktort választja
  • Provider pl. a MessageBodyReader, Writer
  • Provider pl. a ContextResolver, mellyel saját Context, pl. JAXBContext példányosítható
  • ExceptionMapper-ek is provider-ek

Context

  • Per request esetén nincs párhuzamossági probléma
  • Per request esetén attribútum is injektálható
  • Konstruktor paraméter mindig injektálható
  • A három első olvasó, aki ide eljut, vendégem egy sörre a következő JUM-on. Dobj egy e-mailt!
  • @Context annotációval injektálunk
  • A következőkbe injektálhatók: resource, provider, Application leszármazott
  • A következők injektálhatók: Application (önmagába nem), UriInfo, HttpHeaders, Request, SecurityContext, Providers
  • A Providers-en keresztül hozzá tudunk férni a MessageBodyReader, Writer-ekhez, ContextResolver-hez, ExceptionMapper-hez, azaz amit a Provider annotációval elláthatunk

Erőforrások

  • @Path
  • Root resource class: vagy @Path-tal annotált, vagy van legalább egy Path-tal vagy request method designatorral (@GET, stb.) annotált metódusa
  • Request method: request method designator-ral annotált metódus
  • Egy metóduson csak egy @GET, @PUT, stb. annotáció lehet, különben deployment error
  • A @HttpMethod annotáció egy metaannotáció, mely rajta van a @GET, stb. metódusokon
  • HEAD kérés esetén először @HEAD metódust keres, ha nincs, akkor a @GET-et hívja, csak nem ad Response-t
  • OPTIONS kérés először @OPTIONS metódust keres, ha nincs választ generál az annotációk alapján -> WADL
  • @ApplicationPath globális url megadásra, ehhez jön hozzá a resource-onkénti
  • A /{foo} path-ra nem illeszkedik a /foo/bar, de a /{foo: .+} path-ra igen (lásd perjelek értelmezése)
  • Amennyiben egy url több path-ra is illeszkedik, a provider a legpontosabbra próbálja illeszteni. Van egy nem minden esetet lefedő precedencia szabály, mely általában jó. Először a literálok számát nézi, majd a template-ek számát, majd a reguláris kifejezésekkel ellátott template-ek számát.
  • Nem minden karakter megengedett az uri-ban, valamint van, aminek speciális jelentése van. A többit escape-elni kell. A @Path annotációban nem kötelező escape-elni.
  • A subresource olyan POJO, melyhez egy resource POJO továbbítja a kiszolgálást. Nem kell rá @Path annotáció, hiszen nem a root uri-hoz képest figyel, valamint nem kell az Application osztályban regisztrálni.
  • Ha az illeszkedő path-ban két mátrix paraméter ugyanazon a néven szerepel, akkor PathSegment-et kell használni, mert nem egyértelmű a @MatrixParam injection. @PathParam List <PathSegment> formában
  • @FormParam esetén implicit dekódolás van, @Consumes("application/x-www-form-urlencoded")
  • Primitív típus, String mappelésén kívül minden olyan típust mappel, melynek van String paramétert váró konstruktora, vagy statikus valueOf metódusa String paraméterrel
  • Van automatikus collection konverzió
  • @HeaderParam, @CookieParam mappelési hiba esetén 400-as hiba, amúgy 404
  • @DefaultValue annotációval adhatjuk meg az alapértelmezett értékeket
  • @Encoded annotációval adhatjuk meg, hogy mi akarjuk dekódolni, tehát azt kapjuk, amit a HTTP ad, dekódolás nélkül

Content Handlers

  • A következő típusokat standard MessageBodyReader-ek és Writer-ek kezelik, ezek entity provider-ek
  • StreamingInput, StreamingOutput - callback model, általában performancia okokból jobb, ha a provider hív vissza (pl. lehet, hogy új szálon), valamint illeszkedik az aszinkron modellbe.
  • InputStream, Reader
  • File, byte[], String, char[] is használható input/output paraméterként
  • Activation DataSource is kezelendő
  • MultivaluedMap<String, String> form értékekhez, dekódolja a provider, használható az @Encoded annotáció
  • javax.xml.transform.Source, a Document-et nem definiálja a specifikáció
  • JAXB: XmlRootElement, XmlType annotációval jelölt osztályok és JAXBElement példányba burkolt objektumok leképzését is támogatja
  • JAXBContext-et tud példányosítani, de felüldefiniálhatjuk ContextResolver<JAXBContext>-ben (pluggable factories), amit az Application-ben definiálhatunk
  • JSON-höz nem kell speciális kezelés, egyedül a mime type-ot kell application/json-ként jelölni
  • Saját marshallinghoz: MessageBodyWriter, sorbarendezés, legjobb illesztés a mime type-ra, @Provider annotáció, @Produces annotáció
  • MessageBodyReader, @Provider, @Consumes annotáció
  • isWritable, isReadable - a paraméterként adott objektumot tudja-e kezelni (+generikus típus, annotáció, media type)

Response code, response, exception

  • ResponseBuilder-rel előállítható a Response
  • WebApplicationException saját kivétel
  • Megadható benne saját Response
  • Error vagy unchecked exception megy a konténer felé, a többit viszont be kell csomagolni, és úgy megy a konténer felé
  • ExceptionMapper a kivételek kezelésére, generikussal paraméterezhető, mindig a kivételre legjobban illeszkedőt keresi
  • ExceptionMapper-t a @Provider annotációval kell ellátni

Content Negotiation

  • @Produces, @Consumes, tehető resource-ra, metódusra, és a content handler-re is
  • Variant: media type, language, encoding
  • VariantListBuilder: builder

HATEOAS

  • UriBuilder URI-k összeállítására, template paraméter is használható
  • Az UriBuilder egy resource osztályt kapva parmaéterként is képes összeállítani az URI-t
  • UriInfo-val is létrehozható UriBuilder, ekkor adott a séma, szerver, port, context
  • Cache-elés a CacheControl osztályon keresztül, nincs rá annotáció
  • EntityTag osztály az ETag kezelésére
  • Szerver oldalon kezelni a If-Modified-Since vagy ETag header-eket: Request interfész (injektálható) evaluatePreconditions metódusai.
  • Nem csak cache-elésre használható, hanem konkurrencia kezelésre is, hogy csak akkor történjen a módosítás, ha nem változott az erőforrás

Deploy

  • Deploy: JAX-RS unaware konténerben egy servlet-et, és annak int-param-ként kell megadni az Application-t, aware konténerben az Application tehető közvetlenül a web.xml-be. Java EE 6-nál nem kell semmi az xml-be, classpath-t bejárja, és nézi az annotációkat.
  • @Context annotációval a ServletContext és a ServletConfig injektálható
  • Java EE 6 konténerben a szokásos dolgok injektálhatók: @Resource, @PersistenceContext, @PersistenceUnit, és @EJB, támogatja Java EE 6-ban a JSR-299 szabványt.
  • Java EE konténer által biztosított autentikáció és authorizáció adott. Programozott esetben a SecurityContext @Context annotációval injektálható

Kliens

  • Szabvány nem szól róla
  • Legegyszerűbb esetben HttpURLConnection
  • setDoOutput - request body-ba is lehet írni
  • Jersey Client API

Batch Application for the Java Platform (JSR 352)

A Java EE 7 szabványba tervezik beletenni a Batch Application for the Java Platform (JSR 352) szabványt is. Egy kicsit csúszásban vannak, 2012 első negyedévére tervezték a Public Review-t, de csak novemberre sikerült eljutni idáig, és nemrég, december 4-én lett elfogadva.

A szabvány a Java azon hiányosságát próbálja pótolni, hogy nem nyújtott egységes fogalomrendszert, modellt, leíró nyelvet és környezetet batch alkalmazások fejlesztésére, habár nagyvállalati környezetben az alkalmazások nagy része ilyen jellegű, és a technológia sem friss, hiszen ez a megállapítás már a Cobol alkalmazásokra is igaz volt, és már ott kialakultak az egységes fogalmak, best practice-ek. A batch feldolgozás általában nagy tömegű adattal dolgozó és/vagy számításigényes, nem interaktív, háttérben futó folyamat. Vagy az egész, vagy csak bizonyos részei párhuzamosíthatóak. Gyakori követelmények között szerepel a újraindíthatóság, checkpoint kezelés (leállás esetén honnan lehet újraindulni), párhuzamosság, naplózás, management. A specifikáció erre próbál standard megoldást adni, mind a Java, mind a Java EE környezetben, javax.batch csomagban lévő API-val. A negyedik fejezetben definiálja a fogalmakat, mely egy az egyben a Spring Batch felhasználói kézikönyvének idevágó fejezete. A Spring Batch egyedül itt van megemlítve hivatkozásképp.

A dolog érdekessége éppen ez. A specifikációt Chris Vignola készítette, aki az IBM színeiben versenyez, és ismeri annak technológiáját, mely a WebSphere Extended Deployment Compute Grid névet viseli. Azonban megvizsgálta a Spring Batch-t is, és arra jutott, hogy inkább azt veszi alapul. Azonban nem teljes mértékben, hanem bizonyos dolgokat átalakítva, átnevezve (pl. tasklet -> batchlet), bizonyos dolgokat elhagyva, és pár dolgot az IBM megoldásából beemelve. A vicces még az, hogy a referencia implementációt és a TCK-t is az IBM kívánja elkészíteni. Az IBM XML leírója (Job Specification Language) ebben a témában az xJCL nyelv, mely a régi JCL nyelv XML reinkarnációja, és elég egyszerűnek tűnik a Spring leírója mellett. A szabvány számomra meglehetősen szegényes a Spring Batch dokumentációjához képest. A csapatban amúgy szerepel képviselő a Spring oldaláról is.

Az elfogadás körül is voltak problémák, ugyanis az első verziót azért nem fogadta el két szereplő (London Java Community, Twitter, Inc.), mert nem felelt meg a JCP akkori (2.8) kívánalmainak, miszerint a JSR készítése legyen teljesen átlátható. A specifikáció körüli megbeszélések ugyanis privát levelezési listákon folytak. Ezt javították azzal, hogy a projekt immár követhető a Java.net-en. Most már el is lett fogadva a Public Review azzal a feltétellel, hogy az annotációk használatát a végleges verzióban közelíteni kell a Java EE konvenciókhoz, hiszen most jelentősen eltér attól. (A Java EE szerint minden konfigurálható annotációval és XML-lel is, amennyiben mindkettő meg van adva, az XML megadási mód nyer.)

Véleményem szerint teljesen logikátlan lépés az IBM ilyen erős jelenléte ebben a specifikációban, ha már a Spring Batch lett véve alapul. Érdekes, hogy erről alapvetően nem is lehet olvasni, a fórumon lehet egy két üzenetváltásból elcsípni, hogy a szerző tényleg mindkét megoldást alaposan megvizsgálta. Persze érthető, hogy az IBM-nek ebben a témában sokkal nagyobb a múltja és a részesedése is a rengeteg legacy rendszer miatt. Amennyiben azonban a közösség nem áll a specifikáció mögé, megy a Sun/Oracle többi elfelejtett próbálkozása közé (lásd pl. JDO).