2009. szeptember 8., kedd

@Autowired és társai

Mostanában gyakran beleakadok a spring framework @Autowired annotációjába, amit kifejezetten private mezőkre húztak rá, amin nincs setter sem. Pl...

@Autowired
private Datasource datasource;

Az a kifogásom ellene, hogy:
  • besettelni sem lehet neki valami mást
  • springen kívül nem lehet inicializálni
  • elég sok időbe tellik kibogarászni hogy vajon mi lesz ide besettelve
Nem olyan, mint a JdbcTemplate, amit szerintem simán más framework-re is bele lehet tuszkolni, és ráadásul nagyon hasznos. Sikerült portolhatatlanná tenni a kódot, pedig a spring úgy indult annak idején, hogy non-intrusive IoC framework. Másrészt ez olyan, mintha service lookup-ot használnánk, annyi előnnyel, hogy a boilerplate kódot átvette a spring. Viszont akkor már ilyet is csinálhatnánk:

@JndiLookup("jdbc/MyDS")
private Datasource datasource;

A megoldás: TestNG

N alkalommal futottam neki a TestNG használatának eddig, mindig nagyon boldog voltam magával a TestNG-vel, de az IDE integrációjával soha nem tudtam kibékülni és végül inkáb maradtam junit-nál. Az 'új' projectem pár artifact-jába viszont valamiért belecsomagolták a junit egy matuzsálemi verzióját, ami teszt alatt ütközésbe kerül az új verzióval, így nem maradt más választásom, mint testng-t használni.

2009. augusztus 24., hétfő

RIA kalandok

Hát igen, jó hosszú történet, ugyanis a kliens oldaltól mindig próbáltam magam távol tartani. Nyilván a CV-ben sem áll jól, ha valaki nem pöpec a teljes alkalmazás stack minden apró elemében, meg elkezdett érdekelni is a téma.

Szóval a hosszú történet...

OpenLackó

Úgy kezdődött, hogy OpenLackó. Az OpenLaszlo volt nálam az első és eleinte marhára bejött, hogy én is tudok olyanokat csinálni benne, mint a UI guruk.
Előnyök:
  1. Tényleg marha gyorsan össze lehet dobni a felületet.
  2. Alapértelmezésben is szép.
Hátrányok:
  1. Szőrös RPC megoldások. Például minden hívást a laszlo szerveren keresztül akar végrehajtani. Minek? "Java RPC" - public static metódusokat lehet vele hívni. Csúnya dolgokat kényszerített ki a szerver oldalon.
  2. Horrorisztikus fejlesztési menet. Dobáljuk be a lzx fileokat a laszlo szerverbe? Miért nem lehet inkáb beágyazni az egészet?
  3. Nem igazán indult be a komponens-piac, talán éppen a fentiek miatt.
Flex + BlazeDS vagy amit akarsz

A flex-ben amit elsőre megszerettem, az az hogy végre normálisan néz ki a RPC. Hívhatunk teljesen szabványos SOAP hívásokat, vagy kicsit cifrább mulatságba is belemehetünk BlazeDS-sel. Extra a lackóhoz képest az is, hogy nem kell a runtime környezetbe beletolnunk semmi flex specifikus dolgot. Egyből 40 megával kissebb a war file, hoppá.
Előnyök:
  1. Sokféle és használható RPC. Akár szerver data push is.
  2. A data binding szerintem király.
  3. Nem feltétlenül akar valami spécit a szerver oldalra.
  4. Kiválló maven plugin :)
  5. Sokféle free UI komponens és library a neten.
Hátrányok:
  1. Pokolian lassú fordító.
  2. Hát van a flexbuilder, ami pénzes windowsos, akkor már egy új gépet is kellene vennem... Valamint összedobtam egy gyors plugint régebben, ami semmi mást nem csinál, csak lefordítja minden módosításra a flex kódot. Ezek nélkül azért meg lehet lenni.
ZK

Erre egy volt munkatárs hívta fel a figyelmemet és nagyon örültem is neki. A zk király... bizonyos dolgokra.
Előnyök:
  1. Nem kell IDE :) Simán eclipse-ből editálva a zul fileokat háttérbe futó jetty-vel ment minden mint karikacsapás. Nagyon gyorsan lehet vele haladni. Módosítás esetén is villám gyorsan újrafordít.
  2. Tiszta html.
  3. Nagyon egyszerű és működő spring integráció.
  4. Akadnak hozzá hasznos kis extra komponensek, egész könnyűnek tűnik sajátot írni. Az alap csomag is rengeteget tartalmaz.
Hátrányok:
  1. Nekem úgy tűnik, borzasztó sokat nyúl a szerverhez. Nem tudom róla leszoktatni. Mindenért a szerverhez szalad.
  2. Szerver oldali session-t nyit, egész nagyot. Skálázhatósággal nem tudom hogy állhat.
Szóval bekategorizáltam, hogyha egyszer valami csili-vili intranetes dolgot kell majd csinálni, akkor új lehetőségeket kap.

Google Web Toolkit

Hát ezzel odáig jutottam, hogy végigcsináltam egy tutoriált, és amikor oda jutottam hogy lefordít, akkor olyan botrányosan lassú volt, hogy fejvesztett menekülésbe kezdtem és azóta nem merészkedtem vissza. További információk így nem derültek ki.

HTML + JS + jQuery

Végülis feladtam és elfogadtam, hogy meg kell tanulnom javascriptet használni. Kicsit új eszközöket kellett keresgetnem ehhez, tényleg olyan érzés volt, mint gimi után C-ben kalapálni. A jQuery-t egy munkatársamtól lestem el, ő egekig magasztalta.
Előnyök:
  1. Még csak nem is jsp. Statikus html. Akármilyen IDE elegendő támogatást ad hozzá. Jó, mondjuk az eclipse javascript képességei tényleg nem tűnik valami nagy pukknak
  2. A SOAP-ot nem próbáltam, de a REST hívások simán mennek. Csak az megy át a dróton, amit az ember programoz. Alacsony szintű ajax megszelídítve.
Hátrányok:
  1. Még felfedezés alatt áll, de a UI library nem olyan nagyon frankó még.
  2. Alacsony szintű összeakadások. Például beleraktam egy google map-et egy dialog-ba, és hát voltak vele bajok, kicsit elcsúszott a google map. Nem tudom miért, kicsit erősítenem kell még javascrptből.
  3. Szerintem az olvashatósággal vannak problémák, de lehet hogy csak nekem kell még megtanulnom olvasni.
Ez a helyzet idáig. A véleményeteket és útmutatásaitokat természetesen örömmel látom.

2009. július 8., szerda

JAX-RS és JAX-WS

Köszi a hozzászólásaitokat az előző postra, egész sok inspirációt kaptunk ahhoz hogy hogy írjuk át a teszteket!

Igazából most is a véleményetekre lennék kiváncsi.

Szintén munkahelyi projectben azon mesterkedtem, hogy SOAP-os REST-es web service-t is meghagyom egészen addig, amíg teljesen világossá nem válik hogy az adott környezetben melyik a nyerő megoldás. Természetesen spring-gel inicializálom a service bean-eket, CXF-fel exportálom ki, JSR 181 web services és JSR 311 rest annotációkkal látom el a service metódusokat és a beaneket még JAXB annotációval is helyenként. Sikerült is, bár szerintem kicsit szőrös a dolog.
  1. Elösször is a JAX-RS a beanjeid Collection (list, map) mezőire megköveteli, hogy legyen mindnek alapértéke és csak gettere. Azaz ne lehessen null soha, legfejebb üres. Viszont a JAX-WS elvárja hogy mindenkinek legyen szép gettere és settere, különben nem számít proprtynek. Ez a kettő nem feltétlenül zárja ki egymást, csak kicsit megcsúfítja a bean-eket.

    Például így fog kinézni egy bean:



    /**
    * Szerintem gáz, amikor magyar neve van egy osztálynak :)
    * Majdnem mint amikor a javadoc is magyar.
    */
    @XmlRootElement(name="csirke")
    public class Csirke {
    boolean isKopaszNyaku;
    boolean isKendermagos;
    List<Tojas> tojasok = new ArrayList<Tojas>();
    @XmlTransient // Nem ezt a property-t hasznaljuk a rest apival
    public List<Tojas> getTojasok() {return tojasok;}
    public void setTojasok(List<Tojas> tojasok) {this.tojasok = tojasok;}
    @XmlElement(name="tojas")
    @XmlElementWrapper(name="tojasok")
    public List<Tojas> getTojasLista(){ return getTojasok();}
    }


    Szóval szerintem kicsit összetúrkáltuk az alkalmazás legérzékenyebb részét: az adatmodellt. Ha az adatmodell csúnya, az mindennek rossz alaphangulatot ad.
  2. A CXF-nek kicsit nehéz volt megmagyarázni, hogy ha pl a /services/ alá mappeltem a CXFServlet-et, akkor mit kell csinálnia akkor, amikor kap a /services/-re egy kérést. Azt hiszem az lehetett a baj, hogy nem állítottam be at address-t.



    <jaxrs:server name="jaxrs-server" bus="rest" address="/rest">
    <jaxrs:servicebeans>
    <ref bean="csirkefarm">
    </jaxrs:serviceBeans>
    </jaxrs:server>



  3. A service interfacekre raktam az annotációkat, hogy ha lecserélem az implementációt, akkor az új service-re már ne kelljen másolgatnom. Hát elég cifrán meg lett annotálva egy-egy ilyen metódus.



    @WebService(name = "csirekFarm")
    @Path("/csirkeFarm/")
    public interface CsirkeDAO {
    @WebMethod(operationName = "getCsirke")
    @WebResult(name = "getCsirkeResult")
    @GET
    @Path("/csirke/{csirkeId}")
    public void Csirke getCsirkeById(@Webparam(name="csirkeId") Long id);



Most, hogy az annotációk legyőzték az XML konfigurációkat, a kódunk tele van konfigurációval :-) A hétvégén összedobok hozzá egy archetype-ot, ha elég időm marad rá.

2009. június 25., csütörtök

Logging

Belekeveredtem egy problémába a OpenJPA unenhanced osztályaival és úgy döntöttem hogy inkább visszatérek kicsit Hibernate-re. Nos magában a visszatérés nem lett volna nagy ügy: kiszedni az OpenJPA-t a pom.xml-ből, betenni a hibernate-entitymanagert, kicsit módosítani a jpa konfiguráción és kész is lenne...
Viszont a hibernate időközben nagyon szépen áttért a log4j logolásról a slf4j logolásra. Őszintén szólva teljesen lusta voltam egész idáig akár belenézni is, hogy mit kínál az új logging api. Nos a Simple Logging Facade 4 Java azt találta ki, hogy az régi logging apik helyére tesz egyetlen loging rendszert. Azaz kidobtak egy halom jar file-t, amiben például benne lehet a jó öreg org.apache.log4j.Logger, és emiatt nem tűri meg maga mellett az eredeti log4j-t. Dependency hell. Akármelyik csomagom is hozott be log4j függőséget, azonnal ki kell vadásznom a teljes dependency fából. Most még be kell dobálni a slf4j api-t, majd a log4j-over-slf4j csomagot...

A végeredmény az, hogy a JPA implementáció cseréje sokkal kevesebb időt vett igénybe mint a logging api cseréje. A logging az a dolog amitől azt várnám hogy nem zavarhat semmit, nem romolhat el és nem okoz semmiképpen sem futási hibát.

"Lassan haladunk, de nem baj, mert rossz irányba"

2009. június 21., vasárnap

Rémálom a JPA utcában

Ezt a problémát próbáltam felvázolni Tvik-nek a eclipse democamp elött, de azt hiszem túl alacsonyan volt akkor még az agytevékenységem hogy sikerrel járjak. Meg talán viccnek túl hosszú ez az egész.

Szóval egyik nap áthívott az egyik srác egy másik projecttől, hogy segítsek elindulni a JPA persistence tesztek fejlesztésével a projecthez. Eléggé félfüllel követtem a project életét, szóval igazából csak nagyon kevés ötletem van arról hogy mi miért jutott oda ahol van az architektúra fejlődése során, de ehhez a feladathoz ezen a ponton rendelkezésünkre állt:
  • Netbeans-ben kigenerált JPA controller kód (ahogy én értettem ez ugyanaz mint a DAO pattern)
  • persistence.xml kitöltve a production környezethez (JNDI datasource inside)
  • Azt hiszem szintén generált perzisztens osztályok
  • Maven-es build
Feladat: A kódot teszteljük úgy, hogy használjuk fel hozzá kigenerált kódot is. Szóval sima DAO tesztelés.
A generált kód nemnyúkapiszka tárgya.

Első nekifutásra egyszerűen azt javasoltam a kollégámnak, hogy egyszerűen dobjon be egy új persistence.xml-t a teszteknek, és használja azt a tesztekből. Biztosan lehet valahogy, mert a spring és a unitils is meg tudja mondani a persistence layernek, hogy melyik persistence.xml-t használjuk fel. Mondani könnyű persze.
Párhuzamosan én is elkezdtem keresni, hogy vajon a JPA-nak hogy is kell ezt megmondani, de látványosan sehol semmit nem találtam, csak akkor nem foglalkoztam vele tovább mert persze én másik projecten vagyok és azt kell hegeszteni.

Második nekifutás: Be kellett látnunk hogy kicsit alaposabban kell foglalkozzunk a JPA kérdéssel ahhoz hogy a teszteket élesbe állítsuk. Összeültünk egy eredetileg rövidre tervezett pair programming sessionre és nekiláttunk átnézni a teszt menetet. Hamarosan kiderült hogy a spring valami nagyon hosszú tréfát használ arra, hogy a persistence.xml-t más néven keresse meg és ezt nem akartuk átmásolni tőlük, inkáb az volt az alapötlet, hogy a spring-gel inicializáltatunk egy JPA EntityManager-t és azt odaadjuk az érintett DAO objektumoknak. A JPA init ment is mint a karikacsapás, de amikor odaértünk, hogy beletömjük a DAO objektumokba az eredményt, akkor elmúlt a jókedv: a generált osztályok konstruktora inicializálta és private mezőként tartotta az EntityManagert. Azaz szépen udvariasan nem tudunk hozzányúlni. Ráadásul a kódba bele van generálva a persistence unit neve is. Ezt az egészet úgy látszik úgy találták ki, hogy a végleges környezeten kívül máshol ne lehessen futtatni. Azaz nem tesztelő-barát.

Harmadik nekifutás: Override-oljuk a konstruktort. Ja, de az ősosztály default konstruktora akkor is meghívódik. Rövid roham, fejvesztett menekülés.

Negyedik nekifutás: Jó, akkor használjuk a production-ra szánt persistence.xml-t és mielött mindezt felstartoljuk, dobjunk össze egy JNDI contextet a teszt DataSource objektummal. Ez tűnt vagy fél órán keresztül a nagy és tökéletes ördögi tervnek, én teljesen hittem a sikerben amíg a tesztbe drótoztam a spring-test csomag JNDI mock csomagját és startnál elmondtam a varázsigét is, hogy "Fuss QA!!!".... és nem működött. Azért nem, mert a spring JNDI mock csomaga pár metódust nem implementált a JNDI standardból, amit a JPA implementáció akkor is meg akart hívni. Na igen, régen használtam a spring JNDI implementációját és fogalmam nem volt a korlátairól.

Ötödik nekifutás: diplomáciai tárgyalások az ellenséggel. Ekkor kitaláltuk, hogy akkor a build eszközzel etetjük meg azt, amit a szőrös apikkal nem tudtunk. Nos a maven esetében ha két ugyanolyan nevű resource van a src/test/resources és src/main/resources alatt, akkor úgy tűnik kb véletlenszerűen fogja egyiket vagy másikat megtalálni. Nincs más választás, külön profile-ba kell tenni az éleset és a tesztet.
Ant-tal pofátlanul egyszerű lenne a junitnak odalökni egy másik classloadert. Rettenetes mellékhatások: nem futhat egy buildben a deploy és a teszt. A CI konfiguráció se lesz persze egyszerűbb.

Tanulságok:
  1. Rájöttem hogy eddig soha nem próbáltam spring nélkül JPA apit használni
  2. És valószinűleg ez az oka annak, hogy nem utáltam meg már az elején a JPA-t. A JEE architektúra csak kicsit lett kevésbé toldott-foldott mint a jó öreg EJB 2.1 időkben.
  3. A generált kódoktól nagyon udvariatlan dolog, hogy ők akarják inicializálni a persistencemanagert és erről nem lehet lebeszélni őket.
  4. A JPA-ban már az elején nem tetszett, hogy a META-INF/persistence.xml-hez ennyire ragaszkodik, de nem gondoltam, hogy nincs is szabványos megoldás ennek a felülbírálására.
  5. A netbeans generált kódjaitól ments meg uram mintket!
  6. Amikor ilyen kavar a kód, a maven szigorú struktúrája is akadállyá válik.

2009. június 18., csütörtök

Eclipse DemoCamp frissen

Ma este betértem az Eclipse DemoCamp 2009 rendezvényre, szocializálódni és telepakolni a szatyromat információkkal. A hely egy kellemes kis teázó a vár aljában, a hőmérséklet és a népsűrűség is sokkal kellemesebb volt mint tavaly. Persze nem azért, mert kevesebben voltunk :) Kicsit lassan rázódtam bele a hangulatba, inkáb már csak az első előadás után kezdtem kommunikálni emberekkel.

Előadások...

Bocsi, még mielött nekivágok... Nem próbálom hitelesen visszaadni az előadások tartalmát, az biztosan elérhető lesz majd valahol, a saját reakcióimat írnám le ide velük kapcsolatban.
  • Nagy Gergely: Dependency Management with Ivy and IvyDE
    Demókkal megtűzdelt előadás volt arról, hogy az Ivy-t hogyan lehet fejlesztőbarátabbá tenni egy eclipse plugin segítségével. Volt is benne apróbb bug, egyszerű javítással. Ahol kicsit nekem elakadt a lélegzetem, az a repository modell volt. Miért lett ez ilyen bonyolult?
    Feltettem az a kérdést, hogy ha "csak például :)" én mavent használok, de a cég egy másik csapata ivy-t és ant-ot, tudnak-e ők nekem olyan mavenes descriptort generálni a ivy dependency-kből, amivel az én mavenes projecteim tudják használni az ivy+ant kombinációval buildelt cuccot. Gergely mondta, hogy nincs ilyen megoldás és Jason hozzátette hogy igazából nem is lehet, a két project classloader rendszere teljesen más és összeegyeztethetetlen.

    Kövekeztetés: a Cégen belül ha valaki ilyet használ, az nekem nem segítség. Továbbra is hímezhetem kézzel a pomokat.

  • Jason van Zyl: Next Generation Enterprise Builds: Maven, Mercury and Tycho
    Külföldi sztárelőadóval folytatódott a build eszközök harca :)

    Szóval Jason elegánsan átsiklott a maven 3.0 téma felett, ahol én meglepődtem, mert a maven 3.0-ról most hallottam elösször és nagyon érdekelt volna erről minnél több infó, de ennyit kaptunk: minden működni fog a maven 2.x-ből 3.0-on is.
    A m2eclipse alias Tycho igazán meggyőző demó volt. Persze volt benne pár apróbb hiba, mint minden live demóban, de talán végre eljött az ideje, hogy beálljak a sorba és elfelejtsem az 'mvn eclipse:eclipse' parancsot. Amúgy is túl geek-es volt, windowson meg rettenetes.
    A nexusról nem sok újat tudtam meg, mondjuk azon amennyire tudtam rajta tartottam a szemem. Az első pár feature requestet én dobtam be rá és igazából elégedett vagyok azzal amit kaptam ingyen :) A kérdésem az volt hogy mi az, ami kiemeli a nexus-t a maven repository managerek versenyéből. Jason alapvetően a stabilítást és a teszteltséget emelte ki, valamint hogy az archiva igazából bebukóban van.
    További információmorzsa: a nexus a jsecurity-t használja azonosításra és csak 1 hét volt beintegrálni, ami jobb mint a spring-security. Volt nekem is pár problémám a spring-security-vel, de soha nem szúrtam el rá 1 hetet. A rekord egy régi grails-es projectemen volt 2 estényi gubancolás, mert akkor még a grails is gyerekcipőben járt, meg groovy-ban is az volt az első dolog amit írtam. Házi feladat: jsecurity


    Félig meddig ide tartozik, és a következő blog postom arról fog szólni hogy milyen torkos szívás volt generált JPA kódra írt teszteket futtatni mavennel. Pff, a kódgenerálás a múlt század. Nekem az idl compilerek jutnak róla eszembe.

  • Bánfai Balázs, Török Zsolt: Transition from classroom to real-life software engineering
    Nos ebből a szempontból az én karrierem - ha beszéljetünk ilyenről- nem a szokásos dolog. Soha semmi hasznosat nem tanultam iskolában főleg nem informatikáról, és bár jártam egyetemre, úgy érzem hogy -persze csak intellektuális- pofonokon kívül mást nem kaptam. Persze kell a karó a virág mellé, de hát... kéne a virág a karó mellé.
    Úgyhogy erről kimentem dumálni a teázó elé, aztán pedig hazatekertem.

Köszi a szervezésért és a kajáért a B2 International-os arcoknak!

Sziasztok, boldog csütörtököt!