31. března 2008

Vytvářet nejdříve WSDL nebo Java rozhraní?

Mé zkušenosti s vytvářením webových služeb resp. WSDL (viz např. minulý článek) mě dovedly ke zjištění, že vždy raději nejdříve navrhnout WSDL a poté si nechat vygenerovat Java kód (WSDL First Development) než opačně - napsat Java rozhraní, přidat anotace a vygenerovat WSDL (Java First Development).

Píši vždy, ale myslím tím vždy, když budu mít možnost si službu sám navrhnout (zejména pro nové projekty) a příjemcem služby bude jiný systém než můj. Již více nebudu navrhovat WSDL pomocí Java rozhraní a anotací, protože s tím mám špatné zkušenosti:

  • Zatím se mi nikdy nepodařilo vytvořit pomocí anotací takové WSDL, které bych si představoval. Vždy jsem musel vzít nějaké kompromisní řešení. Většinu lze ovlivnit pomocí JAX-WS anotací, ale pokud potřebuji jít dále (například vyladit mapování jednotlivých objektů), tak už to není zcela jednoduché a přijde mi to spíše komplikované. Dosud mám zkušenost s XFire a Apache CXF.

  • Webové služby většinou používám při integraci s jinými systémy převážně systémy od jiných dodavatelů. Svým způsobem je pěkná podoba WSDL mojí vizitkou. Nemluvě pak o tom, že mohou být problémy při vytváření klientů v jiných jazycích než je Java. Ano, ono to vždy půjde, ale jak moc sližitě?

  • Když se mi generuje WSDL z kódu, tak se mi lehce může stát, že něco změním a hned se mi změní WSDL (a ani si to nemusím uvědomit). Pokud budu mít nejdříve WSDL, tak toto se mi stát nemůže.

Samozřejmě vytváření WSDL z Javy se pořád hodí - já osobně vidím hlavní oblast použití pro případ komunikace mezi dvěma systémy (nebo v rámci jednoho systému), kde mám pod kontrolou klienta i server. Zde je mi tak nějak jedno, jak to WSDL vlastně vypadá. Ideální jsou v tomto ohledu možnosti Springu - Remoting and web services using Spring.
Pokud budu mít klienta i server pod kontrolou na stejné platformě, tak pak je ale otázka, proč používat webové služby a nepoužít něco rychlejšího, např. RMI, Hessian, Burlab... Přeci jen webové služby moc výkonné nejsou.

Může se také stát, že již budu mít nějaký historický systém a bude potřeba zpřístupnit určitou funkcionalitu přes webové služby - zde asi také bude vhodné jen přidat anotace, přidat konfiguraci a bude hotovo.

Apache CXF vs. Codehaus XFire

Minulý rok jsem na jednom malém projektíku použil XFire pro zpřístupnění určité funkcionality přes webové služby.

Minulý týden jsem opět potřeboval dát dohromady pro účely demo aplikace nějakou webovou službu a chtěl jsem tedy znovu použít XFire, protože jsem nechtěl nic vymýšlet. Ale hned při zobrazení úvodní stránky projektu XFire se mi zobrazila tato hláška:

XFire is now CXF - User's looking to use XFire on a new project, should use CXF instead. CXF is a continuation of the XFire project and is considered XFire 2.0. ...

Nedalo mi to, abych tedy nevyzkoušel Apache CXF, protože se to někdy v budoucnu může hodit.

Bohužel mě to moc (zatím) nenadchlo, určitě také kvůli tomu, že vše ještě není úplně dotažené jak má být:
  • Kdy píšou, že je to vlastně XFire 2.0, tak bych očekával nějakou návaznost, možnost migrace na vyšší verze. Potřeboval jsem převést popis webové služby (JAX-WS APIs, specifický binding objektů pomocí Aegis), konfiguraci webové služby (nastavení serveru) a testy.
    Migrace JAX-WS byla bez problémů, což je určitě tím, že se jedná o JSR 224 specifikaci a Apache CXF nabízí v současné době plnou implementaci. Aegis je i v Apache CXF, takže zde také nebyl problém.
    Konfigurace je nyní úplně jiná, takže tato část se musí přepsat. Ale je k dispozici celkem rozumná migrační dokumentace, takže s tímto jsem problém neměl.
    Bohužel testy se mi nepodařilo zmigrovat vůbec a o co hůře, ani se mi žádné testy nepodařilo napsat! Určitě je to také tím, že jsem k tomu našel minimum dokumentace. Pomocí XFire se psaly testy parádně.

  • S dokumentací budu pokračovat - jsem asi "rozmazlený" Springem, kde vždy najdu to co potřebuji. Tady prostě ne - základní dokumentace je dle mého názoru nedostatečná a JavaDoc mi přijde hodně slabý. Zkoušel jsem si i nějaké kusy kódu uvedené na webu a i když jsem je překopíroval, tak mi to hlásilo chyby, musel jsem něco dopisovat... Tohle je prostě slabina.

  • Každý, kdo dělá s Javou je zvyklý, že když nastane výjimka, tak se vypíše celý průběh volání. Tady to vše Apache CXF "nějak" chytá a ve výsledku to jen vypíše chybovou hlášku bez nějakých dalších informací.

  • Ani nevím, zda Apache CXF vznikl až po XFire nebo oba projekty spolu běží souběžně, každopádně bych si troufl odhadnout, že hlavní důvod přechodu na Apache CXF bude architektura aplikace. Apache CXF je zcela postaven nad Springem, má naprosto modulární architekturu, takže není žádný problém "cokoliv" změnit, upravit. Ale když k tomu není pořádná dokumentace, tak pak architektura může být sebelepší...

Hrál jsem si s Apache CXF jeden den, takže moc toho vyzkoumat zase nešlo a na něco jsem určitě nepřišel. Budu rád za vaše postřehy.

24. března 2008

Konkurenční přístup k datům - zamykací mechanismy, díl druhý

V předchozím díle jsem popisoval optimistické zamykání na datové úrovni, v tomto díle popíšu pesimistické zamykání a také zmíním další možný způsob řešení konkurenčního přístupu k datům - plně izolované transakce.

Pesimistické zamykání

Tento způsob zamykání již předem počítá s tím, že bude docházet ke konkurenčním přístupům k datům, a proto si každá transakce zamkne svá data a nepustí je dokud data nebudou úspěšně změněna nebo pokud se neprovede roll-back transakce. Tím je zaručeno, že data během transakce nikdo jiný nezmění, a že se aktualizace vždy povede. Také je zaručena konzistence čtených dat v rámci jedné transakce.

Pesimistické zamykání na úrovni dat je řešeno přímo databázovými stroji, např. Oracle používá SELECT FOR UPDATE.

Výhody: není potřeba měnit datový model, zaručuje konzistentní data pro čtení, zaručuje, že jiná transakce nezmění zamknutá data, lepší než izolované transakce - menší nároky na zajištění konzistence dat, menší pravděpodobnost dead-locku.

Nevýhody: všechny potencionálně konfliktní transakce musejí používat stejný přístup nad danou datovou jednotkou, výrazně snížena výkonnost, při častém použití se zvyšuje pravděpodobnost deadlocku (jedna transakce čeká na druhou až uvolní svá data), použití SELECT FOR UPDATE má svá určitá omezení, ne všechny perzistentní Java ORM nástroje tento přístup umožňují, omezená použitelnost cache.

Použití: vhodné pro aplikace, kde je potřeba mít zaručenou konzistentnost čtených dat, kde nemáme možnost použít jiný typ zamykání.


Plně izolované transakce

Pokud budeme používat transakce, které jsou od sebe vzájemně izolovány pak databázový stroj zaručí, že výsledek spuštění více transakcí v jeden moment bude stejný, jako kdyby se jednotlivé transakce spustily postupně za sebou. Bohužel tímto přístupem velice trpí výkonnost a škálovatelnost databázového stroje.
Pro řadu případů je možné použít slabší úrovně izolace - REPEATABLE READ nebo READ COMMITTED.

Výhody a nevýhody jsou zřejmé - jednoduché na použití, zabraňuje většině problémů s konkurenčním přístupem k datům, ale za cenu big overhead.

Použití bude tam, kde ztráta výkonnosti je akceptovatelná nebo tam, kde je naprosto podstatná konzistence čtených dat.


Já osobně preferují mezi ORM nástroji Hibernate, proto ještě uvádím odkaz na možnosti vymezení transakcí resp. řešení konkurenčního přístupu v tomto nástroji.

V příštím a posledním díle se budu věnovat offline zamykacím mechanismům.

Konkurenční přístup k datům - zamykací mechanismy, díl první

Každý asi ví, že konkurenční přístup k datům je nutné řešit, ať už na datové nebo aplikační úrovni. Mám ovšem tu zkušenost, že většina kolegů tento problém řeší až v době implementace případu užití, což si myslím, že už je trochu pozdě. Přístup k datům resp. zvolený zamykací mechanismus ovlivňuje návrh samotné aplikace (datový model nebo aplikaci samotnou) a proto by způsob přístupu k datům měl být vyjasněn již v době analýzy a zohledněn v návrhu aplikace.
Rád bych tedy v sérii několika článků zmínil základní způsoby řešení konkurenčního přístupu k datům - ať už na úrovni datové nebo aplikační.

Optimistické zamykání

Navzdory svému jménu vlastně o žádné zamykání nejde. Transakce přistupují k datům bez nějakého omezení, pouze při updatu se ověřuje, zda data nebyla v průběhu transakce změněna jinou transakcí od doby, kdy se data načetla. V případě kolize je nutné transakcí vrátit (roll-back).
Kontrola změny dat se může řešit pomocí:
  • evidence verze. Pro tuto variantu je nutné přidat nový speciální sloupec do tabulky pro evidenci verze. Při každé změně hodnoty se zvýší verze a pak je jednoduché zjistit, zda došlo ke změně nebo nikoliv.

  • evidence času poslední změny. Víceméně totožné jako předchozí varianta, ale místo verze se eviduje timestamp poslední změny.

  • porovnání nové a původní hodnoty. Velké výhoda tohoto přístupu je ta, že není nutné přidávat žádný sloupec, tedy vhodné pro systémy, kde nemůžeme provádět úpravy v datovém modelu.

Většina ORM nástrojů minimálně jeden z uvedených způsobů podporuje a je pouze otázkou konfigurace, jaká implementace se použije.

Výhody: snadná implementace, nenáročná kontrola změny dat a roll-back pouze v případě konfliktu

Nevýhody: všechny konkurentní transakce (myšleno nad jednou datovou jednotkou, např. tabulkou) musejí používat optimistické zamykání, není vždy možné provádět změny v datovém modelu a tedy přidávat nové sloupce (není možné vždy použít třetí variantu ověřování, např. problémy s null hodnotami, desetinná čísla), není zaručena konzistence čtených dat.

Použití: vhodné pro aplikace, kde máme datový model pod kontrolou, kde nám moc nevadí nekonzistentnost dat při čtení a hlavně tam, kde nám nevadí, když se aktualizace dat neprovede. Pokud budu v UI mít složitý formulář nebo průvodce přes několik obrazovek, tak pak bych optimistické zamykání určitě nepoužil, protože uživatel by asi nebyl moc šťastný, když by si po několika minutách vkládání dat do formulářů přečetl hlášku, že data nelze uložit.

V příštím díle se zmíním o pesimistickém zamykání a dalších možnostech řešení konkurenčního přístupu k datům.

2. března 2008

Proč nemám rád Seam

V poslední době se hodně hovoří o JBoss Seamu - píší se o něm články (1, 2, 3), přednáší se o něm, u nás v práci se vedou diskuze, zda ho použít nebo ne. Mě už to prostě nedá, abych zapřemýšlel veřejně, protože bych moc rád moje názory zkonzultoval s okolním světem.

Ještě než se pustím do "přemýšlení", tak musím poznamenat, že jsem hodně ovlivněný Springem - mám tu technologii rád, nikdy mě nezklamala, ztotožňuji se s názory lidí ze SpringSource. Mám také rád Javu, protože mám možnost plné kontroly nad aplikací, když chci napsat výkonnou, škálovatelnou a robustní aplikaci.
Také musím napsat, že nemám žádnou větší zkušenost se Seamem, pouze jsem si zkoušel a procházel nějaká dema.

Co se mi na Seamu líbí?

  • výborně integruje (a opravuje) technologii JSF a pokud dnes někdo chce používat JSF, tak asi určitě se Seamem.

  • Seam framework integruje spoustu technologií dohromady v jeden kompaktní celek.

  • Seam považuji nejsilnější v prezentační vrstvě, hlavně se mi líbí možnost využití a integrace AJAXových komponent.

  • Nemůžu nezmínit rychlost vývoje, potažmo náklady na vývoj aplikace.

Co se mi na Seamu nelíbí?

  • velice mi jsou blízká "čistá", flexibilní řešení, protože člověk nikdy neví (lépe řečeno zákazník nikdy neví). Z tohoto pohledu se mi Seam moc nelíbí - z vlastní zkušenosti vím, že hodně často je potřeba ještě jedna vrstva (Facade) mezi kontrolerem a aplikační vrstvou. Dnes je in, že vše musí být POJO, ale pokud POJO má na sebe navěšeno spoustu anotací, které mi zabraňují v testování, které mě vážou k nějakému řešení, tak už to není POJO.

  • Všechno kromě snad prezentační vrstvy (ale i zde by se dalo spekulovat) jde udělat stejně dobře nebo lépe pomocí Springu. Mám na mysli zejména možnosti integrace s dalším knihovnami, možnosti konfigurace, možnosti testovatelnosti apod.

  • Spring security (dříve Acegi framework) považuji za nejlepší open-source řešení pro zajištění bezpečnosti aplikací. Seam pěkně zapojil Drools, ale i tak se to nedá srovnávat, hlavně co se týče flexibility a možností.

  • Vše je konfigurováno pomocí anotací. Někdo je má rád, někdo ne. Já jak kdy, takže mi tu chybí možnost volby. Např. konfigurace scheduleru přes anotace v Seamu mi přijde celkem hrozná.

  • Kompaktnost řešení je negativně vyvážena omezenou možností použití řešení třetích stran.

Co říci závěrem

V žádném případě nemohu říci, že Seam je špatný framework, protože to není pravda. Seam udělal resp. udělá velkou službu Java světu, protože dokáže přitáhnout lidi, kteří chtějí dělat malé až středně velké webové aplikace bez nějaké větší aplikační logiky v pozadí, kteří ale nechtějí nebo mají strach se prokousávat tolika technologiemi, které je potřeba pochopit a naučit se.

Já ale (snad) už začátečník v Javě nejsem, potřebné technologie znám, nerad vytvářím GUI, spíše mě zajímá pozadí aplikace, píši malé, středně velké až velké aplikace, které nepracují pouze s databází, které mají mnohdy složitou aplikační logiku, které mají být výkonné, robustní... A proto tedy nemám rád Seam.

Java applety a SSL

Jak jsem již dříve referoval, na jednom našem projektu používáme komponentu ImageUploader pro nahrávání dokumentů do systému. Komponenta se automaticky dle verze prohlížeče spouští jako ActiveX (pro IE) a nebo Java applet. Komunikace mezi komponentou a serverem je zabezpečena pomocí protokolu HTTPS.

Dále je důležité říci, že zákazník má vlastní certifikační autoritu, která není odvozena od žádné věhlasné věrohodné certifikační autority.

Pokud uživatel nechce, aby se mu pořád objevovala chyba, že cílová stránka má neplatný certifikát, tak je nutné importovat kořenový certifikát do lokálního úložiště důvěryhodných certifikátů na počítači daného uživatele. Tento postup je asi následující:

  1. Stáhnu si kořenový certifikát zákazníka vystavený na webu
  2. Kliknu na něj a průvodce mě provede instalací certifikátu

Postup velice jednoduchý a pro uživatele nijak komplikovaný.

Jenže je tu velké ALE - takto jednoduché je to pouze pro prohlížeč Internet Explorer. Pro Firefox je to složitější, protože má vlastní úložiště důvěryhodných certifikátů, takže je potřeba import kořenového certifikátu udělat ještě jednou zvlášť pro Firefox.

Pokud chceme používat Java Applety se zabezpečenou komunikací, tak musíme jít ještě dále, protože Java má také svoje úložiště důvěryhodných certifikátů a proto musíme kořenový certifikát vložit i sem. K tomu má Java nástroj keytool, který je sice celkem mocný, ale bez šance, že by s ním dělal normální uživatel internetu.

Co s tím? Řešením by bylo, kdyby kořenový certifikát zákazníka byl odvozen od nějaké světově věrohodné společnosti jako třeba VeriSign, Thawte. Tyto věrohodné firmy jsou již automaticky v úložištích důvěryhodných certifikačních autorit, takže by úplně odpadl import certifikátů. Jenže za to se platí a na to zákazník nemá peníze.
Dalším řešením by bylo, kdyby bylo jedno úložiště důvěryhodných certifikátů. To nevím, jak je moc reálné, takže to nemohu posoudit. Co mě ale nejvíce překvapuje, že Java resp. Java applet není schopen sdílet informace o certifikátech s prohlížečem, ve kterém běží?

Přijde mi tento postup natolik uživatelsky nepřívětivý (navíc ještě ve srovnání s technologií ActiveX), že se spíše ptám sám sebe, kde jsem udělal chybu já. Z mého pohledu je to další důvod pro mé tvrzení, že Java applety se moc nepovedly a už se nemůžu dočkat až bude něco lepšího, snad JavaFX.

Pokud mi můžete v tomto směru poradit, tak budu moc rád.