2007/02/26

Batik

Szeretem az olyan pillanatokat, amikor végre nem kell fanyalognom.

Kellett volna gyorsan rajzolnom egy SVG-t, a gugli kiköpte a Batik-ot. És tényleg. Lenyűgöz feature lista (An SVG DOM implementation, SVG microsyntax parsers, scripting module, a generator that creates an SVG document from Java2D calls, Swing SVG component, transcoder module), és minden megy pöccre, ahogy dokumentálva van, pont úgy.

Én pl. a Graphics2D-n keresztül írtam. Előszőr összelőttem a programot egy Swinges ablakon. (Egyszerűbb volt oda gyorsan összedobni. Aztán egyszer csak a programo szályába az SVG Graphics2D implementációját adtam, és oda ugyanúgy szépen írt mindent.

Apró örömök az életben.

2007/02/23

OpenID java libraries

Kocka kérésére :)

Az OpenID.net három java libraryról tud.

IdPrism: Jelenleg én ezzel kísérleteztek, mert ez a legegyszerűbb. OpenID 1.1-et tud, azt viszint ajaxon keresztül is. A letöltött könyvtár tartalmaz egy példa servletet is, ahol mind az ajaxos mind a szerver oldali megoldásra látunk egy egyszerű példát. A kód nem egy nagy durranás, de legaláb könnyen át lehet látni.

OpenID4Java OpenID 2.0-sat is támogat, jól néz ki, ez lesz a következő, amit kipróbálok.

NetMesh InfoGrid LID Java. A legnagyobb baj vele, hogy ez alapvetően LID implementáció. Mivel a LID speckó része, hogy OpenID-ül is kell tudnia, ezért valahol benne van az OpenID támogatás.

LID meg egyelőre megfigyelés alatt. Annyit csak, hogy próbáljuk meg megkeresni az OpenID.net oldalon a letölthető speckót, és a rá vonatkozó licenset, és ugyanezt a LID oldalon. Na ugye. Tegnap írtam egy levelet a LID community levlistájára (az archívum nagyon gyér forgalmat mutatott, de hátha). Az első meglepetés, hogy a lista moderált (szóval ennyit a communityről). Aztán jóváhagyás helyett megkaptam emailben a speckókat, amik CC licensz alatt érhetőek el. De egyelőre maradok az OpenID 2.0-hoz való felzárkózásnál.

2007/02/21

OpenID II.

Azt hiszem most egy kicst erről fogok szólni.

Ami még fontos:
Az OpenID elosztott rendszerű. Ha beütsz egy OpenID azonosítót (pl. karenin.myopenid.com) Azt a rendszer elképzeli url-nek. (http://karenin.myopenid.com/ és lekéri az az oldalt. Az oldal fejlécében lesz valami ilyami:
<link rel="openid.server" href="http://www.myopenid.com/server" />
Na erre a címre fog átugrani mindenféle request kérelemmel.

Ezt annyival meg lehet bolondítani, hogy egy delegate nevet is használok
<link rel="openid.server" href="http://www.myopenid.com/server">
<link rel="openid.delegate" href="http://karenin.myopenid.com/">
A fentieket beraktam jelen html fejlécébe. Ezek után már a problemjava.blogspot.com-ot is használhatom OpenId azonosítónak, ami használatkor a www.myopenid.com/server-en keresztül a karenin.myopenid.com-ot fogja autentikálni.

Azaz, ha később létrehozok egy másik OpenId-t egy másik szolgáltatónál, az OpenID-s honlapokat ugyanúgy használom tovább problemjava.blogpost.com névvel, csak a fejlécembe írom át a hivatkozást.

Ami még érdekes, hogy ha nem mondom meg (mondjuk egy reguláris kifejezéssel), hogy milyen OpenID szerver felhasználói jöhetnek be hozzám, akkor alapból mindenkit beengedek. Nem lenne nagy munka egy olyan OpenID szervert összerakni, aki kvázi egyszerhasználatos usereket generálna, és bármilyen requestre azt mondaná, igen ismerem, igen be van lépve. És indulhat is a comment spam.

2007/02/20

OpenID I.

OpenID 1.1 nagy vonalaban:

A user regisztrál egy oldalon (pl. myopenid.com), és belép. Jó nagy session-t kap, be lesz lépve 2 hétig.

Az én oldalamon is be akar lépni. Itt beírja az OpenId azonosítóját. Ez alapján az oldalam átdobja redirect-tel a böngészőjét az OpenId oldalára. A requesthez hozzá csap némi információt, pl. hogy hova térjen vissza az autentikáció után.

Az OpenID oldal tudja, hogy a tag belépett (ott van az élő session, ha nincs, akkor belépteti), összerak egy HTTP válasz üzenetet arról, hogy ki ő, és hogy tényleg okés-e, és az előzőleg megadott oldara visszatér a megfelelő paraméterrel.

(Nem tudom világos-e. Azt hiszem valami frappáns hasonlat kéne a módszerre, de még nem jutott eszembe semmi.)

Akkor nézzük tovább. Tehát én átpattintottam a böngészőjét a felhasználónak az OpenID szerverre, és az nekem visszajött némi infóval, hogy okés a srác. Honnan tudom, hogy a visszajövő requestet tényleg a másik OpenID szerver küldte?

Erre két módszer van a speckóban:

A statefull megoldás, hogy előtte az OpenID szerverrel megbeszélek egy titkos kódot, amivel aláírja a választ. (A megbeszélésre a Diffie-Hellman algoritmust használjuk, ami lehetővé teszi, hogy nem biztonságos csatornán keresztül is megállapodjunk egy közös titkos kulcsban.)

A stateless megoldás, hogy miután a böngész visszatért hozzám, a servletemből a háttrében nyitok egy http lekérése, és én is megkérdezem az OpenId szervert: te figyelj, itt van ez a válasz, iyen paraméterei vannak, és ilyen aláírás van rajta, okés? Az OpenID szerver ellenőrzi az adatokat (ehhez már nem kel a felhasználó böngészőjétől függő session, hiszen csak azt nézi meg, hogy tényleg ő írta-e alá a dolgot, azaz, hogy az adott adatokra az ő titkos kulcsa is ilyen aláírást generálna-e. Ha a ugyanazt, akkor a user böngészője nem hazudott, és a requestben megadott OpenId userévvel garázdálkodhat nálam is.

folyt. köv., addig viszont egy kipróbálást ajánlok: regisztrtáljunk pl. a myopenid.com oldalon, kapni fogunk egy karanin.myopenid.com szerű azonosítót, és aztán próbáljunk meg belépni OpenID-sített honlapokon (pl. wikitravel.org). A MyOpenId azért is jó, mert autentikáció előtt mindig kér egy jóváhagyást, ezáltal jól látható a működés.

2007/02/19

Proxy mögött

Tudom, hogy elenyésző azon esetek száma, amikor az éles szerver egy proxy mögül zizegne, de a development környezetben ez nagyon is előfordul.

Mert van olyan, amikor egy servlet nyit egy TCP connection-t, és azon próbálna kommunikálni valahová máshová (pl. OpenLaszlo, bizonyos OpenID implementációk). Na már most, ha ennek kommunikációnak a céges proxyn keresztül kéne hogy menjen, de ilyen lehetőségre a fejlesztők nem is gondoltak. (Na jó OpenLaszloban gondoltak, de ott nem izzúlt be.)

Valmi OpenVPN-s dolgot nagyon össze kéne már gyúrni.

2007/02/12

servlet 2.5 / jsp 2.1 web container?

Sikeresen portoltam JSF 1.1-ről 1.2-re a picipuha-majd-elkészül alkalmazásomat. Persze a kérdés még mindig ott van, hogy mi fogja hajtani. JSF 1.2, azaz JSP 2.1 kéne.

Tomcatből a 6-os még mindig béta. 5.5 nem tujda. :(

Jetty-hez a fejlesztőeszköz (NetBeans) integráció nem megoldott (bár egy ilyen modult talán össze is dobnék), meg egy kicsit gyanús is, amikor azt írják, hogy 2.5-ös servlet container, de azért a dependency injection nem működik.

Glassfish az igen. Az nagyon szépen muzsikál, a Jackrabbit JCR-t is JCA-n keresztül simán vitte. Kár, hogy egy sima start 50-60 mega Heap-et eszik a Tomcat 5-6-jával szemben. (Jconsole) Ez azt jelenti, hogy a 200 megás szerveren elég necces lenne.

Tovább:
Kideríteni, hogy hogy lehet Glassfish szolgáltatásait szelektíven indítani (pl. ejb/JMS momentán még nem kell nekem.
Vajon ha a Grizzly-t teszem be jetty-be vagy tomcat 5.5-be (jettyhez már láttam nyomokat, hogy lehet), akkor servlet 2.5-öt kapok, vagy egész más szint?

2007/02/09

java.text.Normalizer

Itt olvasom: azt hinné az ember, hogy ha UTF-8at használ, akkor már többet nem lesz semmi baj az ékezetekkel, pedig de: mivel az ékezetes karaktereket lehet több karakterből is összrakni az Unicode-ba, de sokszor van egy egy karakteres rövidítés is rá.

A cikk példája, hogy vilálog legyen:
String name1 = "Jos\u00E9";       // José with precomposed é
String name2 = "Jos\u0065\u0301"; // José with combining sequence e + ´

Aze a kettő ugyanúgy jelenik meg

A java.text.Normalizer mindig közös alakra hozza a Stringeket, így kereshetővé és összehasonlóvá teszi. Persze csak 1.6 alatt működik, és azért nekem van egy tippem, hogy mondjuk egy webes alkalmazásnál hány ember fog a beviteli formban composite uncide karaktereket használni.

Vagy lehet, hogy egy tisztességes DB kezelő az egészet lekezeli, és csak mondjuk file műveleteknél kell vele foglalkozni?

Vajon ékezetes domaineknél ez kettő külön domainnek számít? Nyilván ott is kell lennie valami normalizálásnak.

2007/02/08

ANT custom selector

Nekem pl. új volt.

<fileset id="activefiles" dir="${workdir}">
<custom classname="net.anzix.ant.ucm.ActFilesSelector" classpath="dist/UCMReporter.jar"/>
</fileset>
Nem taskdef-et használunk, hanem custom selector-t. A fileset végig megy az összes fájlon, és a selectortól megkérdezi, hogy szerinte benne legyen-e a filesetben az a fájl:
public boolean isSelected(File basedir, String filename, File file) throws BuildException {
Nekem azért kellett, mert egy java osztályom visszaad egy file tömböt (ClearQuest-ben érintett fájlok, command line wrapperből szedve), és azt be akaromtam rakni egy filesetbe, úgy hogy később még exlude/includolni lehessen rajta az ANT-ban. Na erre pl. nem túl hatékony a módszer, de ameddig így is 3 mp alatt kijön az eredmény, egyelőre ez lesz.

2007/02/05

régi szép napok

Van egy jar könyvtáram (illetve nem az enyém, csak szereztem), szép 1.5-ben megvalósítva (enum, generic, template). Van egy CDC-res szánt alkalmazásom, amit IBM J9-el akarok PocketPC-n futtatni (helyből -source 1.4).

Az egyik megoldásnak a retroweaver-t találtam, amit a lefordított class-okat machinálja át 1.4-es alatt is futathatóvá. Ant taskként működik, kipróbáltam, és működött. Szép. (Persze csak akkor , hogy ha nem használunk csak 1.5 api-jában lévő dolgokat).

A másik megoldás (és sajnos ez lett belőle), hogy kézzel nekiállok gyomlálni, és átírni a dolgokat. Sajnos ez lett belőle, mert kiderült, hogy a CDC/Basic Profile-bül hiányzik néhány awt.geom.*, amit a könyvtár használt, de kellett, úgy hogy úgy is át kellett alakítani.

Viszonylag kis api, de akkor is elég gépies volt visszaalakítani. Egy életre megtanultam, hogy mennyivel szebb 1.5-ben programozni. Sorban butítottam vissza mindent, az enumoktól kezdve az Autoboxingig, sok castolás a generic helyett. Brr...

2007/02/02

custom EL

Az van, hogy Java Content Repository lesz a megoldás. A POJO-k (amit JPA-val tudnék pertisztálni)sajnos túl merevek, nem lehet őket kiterjeszteni könnyen, míg a JCR node-jait lehet, mert nincsenek hardcode-olva bele a property nevek és típusok (persze veszítünk a típusossággal, dehát volt már nagyobb veszteségünk is).

Persze a JSF-es Expression Language alapból nem jön rá, hogy a #{name.property}-re egy JCR-es node.getProprty().getString()-et kéne kiadnia.

Viszont lazán lehet definiálni PropertyResolvert:

1. A PorpertyResolvert- leszármaztatom
2. a konstruktor megkap paraméterben egy PropertyResolvert(a defaultot), és minden metódust neki delegálok tovább. Pl.
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
Ha a base JCR-es Node, akkor castolom és kiszedem a propertyt. Ha nem, delegálom vissza akonstruktorba megkapott resolvernek az ügyet.
3. a faces-configba kell még egy ilyen:
<application>
        <property-resolver>com.valami.OwnPropertyResolver</property-resolver>
</application>


Mindez JSF 1.1-ben, ahol külön value resolver is van. 1.2-ben még egyszerűbb/szebb a dolog.