Až Vám zčerná obrazovka, přejděte na Linux!

Proč používat Linux
Zobrazují se příspěvky se štítkemJava. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemJava. Zobrazit všechny příspěvky

pátek 21. října 2011

Grails, Searchable plugin a org.hibernate.NonUniqueObjectException

Podařilo se mi při testování Searchable plugin získat org.hibernate.NonUniqueObjectException při Create operaci. Je to způsobeno chybou při vkládání do složeného indexu. Tvůrce pluginu s tím má nějaké potíže, takže je potřeba použít workaround: je potřeba během save() vypnout mirorring a občas pro jistotu reindexovat.

def searchableService
def save = {
def polozkaInstance = new Polozka(params)
searchableService.stopMirroring()
if (polozkaInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'polozka.label', default: 'Polozka'), polozkaInstance.id])}"
redirect(action: "edit", id: polozkaInstance.id)

}
else {
render(view: "create", model: [polozkaInstance: polozkaInstance])
}
searchableService.startMirroring()
}


Třeba to někomu pomůže.

pátek 23. září 2011

Generování PDF v grails - chybějící české znaky


PDF plugin do Grails je rychlé a šikovné řešení, ale, samozřejmě jako se vším, co udělají kluci v USA, neřeší korektně kódování. Takže je potřeba embedovat font, který obsahuje patřičné znaky. Zde je ukázka, jak to udělat.
Třeba to někomu pomůže.
<style>
    @page {
        size: 210mm 297mm;
    }
    @font-face {
        src: url(file:///c:/windows/fonts/arialuni.ttf);
        -fs-pdf-font-embed: embed;
        -fs-pdf-font-encoding: Identity-H;
    }
    body {
        font-family: "Arial Unicode MS", Arial, sans-serif;
    }
    </style>

pondělí 31. ledna 2011

První potkání s Grails

Tak jsem se po dlouhém odkládání konečně dostal k tomu vyzkoušet si Grails. Na tento framework jsem četl poměrně hodně chvalozpěvů, jak moc je to jednoduché v něm něco udělat, a tak jsem si říkal, že by to snad ani nemuselo být nijak složité.
Stáhl jsem si Grailsy a protože vím, že IntelliJ IDEA má pro Grailsy podporu, zkusil jsem bez jakékoli přípravy to zkusit rozjet.
To, že IDEA je naprosto fantastická, jsem věděl už dávno. Ale to, co jsem právě prožil, to je prostě fantazie.
  1. V prvé řadě vytvoříte Grailsový projekt. Tady není co zkazit, jenom odklikáte from scratch, název a cestu (tak jak jste zvyklí), jenom místo Java projektu zvolíte Grails.
  2. Otevře se Vám místo klasického stromečku Project stromeček GrailsView, které obsahuje logicky uspořádané objekty. V tuto chvíli jsem naprosto nevěděl, co dělat, i sáhl jsem po Gůglu a vygůglil tutoriál Getting Started with Grails od Scotta Davise a Jasona Rudolpha. Je zdarma ke stažení na infoq.com, ale vyžaduje registraci. Tam jsem se dočetl o tom, co je doménová třída, controller a view (skončil jsem na straně 27 u "Hello World")
  3. Přes pravé tlačítko na Domain classes jsem si vytvořil první doménovou třídu Race a nakopíroval do ní seznam atributů z tutoriálu.
  4. Klikl jsem na RaceController - Generate controller, čímž se vygeneroval zajímavě vypadající CRUD Controller.
  5. Klikl jsem na Race Views - Generate views, čímž se vygenerovaly čtyři soubory GSP.
  6. Ze srandy jsem klikl na Run. Otevřel se prohlížeč a v něm uvítací stránka Grailsů a v ní odkaz na RaceController.
  7. Klikl jsem na něj a BINGO! Otevřela se mi velice hezky vypadající jednoduchá, ale plnohodnotná webová aplikace - evidence mých objektů Race!  
V tuto chvíli mi spadla čelist..

Všechno je to pěkně popsáno i s ukázkami zde 
Příště popíšu další zkušenosti s touto na první pohled geniální dvojicí - Grails a IDEA.

úterý 15. června 2010

Jak vyřešit ORA-01591: zámek uplatněný spornou distribuovanou transakcí

Tak jsem si jednou hrál s Hibernate a automatickým vytvářením tabulek nad skoro produkční databází Oracle 10 a dostal jsem se do jedné poněkud choulostivé situace. Při deployi earu jsem dostával
ORA-01591: zámek uplatněný spornou distribuovanou transakcí
Chvíli jsem si myslel, že to má na svědomí špatně navržený deployment Hibernate. Po čase jsem začal Gůglit ve vodách mimo Javu a dostal jsem se k jednoduchému řešeni:

Jedná se o problém, kdy transakce selhala v okamžiku, kdy se dostala do stavu prepared. Jediné řešení je ji odstranit. A řešení jsou dvě: buď se k ní připojit a rollbacknout, nebo ji smahnout přímo v databázi.

Druhé řešení je poměrně elegantní. Oracle definuje SQL příkaz ROLLBACK FORCE a jemu odpovídající PL/SQL funkci dbms_transaction.rollback_force(xid). V tabulce "SYS"."PENDING_TRANS$" je uložen záznam o všech čekajících transakcích. Ve sloupci LOCAL_TRAN_ID je XID.

Stačí se tedy přihlásit jako uživatel SYSTEM s funkcí SYSDBA (například v sqlplus), spustit
exec dbms_transaction.rollback_force(moje_xid)
a je vymalováno.

pondělí 31. května 2010

Hibernate error - identifier altered from 1 to 1

Nějakou dobu jsem laboroval s toto poněkud podivnou hláškou - jak může změna z 1 na 1 vygenerovat chybu? A kde se vůbec ta změna bere, když jedinou operaci, kterou dělám, je session.save()?

Nakonec jsem chybu našel. Při laborování s formátem dat v databázi a ručním copy&paste psaní hbm.xml jsem zavlekl typovou nekonzistenci do dat. V databázi (PostgreSQL) jsem měl u ID Integer (což onu chybu ale nevyvolá), v hbm.xml java.lang.Integer, ale ve třídě java.lang.Long. No a protože long nelze bez přetypování uložit do intu, ona alterace byla na světě.

Řešení tohoto problému je tedy prosté. Zkontrolujte si, že vám PŘESNĚ sedí jednotlivé typy v Javě a v hbm.xml

Kéž to někomu pomůže.

úterý 9. února 2010

JBoss 4.2 a kumulující se instance Stateless EJB

Asi týden jsem si hrál s J2EE aplikací Westico Visibility Platform a každou chvíli mi aplikace sletěla na OutOfMemoryError. Asi memory leak, řekl jsem si.
Stáhl jsem si tedy NetBeansy (qůli profileru) a začal hledat, kde tesař nechal v paměti díru. Zjistil jsem, že mi permanentně narůstá počet instancí dvou Session Stateless EJB, které volám z MDB ihned po sobě, těsně před ukončením zpracování zprávy. Protože provádím JMS ack ihned po příchodu zprávy, říkal jsem si, že si asi lookup vytvoří nové instance fazolí, ale požadavek neskončí a proto to bobtná. Dlouho jsem trasoval onu Message Driven Beanu, dokud jsem si opravdu nebyl jistý, že požadavek skončil a tudíž GC by měl odstranit "nepotřebné" instance a v poolu by měly zůstat jenom "potřebné". Tak jsem se zaměřil na pool a zjistil následující:
JBoss má oddělené pooly pro MDB a stateless EJB. Pro obejítí klasické Javovské synchronizace používá JBoss ThreadLocal pool. A v tom je právě šutr úrazu. Díky klasickému implicitnímu chování MDB se stane, že každý požadavek je zpracován jiným vláknem a tedy pool pro bezestavové fazole bobtná, přestože má nastaven maximální počet instancí v poolu.
Pokud tedy chcete v JBossu volat stateless EJB z MDB, musíte patřičné bezestavové fazoli nastavit jiný typ poolu. Ideálně org.jboss.ejb3.StrictMaxPool, a to třeba pomocí JBossí anotace @PoolClass, jak je popsáno zde.

Třeba to někomu zachrání kupu nervů.

úterý 8. prosince 2009

Invalid checksum na UDP paketech

Nějakou dobu jsem laboroval s tím, že mi javovská aplikace běžící na IBM xSeries x3650 s OpenSuSE 11.0 generovala invalidní UDP pakety. Hlásil mi to WireShark (dříve ethreal).
Firmware jednočipu G2 to nebyl sto sežrat a pokud jsem na něj chtěl data dostat, musel jsem to vyřešit. Tak jsem Gůglil a zkoušel...

Výsledek mého snažení lze shrnout do těchto bodů:
  • Je to víc jak rok známý problém a řeší se, ale ještě není vyřešen.
  • Problém není v Javě, ale někde mezi jádrem a síťovkou. Stejný kernel na jiné síťovce funguje, jsou prý kernely, které s těmito síťovkami fungují. V tomto případě to nechodí na Broadcom Corporation NetXtreme II BCM5708 Gigabit Ethernet (rev 12)
  • Na vině je chybné generování checksumu síťovkou, neboť při použití Raw Socket (což Java dělá), generuje checksum právě síťovka (nebo její modul, nevím, ve zdrojácích jsem nebyl)
  • Řešením je použití TCP checksum offload, které vypíná ono generování kontrolního součtu.
  • Na Linuxu se k vypnutí použije ethtool -K ethN rx off tx off, kde ethN odpovídá konkrétní síťovce, kde to chcete vypnout (tedy eth0, eth1,...)

Třeba to někomu pomůže...

pondělí 23. března 2009

Odkud stánhout JAD

JAD je velice oblíbený a používaný Javí zpětný překladač (angl. decompiler, česky by to mělo znít jednoslovně jako odpřekladač, ale já na jednoslovné překlady moc nejsem). Chtěl jsi jej dnes stáhnout, ale původní stránky jsou v konkurzu (vypršela platnost domény) a tak jsem si musel trošku zaGůglit.
Tomas Varaneckas něco postahoval a udělal tak na Paranoindím inženýringu vlastní pidizrcadýlko se vším podstatným JADovatým - http://www.varaneckas.com/jad

úterý 10. února 2009

Instalace Lotus Notes na openSuSE 10.3

Dnes jsem se pokusil nainstalovat Lotus Notes 8.0.2 na svůj stroj, kde mi běží OpenSuSE 10.3 Se zlou jsem se potázal:

java: xcb_xlib.c:52: xcb_xlib_unlock: Assertion `c->xlib.lock' failed.


Nelenil jsem a zeptal jsem se bratra Gůgla. Odpověď přišla velmi brzy. Problém je v XIneramě (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6532373). Byl. Oprava je dávno venku. Bohužel se nedostala do openSuSE 10.3 Na druhou stranu je zde implementován v Java wrapperu nádherný workaround - stačí zapnout používání "rozbředlých zámků" (IMHO velmi impozantní překlad pro sloppy lock) pomocí LIBXCB_ALLOW_SLOPPY_LOCK=1. A je to.
Tento wrapper se ale nepoužije, pokud si systém sám se sebou veze vlastní JRE - pak vylítne onen problém se zámkem. Takže pro instalaci stačí
export LIBXCB_ALLOW_SLOPPY_LOCK=1; ./setup.sh
a je vymalováno. Snad to někomu pomůže.

pátek 24. října 2008

Copy&Paste fórek

Právě jsme na Javí konferenci řešili použitelnost JSTL SQL (lépe řečeno do jaké míry je prasárna vůbec jeho existence), když se v jednom příspěvku objevil odkaz na báječný obrázek na toto téma.

PS: Ale na druhou stranu i tento obrázek IMHO vznikl pomocí Copy&Paste :-D

středa 30. července 2008

Jak oRESTovat Javí aplikaci

Dneska ráno jsem našel naprosto zajímavý článek, první ze série o RESTu, který objasňuje REST na příkladu jeho převedení do světa Javy.

První díl vzali autoři z trošku jiného konce - začali od Bindingu neboli vazby mezi klientem a serverem. Vazbu v RESTu definují jako asociaci logického jména na něco "fyzického", třeba kusu kódu, kus paměti či metodu.

Dávají do kontrastu vazbu mezi jménem třídy v Javě (a klasický ClassLoading) proti volné asociaci mezi URLčkem a "stránkou" Webu. Zasmál jsem se nad přirovnáním, že změna implementace třídy (v jejich příkladě java.util.Date) znamená (bez šíleného overheadu s vlastní implementací ClassLoaderu) restart celého JVM, což v případě Webu je věc naprosto komická. No schválně si představte restart celého Webu. Ten synchronizační komunikační protokol bych chtěl vidět... tedy nechtěl...

Takže si řekli, že:
1. Browser se zeptá Domain Name Service (DNS) na "tapikuv.blogspot.com" (v jejich případě www.theserverside.com, ale co bychom si to neupravili, že :-D) a zpět získá IP adresu.
2. Browser vytvoří TCP/IP spojení na onu IP adresu na portu 80.
3. Spojení použije na odeslání HTTP GET requestu na zdroj "/" na tapikuv.blogspot.com.
4. Server dostane HTTP request, něco s ním udělá a vrátí nějakou reprezentaci zdroje "/".
5. Browser ji dostane, něco s ní provede a zobrazí to uživateli.
6. nakonec browser shodí TCP/IP spsojení a "un-binds" (poměrně hodně podstatné slovo, viz níže) od endpointu.

Takže si kluci zavedli vlastní URI schéma "resource" (např. resource:/customers) a navrhli pár tříd:
1. Context (něco mezi JNDI kontextem a proxy)
2. Request (obdoba HTTP requestu)
3. Representaion (obecná třída, ve své podstatě obdoba java.lang.Object)

Celý proces pak probíhá tak, že na kontextu vytvoří request na konkrétní URI, přidají k němu co potřebují, nechají jej provést a zpět dostanou Representation.

Na první pohled nic nového pod sluncem, máme EJB sdílející s klientem jenom mezixicht (miluji toto slovo, které jsem před víc než 20 lety našel ve VTMku), JNDI Context.lookup(), zavolání metody EJBčka a návrat nějaké hodnoty.

Fígl je v tom, že v tomto systému je jenom jeden mezixicht, sdílí jej tedy VŠECHNA EJBčka. To umožňuje dramaticky omezit různá omezení. Klient se tak de jure nestará o evoluci takovýchto EJBček. Stačí mu jenom znát správné URIčko a umět se vypořádat s instancemi Representation.

Sranda je v tom, že výhody tohoto systému nepochopil téměř žádný diskutující. Odvolávky na zahození typovosti v Javě,když ji přece sami autoři používají, že do Javy to vůbec nepatří, že je to přece k ničemu, když ti server vrátí něco, co ty dopředu nevíš, že vrátí, či na to, že to všechno řeší přece CORBA, DCOM a SOAP, jsou velice srandovní. Šlo přece o vysvětlení na příkladu architektonického stylu. Težko přece budeme dělat RESTovou servisu na operátor ++, že...

Na druhou stranu se autoři zapomněli zmínit o jedné podstatné věci, a tou je právě onen "un-bind". Tato operace totiž není v RESTu definována, kde je nahrazena operací "rebind". Chápu, že ona jemná nuance nemusí být pro mnohé čitelná. Hlavní rozdíl je v tom, že ona vazba mezi logickým jménem a "fyzickou" reprezentací má obvykle trvání přesahující jeden request. Teprve když si klient usmyslí, že je načase aktualizovat odkaz, udělá onen "rebind". Kromě kešování bindingu tu navíc máme ještě kešování reprezentací, kdy zase klient rozhoduje, zda je na čase se podívat po aktuální verzi.

No a samozřejmě mám trochu potíž s onou třídou Context. Podle mne je mnohem lepší ji rozdělit na Registry, Repository a Proxy. Registry mi řekne "fyzičtější" odkaz (zde dělám rebind), Repository mi vrátí Proxy (které si kešuji) a na Proxy pak volám requesty. Přijde mi to logičtější a více RESTózní.

středa 2. července 2008

Ořez textu v MANIFEST.MF

Dnes jsem při hledání příčin jednoho ClassNotFoundException narazil na zajímavou informaci. Jeden každý řádek manifestu nesmí být delší než 72 bajtů (nikoli znaků). Pokud vyvstane nutnost napsat na řádek delší text, je potřeba onen text rozdělit na více řádku po maximálně oněch 72 bajtech, přičemž každý pokračující řádek pak musí začínat právě jednou mezerou.
Pak se nedí co divit, že při dlouhé Class-path vygeneruje IDEA manifest, který třeba obsahuje začátek názvu jaru na konci jednoho a zbytek na začátku druhého.

pátek 20. června 2008

Proč je Ant generátorem špaget

Dagi napsal zajímavý článek o jeho zkušenostech z programováni v Antovi. Ano, XML nebylo nikdy určeno k programování a je jedno, že se hojně používá. A to není jenom Ant, dokonce je i XSH. I ono krásné deklarativní XSLT je zprocedurovatelné a pak se v tom prase vyznej :-(

Co se ale týká mravence, tak tam je historie naprosto jasná. Na Apachi hledali nástroj obdobné síly jako GNU Make, úspěšně používaný v jejich primárním projektu - k buildování web serveru Apache. Hlavním kriteriem takového nástroje ale byla implementace v Javě. A takový nebyl, tak se rozhodli si jej udělat sami. I řekli si, že nástroj nebude umět nic šíleného a tak že k formátu mohou přistupovat jako k deklarativní konfiguraci a proto zvolili XML formát. Jenomže síla Make není jenom v jeho deklarativnosti, ale hlavně v síle unixového shellu. A proto se začal Ant a jeho build.xml rozlézat do příšerných obludností. Přibyly podmínky, cykly a další šílené konstrukty, atributové deklarace jsou nahrazovány flexibilnějšími XML strukturami,... A tak se z prosté jednoduché konfigurace stal další Turingův stroj a jako takový začal být používán. A protože je ve velkých projektech neustálá potřeba rozvíjet možnosti buildovacího systému, build.xml bobtná a bobtná... už jsem viděl i megabytový.

středa 18. června 2008

Metodika návrhu SOA aneb kdy začít s WSDL a kdy s kódem

Přečetl jsem si Vytvářet nejdříve WSDL nebo Java rozhraní od Petra Jůzy a rozhodl jsem se, že také připojím pár svých zkušeností.

Na otázku, zda začít nejdřív s WSDL nebo nejdřív implementovat a potom generovat WSDL neexistuje jednoznačná odpověď. A navíc je třeba podle Cimrmana vzít v potaz i roli kohouta, ale nepředbíhejme :-)

Bavme se tedy v prvé řadě o WebServise, u které tato otázka má smysl, tedy o RPC.

Nedá se říct, že by varianty měly své pro a proti. Prostě jsou každá na něco jiného.

Hodláte-li napsat WebServisu na zelené louce, máte na začátku dva výchozí předpoklady: a)bude to WebServisa někomu zveřejněná a která b)bude něco dělat. Pravděpodobně začnete s nějakou analýzou problému. Z analýzy vypadne struktura dat, která by měla kolovat tam a zase zpátky. Struktura se lépe popíše XML schematem než pomocí tříd. Nad ukázkovým XMLčkem se pak lépe přemýšlí jiným lidem, je to názornější. Proto je tedy v takovém případě nejlepší začít s XML schematem, přidat operace a máte WSDL. Z něj pak generovat kód.

Máte-li už napsaný kus kódu a chcete lokální volání roztrhnout SOAPem, není jednodušší cesty než označit nějakou fasádu jako WebServisu a nechat k ní vygenerovat WSDL. Nejčastější a nejhezčí je ale vypublikovat ji pomocí Endpoint.publish().

Já ale tvrdím, že tato otázka je ve své podstatě nesmyslná. Kde je jádro pudla, nebo lépe řečeno kohouta? V pohledu na věc.

Ať už jde o Integrační, B2B, Intranetový Infrastrukturní či Separační scénář, vždy je na počátku všeho zadání. Jak už nás učili na základní škole, zadání problému se klasicky popisuje trojicí množina vstupních hodnot, množina výstupních hodnot a přechodová funkce, popřípadě jejich množina. A to se dá říct jak o nově vznikající aplikaci či WebServise, také o fasádě nad legacy systémem. Ač se to nezdá, totéž platí i při roztrhávání, protože se může ukázat, že bude daleko čistější vygenerovat novou fasádu. V případě složitějšího problému komunikace mezi více participanty pak také víte (nebo aspoň tušíte), co si ti dva tam budou posílat. Každý z participantů má přece svoji roli a k roli patří zase vstupní i výstupní data a popis, co má dělat.

Proto je nejjednodušším postupem rozdělit si vstupy a výstupy na samostatné celky (= zprávy), ty ozobákovat, pojmenovat si jednotlivé funkce (=operace) a spárovat zprávy k operacím. Výsledkem je pak kostra WSDL. Pro lenochy je pak možné vygenerovat kód z oné kostry, vypublikovat WebServisu čistě jako třídu bez WSDL a do kostry doplnit zbývající části WSDL, které za nás vygeneroval publisher.

Tento přístup má hned několik kladů:
* tvůrce se musí nejdříve zamyslet nad strukturou dat, což nebývá tak úplně zvykem
* to zabrání nutnosti neustále měnit rozhraní (a tím i WSDL) při změně datového modelu
* tvůrce uvažuje v intencích dokumentů a operací nad nimi, což mu umožní přehoupnout se přes onen RPC XORBA zlozvyk
* WSDL je čitelné a "hezké" a interoperabilní (pokud je navrženo jako document-wrapped (.NET nic jiného neumí))
* celý návrh systému je pak mnohem lépe udržovatelný, modularizovatelný, rozšiřitelný, znovupoužitelný, lépe odladitelný

na závěr se s vámi podělím o jednu velice podstatnou metodickou pomůcku. Z jednoho neúspěšného projektu Systinetu jsem si odnesl následující systém návrhu SOA aplikací:
1)Vyjmenuj si všechny role participantů, kteří se na aplikaci (procesu) podílejí.
2)Namaluj si síťový graf procesu podle jednotlivých rolí.
3)Rozděl proces na ucelené podprocesy.
4)Vytvoř XML dle struktury procesů, a to tak, že root elementem bude název procesu a v něm na stejné úrovni jako elementy názvy podprocesů. Při vzájemném zanoření podprocesů zanoř element podřízeného podprocesu do elementu nadřazeného.
5)Ke každému participantovi se pokus navrhnout kostru struktury dat (XML, stačí root element a jednu úroveň elementů v něm), které mohou od nich ostatní požadovat.
6)Tato XMLčka sluč do jednoho dokumentu, a to tak, že je podle pořadí v síťovém grafu poskládáš pod sebe do elementu procesu či podprocesu, ve kterém se role vyskytuje.
7)Ke každé roli označ data, která potřebuje pro svoji práci.
8)Z těchto dat poskládej ke každé roli zprávu, kterou bude participant akceptovat na svém vstupu.
9)Data, která participant produkuje, označ jako odchozí zprávu.
10)Dopodrobna rozpracuj XML schema jednotlivých zpráv

Každá role pak odpovídá jedné operaci WebServisy. Pokud hraje jeden participant více rolí, má jeho WSDL více operací. Každý proces i podproces má ještě dvě fáze, které je také nutno zmínit: iniciační (musí vyletět první zpráva) a ukončovací (poslední zpráva musí někam doputovat).

A co se týká implementace celého systému, máme minimálně principiálně čtyři možnosti.

První a nejlepší možností by bylo použít principy z onoho neúspěšného (když vymyslíte něco, co předběhne dobu o deset let, a stane se to díky tomu nezproduktovatelné, naštve to) produktu. V dubnu 2010 mi vyprší klauzule o mlčenlivosti, tak si počkejte na podrobnosti :-) Nemohu Vás bohužel ani odkázat na nějaký veřejný zdroj, protože bylo všechno staženo včetně blogspotů :-(

Další možností je pouštět data do messagingového systému, kde budou zprávy z jedné instance procesu korelovány. Ale to jsme u TIBCO Randezvous a to Vám fakt nemohu doporučit ;-) .

Třetí možností je dát do každé zprávy tranzitivní obal všech zpráv požadovaných mými následovníky. Tento Message Decorator pattern se používá v ESB, má jak své výhody, tak nevýhody. Některé věci v něm nejde bez Cimrmanova úkroku stranou dělat vůbec.

Čtvrtá možnost je ta nejčastější. Každý proces či subproces je implementován jednou fasádní WebServisou. Pro jednoduché věci je BPEL, složitější logiku je lépe kódovat. Iniciační fázi odpovídá příjem zprávy a finalizační pak odeslání výstupní zprávy. Pro jednoduchost je možno implementovat několik rolí v procesu přímo ve fasádě, ale je dobré si tam minimálně nechat čisté rozhraní pro případné oddělení.

PS: Kdyby to pomohlo alespoň jednomu z vás, nepsal jsem to zbytečně. A vyjmenovat výhody takovéto metodologie návrhu nechám na Vás jako domácí cvičení do komentářů

úterý 17. června 2008

Bude MVC model nahrazen architekturou RIA + SOA?

Uvidíme :-)
Každopádně jsem si dnes přečetl článek od Nolana Wrighta a řekl si - zase další BFW (Buzz Flame War :-) ). Ale přeci jenom mi to nedalo a trošku jsem se nad tím zamyslel. Nemá samozřejmě smysl papouškovat názory od CEO firmy produkující Appcelerate, platformu pro "tvorbu RIA+SOA aplikací" už jenom proto, že s ním nemohu úplně souhlasit.

V čem se vlastně tak liší tyto dvě architektury?
ModelViewController je architektura, která dělí celou aplikaci na tři (ale spíš čtyři) vrstvy:
* View neboli prezentační vrstvu
* Model neboli reprezentaci dat (a tou čtvrtou pod Modelem je pak databáze)
* Controller nebo business logika

Co se týká vývoje Webových Aplikací, o které jde především, se prezentační logika sestává s generování HTML kódu (ve světě Javy JSP) (no dobře, máme ještě nějaké JavaScripty, ale ty slouží čistě jako podpůrný prostředek pro zobrazení, nic víc), Model je Objektová vrstva nad relační databází (ve světě Javy třeba EntityBeans či Hibernate POJOs) a Controller je pak něco mezi (typicky Session Beany + různé controller frameworky, jako třeba Struts, Tapestry či HyperQbs :-) )

Stav je držen primárně na straně Modelu, protože na klientovi toho moc držet nemůžete a Controller by měl být bezestavový.

RIA+SOA je oproti tomu dvouúrovňová architektura. Na straně klienta máme aplikační logiku napsanou v JavaScriptu, na straně serveru pak Webové Služby. Stav se primárně drží na straně klienta a WebServisy slouží pouze primárně jako Donory a Akceptory dat (a tady se s Nolanam vcelku lišíme, protože on přenáší business logiku na stranu WebServis, což potírá samu podstatu RIA - RIA není jenom o pěkném Ajaxovaném xichtu, ale také o tom, že klient obstarává velkou část aplikační logiky).

Stav je tady držen na dvou místech. Primárně je držen na straně klienta a teprve až výsledky aplikace se promítnou na server přes rozhraní Webových služeb, které pak slouží jako poskytovatelé oněch výsledků dalším aplikacím.

Taková RIA+SOA architektura pak přímo vybízí k použití Loosely-Coupled Coarse-Grained WebServis a či dokonce RESTu.

úterý 3. června 2008

Ať žije frameworkování - 2. díl

Dneska jsem si přečetl zajímavý článeček na Sys-Conu, který dokazuje, proč je funkcionální programování lepší než stávající trendy OOP v Javě.

Tím by ani nebyl onen článek tak zajímavý, obzvláště proto, že není logicky korektní a v důkazu excelentnosti JVM jazyka Scala používá mimo jiné metodu, u které sám píše, že je "more difficult to understand":
class CharReader (r: Reader) extends Reader {
override def repeatForEach (f: String => Unit) = {
r.repeatForEach ((s: String) =>
s.toList.foreach ((c: Char) =>
f (c.toString)));
}
}


Mnohem podstatnější je ale následující ukázka kódu:
public static void main(String[] args) {

BeanFactory factory =
new XmlBeanFactory(new FileSystemResource(“applicationContext.xml”));
Reader arrayReader = (Reader) factory.getBean (“arrayReader”);
Reader charReader = (Reader) factory.getBean (“charReader”);

String s = arrayReader.read();
while (s != null) {
System.out.println (s);
System.out.println (charReader.read());
s = arrayReader.read();
}
}

Nikdo nemůže říct, co tento kód udělá, protože veškerá jeho logika je dána ve Springové konfiguraci. Readery mohou být propojeny či mohou být nezávislé, nikdo neví, co vlastně čtou atd. atp. . Sice se to lehce píše, ale odladit to... a případně po někom převzít či se k tomu po roce vrátit...

Proto frameworky raději nepoužívám a pokud ano, pak s velikým odporem. Leda by to byty ty základní, utilitózní, jako je třeba log4J či SaX/DOM. A pokud už nějaký použiju, musí být naprosto jednoduchý a přímočarý, bez jakýchkoli automagismů, jako třeba FreeMarker či servlet container.

středa 28. května 2008

Aprílové vydání TheServerSide, ale 28.května

Když jsem dnes dostal mailem sčot TheServerSide, trošku jsem si ho procházel. Po přečtení tohoto článku jsem došel k názoru, že se musí jednat o aprílový žert. Joseph Ottinger, editor TheServerSide na plný úvazek, píše, že bez schopnosti rozpoznávat sémantiku kódu půjde Java do kytek. A na čem to dokazuje? Uvádí příklad rozhovoru:
P:To, co bych chtěl, je x.contains(y)

G:Jasně, je jedna metoda v Collection API, která, myslím, dělá to, co bys chtěl.

P:Ale moje kolekce se nejmenuje x!

Představa autora je taková, že někdo si stáhne z webu kus kódu (v tomto případě příklad na použití contains(), cut&paste-ne ho do svého a Java sama nějak automagicky pozná, co vlastně měl na mysli!
Proto jsem použil akronymy G jako Guru a P jako Pitomec.
V diskusi ke článku je jeden příspěvek, který naprosto přesně vystihuje situaci:
Jasně, Java půjde do kytek, protože mi každé ráno sama od sebe neuvaří kafe...


A na závěr to nejhorší. Tento článek má odkaz v mailu, který mi přišel! Na hlavní stránce! Pokud takto má vypadat qalita článku tohoto serveru, tak buď si z lidí vystřelili, nebo je tu úpadek jak prase.

PS: Chtěl jsem odpovědět na příspěvek. Použil jsem své platné přihlašovací údaje. Dostal jsem Invalid username/password. Nechal jsem si poslat email přes Forgotten your password?, došly mi stejné údaje, jako jsem zadával. Zadal jsem je znovu přes C&P a bác ho - pořád invalid username/password.

středa 30. dubna 2008

Jak na JBossí WebServisy v IDEA

Po několika dnech Googlování a pokusů a omylů se mi konečně podařilo rozchodit první WebServisí komunikaci klient-servisa na zákeřné kombinaci: Windows XP, Sun J2SE 1.6.0_5, JBoss 4.2.2GA, IntelliJ IDEA 7.0.3

Co je třeba udělat:

  1. nainstalovat ony zmíněné produkty :-)
  2. nepoužívat implicitní JAVA_HOME/jre/lib/endorsed adresář, protože se buď nepodaří zkompilovat vygenerované stuby nebo začne řvát JBoss
  3. stáhnout si a nainstalovat jbossws patch:

    1. rozbalit (ideálně hned vedle jboss-4.2.2GA, ať to máte pohromadě)
    2. přejmenovat JBOSSWS_HOME/ant.properties.template na JBOSSWS_HOME/ant.properties
    3. v JBOSSWS_HOME/ant.properties nastavit propertu jboss422.home na JBOSS_HOME (např ../jboss-4.2.2GA)
    4. v JBOSSWS_HOME/build/build-deploy.xml odstranit závislost targetu deploy-jboss422 na undeploy-jboss422 (jinak na Vás zařve, že nemůže smazat soubory v JBOSS_HOME)
    5. pokud není ant v cestě, tak je třeba nastavit
      set "ANT_HOME=JBOSSWS_HOME\tools\ant"
      set "PATH=%ANT_HOME%\bin;%PATH%"

    6. v JBOSSWS_HOME spustit ant deploy-jboss422 - tím se do JBOSS_HOME/lib/endorsed nahrají patřičné jary JAXBčka


  4. napsat si servisu (Web a WebService (JAXB2.1, nikoli Axis))
  5. nadeployit servisu do JBossu
  6. založit projekt pro klienta (WebService client, JAXB2.1, nikoli Axis)
  7. vygenerovat stuby z WSDLka WebServisy
  8. upravit example.HelloWorldClient tak, aby zavolal onu servisu
  9. vytvořit Run Configuration pro klienta (typ Application)
  10. do VM Parameters dát "-Djava.endorsed.dirs=C:\Documents and Settings\tapik\.IntelliJIdea70 \system\webservices\jaxws-ri-2.1\"
  11. spustit a doufat, že funguje

Pokud funguje, je vymalováno.

pátek 25. dubna 2008

IDEA WebService plugin a JDK 1.6

Po šesti letech zkušeností s WASPem (alias Systinet Server for Java) jsem se vrhl do implementace WebServisy, kterou lze nadeployit do JBossu bez nutnosti jakékoli další knihovny. Tak jsem zvolil JavaWS.
Ninstaloval jsem si IDEA WebService Plugin, juknu se letmo na tutorial, zkusim si spustit example webservisu a bac ho:
The exception com.sun.xml.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class example.jaxws.SayHelloWorldFrom is not found. Have you run APT to generate them?
Tak to jsem teda čuměl jak puk. Řeknu si No nic, ask Google. Googlil jsem hodinu, prošel jsem si dokumentaci k JavaWS, JBoss WS, Idea Webservice Plugin. Jediné, co jsem našel, že všem fungovalo, bylo nastavit java.endorsed.dirs na adresář s javaws dodávaný k IntelliJ IDEA. Furt nic. Zkoušel jsem už různé obskurní řešení typu @WebServiceProvider, ale furt nic. Nakonec jsem našel toto naprosto triviální řešení.
By default generuje JavaWS ve formátu WRAPPED, ale já po něm požadoval chování BARE. Stačí tedy nastavit:
@SOAPBinding(parameterStyle=ParameterStyle.BARE) a je po ptákách.

středa 23. dubna 2008

Krátké oRESTování

O RESTu se všude vedou dalekosáhlé debaty. Například zde se Vlasta Vávrů snaží přijít oné věci na kloub.
Nejsem sice kdovíjaký REST-guru, ale svoje si k tomu řeknu:
* REST je o zdrojích (resourcech). Každý zdroj má svou jednoznačnou identifikaci - URI. Po dobu jeho životnosti pod tímto URI vždy a za každých okolností najdete tento zdroj (jestli je to URLčko nebo URN do repozitáře je buřt). Každý zdroj JE STAVOVÝ. Minimální sada stavů je jsem - budu - byl jsem. Představíme-li si jako zdroj seznam členů CZLUGu, je jasné, že se bude v čase měnit. Ale pokaždé dostanete logicky totéž, aktuální seznam členů. No, aktuální, RESTózní architektura umožňuje plnohodnotné interceptory, kde například může stát cache, která vrátí seznam klidně včerejší. I o tom REST je. Data nemusí být vždy aktuální.
* důležitou vlastností RESTózních aplikací je omezená množina operací, které lze s daným zdrojem provádět. Proto je HTTP RESTózní, má čtyři hlavní operace GET, POST, PUT a DELETE.
* komunikace MUSÍ BÝT BEZESTAVOVÁ, tedy komunikace nesmí zahrnovat stav klienta. To ale neznamená, že sezení jako takové je v RESTu nesmysl. Pouze jeho řešení pomocí sušenek je nepřípustné. Mám-li sezení zakomponováno do URL, jsme v pohodě. Samo sezení se stává zdrojem. Dostávám se tak do situace, kdy logická operace přidej produkt s URI:XY do košíku patřící sezení s URI:SSS (třeba HTTP POST SSS produkt=XY) bude mít za následek vždy to totéž a o to právě v RESTu jde. Dalším problémem pro bezestavovost komunikace jsou <INPUT TYPE="HIDDEN">. Tyto jsou v HTML zavedeny právě pro udržení stavovosti komunikace, čili typická antiRESTóznost.
Doufám,že si někdy najdu čas a všechno, co o RESTu vím, sem napráskám.