Author Archives: admin

EJB 3.0 vs. Spring

O víkendu jsem měl chvíli čas a jelikož jsem zjistil, že jsem snad poslední, kdo neposlouchá slavný podcast, tak jsem si pustil jeho čtvrté vydání. Neodolal jsem a psal jsem i poznámky, které se teď pokusím sepsat v srozumitelné podobě. Nejprve bych předeslal, že jsem veliký fanoušek a zastánce Springu, takže ode mě nečekejte nestrannost.

J2EE ≠ EJB

První důležitý bod je to, že Spring se nestaví proti J(2)EE, právě naopak. Dokonce i Rod Johnson (autora Springu) píše, že J2EE je hodně dobrá skupina standardů. Ale je mylné se domnívat, že J2EE = EJB. Pokud se podíváte co to je J2EE tak EJB je jenom jedna část z více než dvaceti! A byl právě důvod, proč vznikl Spring – umožnit snadno používat funkcionalit J2EE.

Vraťme se ale k EJB. Ty nám přinášejí následující věci (převzato z [1]):
1.Declarative Transactions Management
2.Remoting
3.Clustering
4.Resource pooling
5.Security
6.Thread management
7.EJB instance pooling
8.Business object management

Zajímavých je pravděpodobně jenom prvních pět bodů, zbytek využijete jenom pokud máte dostatek odvahy a vrhnete se do SFSB nebo entity bean. V případě že používáte jenom SLSB a MDB, vám poslední tři body žádný užitek nepřinesou (kromě pár starostí).

Projděme si tedy podrobně přínosy, které nám EJB přináší a porovnejme si je Springem

Declarative Transactions Management – Spring nám také umožňuje definovat transakce pomocí anotací (klidně i stejných jako používá EJB) a XML. Navíc tyto transakce fungují i pokud nemáme k dispozici JTA.

Remoting – Spring umožňuje remoting pomocí RMI, Hessian, Burlap, HTTP invokeru a JAX-RPC. Největší legrace je to, že když se rozhodnu změnit technologii, stačí mi změnit pár řádek v konfiguraci. Kód aplikace zůstane nezměněn

Clustering – Jedna z největších výhod EJB. Ale pozor, pokud používáte pouze bezstavové objekty jako SLSB a MDB, je clustering velice snadný. Jste si jisti, že k tomu potřebujete něco tak komplikovaného jako EJB?

Resource pooling – Například pool databázových připojení. To ovšem není vymoženost EJB jako spíše aplikačních serverů. Možné nahradit pomocí C3P0 nebo DBCP

Security – EJB nám poskytují rozsáhlé možnosti zabezpečení. Škoda jen, že si to každý dodavatel aplikačního serveru naimplementoval po svém, takže se můžeme rozloučit s přenositelností. Byla by to jedna z nejužitečnějších přínosů EJB, kdyby ovšem byla dostatečně definována.

Všimněte si že, JTA je ve výčtu chybí. Je to samostatný standard, na EJB zcela nezávislý. Takže argument typu „Pokud potřebujete distribuované transakce, musíte používat EJB“ je naprosto zcestný. JTA můžeme dokonce používat i mimo AS, například pokud použijeme JOTM.

Vidíme tedy, že Spring umí to samé jako EJB. Jak se tedy rozhodnout? V době EJB 2.1 bylo rozhodnutí snadné, pokud jste nepotřebovali žádnou ze specialit EJB jako je clusterování, MDB nebo SFSB bylo lepší zvolit Spring. Ušetřili jste si tak neuvěřitelné množství naprosto zbytečné práce s EJB.

Doba pokročila, EJB prošly kosmetickou operací, při které na starý ošklivý obličej našili masku anotací. Ta ošklivost je tam pořád, ale už ji nevidíme. Což mimo jiné znamená, že už můžeme EJB používat, aniž bychom museli psát (nebo generovat) hromady zbytečného kódu.

Za tu dobu ale i Spring hodně pokročil. Objevily se message driven POJOs, Terracota nám zajistila snadné clusterování i jiných než bezstavových objektů a SFSB pořád ještě nikdo nepoužívá.

Jak si tedy vybrat? Jelikož jsem fanoušek Springu, je odpověď jasná, mám pro to následující důvody:

Zjednodušuje práci s projekty třetích stran

Volání kódu někoho jiného je v podstatě jediné co Spring umí. Umožňuje mi snadno navázat můj kód na různé knihovny a další frameworky. Je důležité si uvědomit, že Spring nic nedělá (až na pár vyjímek). Jenom práci deleguje buď na knihovny nebo aplikační server.

Snadnost práce s nízkoúrovňovými Java standardy

Spring nám zjednodušuje práci s Java standardy, které jsou často hodně nízkoúrovňové. Hezkým příkladem je třeba Java Mail API. Kdo ho někdy používal v čisté podobě ví, že je to API těžko použitelné a kód který ho používá je netestovatelný.

Další příklad je i JDBC, dle mého názoru jedna z nejdůležitějších částí Java API. Opět je to nízkoúrovňové rozhraní, které by nemělo být používáno přímo. Spring nám jeho použití výrazně usnadňuje a navíc nám zamezuje udělat chybu. Malá anketní otázka: když používáte JDBC, jste si jisti, že děláte správně všechno to TCFTC (try{}catch{}finally{try{}catch{}})?

Svoboda výběru

Tím se dostáváme k svobodě výběru. EJB mě nutily pro perzistenci používat entity beany. Když se přišlo na to, že jsou nepoužitelné, nutí mě používat JPA. Pokud ale JPA nechci nebo nemohu používat, už mi nezbude nic jiného než JDBC. Spring mi na druhou stranu říká: „Já ti věřím, že svým potřebám rozumíš natolik, že víš, kterou technologii si vybrat. Ať si vybereš cokoliv, jsem ochoten ti pomoci.“ Takže mi zjednodušuje práci s JDBC, iBatis, JPA, JDO atp. Pokud nevím co si mám vybrat, měl bych se přeškolit na .NET, tam mi to řeknou.

Snadnost konfigurace aneb „Nemáte-li Spring, musíte si ho napsat“

Všiml jsem si, že kdo nepoužívá Spring, napíše si obvykle jeho obdobu. V každé aplikaci potřebuji konfiguraci. Ať už je to čtení nastavení z properties souboru, nebo nějaký druh XML konfigurace. Jelikož mi EJB s tímto ani trochu nepomohou, musím si to obvykle napsat sám. Často se tvoří nějaká SLSB, která konfiguraci načítá a ostatní beany ji využívají. Ale to je přesně to co mi zajišťuje Spring!

Dependency injection

Myslím tím opravdovou dependency injection. Tzn. že si mohu injektnout (šlehnout?) cokoliv kamkoliv. Do jakékoliv třídy mohu vložit string, odkaz na soubor, jméno třídy, referenci na cokoliv, mapu, list, preperties soubor, zkrátka cokoliv mě napadne. EJB jsou v tomto směru dost omezené. Zde bych si dovolil varování. Tato vlastnost Springu je neuvěřitelně návyková. Jakmile si na DI zvyknete, už se vám bez ní bude neuvěřitelně špatně pracovat. Takže pokud chcete pracovat s EJB, radši si se Springem nezačínejte.

Spolupráce s MVC frameworky

Spring podporuje všechny možné MVC frameworky. EJB podporují JSP, servlety a JSF. SLSB prostě nikam jinam neinjektujete.

Dostupnost prostředí

Aplikaci napsanou ve Springu mohu použít v jakémkoliv prostředí, které mi poskytuje služby, které potřebuji. Pokud souhlasíme s tvrzením, že 90% procent aplikací je jednoduchých, tak nám stačí Tomcat nebo Jetty. Aplikaci, napsanou v EJB 3, mohu zatím nasadit na jednom jediném AS, který na tom jen tak mimochodem není moc dobře se stabilitou.

A jaké jsou nevýhody Springu? Jednou z největších je politika. Za EJB stojí velké společnosti a neuvěřitelné množství peněz. Velcí klienti jako třeba banky mají (nebo spíše měli) nedůvěru k open source řešením. I když i to se mění, už i BEA začala výrazně podporovat Spring. To by moho nedůveřivcům něco naznačit. A už i velké společnosti pomalu začínají chápat, že použití nebo úprava open source řešení jim zajistí levnější a kvalitnější produkt, než kdyby jen spoléhali na standardy nebo řešení velkých výrobců.

Objevuje se argument, že EJB 3 jsou pro programátora snazší než Spring. Existuje ale projekt Pitchfork, který Springu umožňuje číst EJB anotace a konfigurovat svůj application context podle nich (o Pitchworku plánuji něco napsat v brzké době). EJB 3 navíc nejsou vůbec jednoduché, jenom se tak na povrchu tváří. Kdo si myslí, že jsou jednoduché, ať mi odpoví na následující otázky. První kdo na ně odpoví a nemá iniciály M.R. získá nehynoucí slávu:

1) EJB 3 umožňují získat referenci na SLSB z JNDI následovně


    InitialContext ic = new InitialContext();
    Hello  hello = (Hello)ic.lookup(Hello.class.getName());
    hello.hello();

Otázka je následující:
a) Na co ukazuje reference hello? (Je to home objekt, nějaká proxy, …)
b) Musí mít každý klient svoji referenci, nebo je bezpečné ji sdílet?
c) Je potřeba ji nějak vracet do poolu?
d) Co se stane, když po tom co referenci získám a před tím než ji použiji dojde k přerušení spojení s aplikačním serverem?

2)Je bezpečné injektnout SFSB do servletu?

Reference

[1] Johnson, Rod; J2EE Developement without EJB; Wiley Publishing; 2004

[2] Sriganesh, Rima Patel; Mastering Enterprise Java Beans 3.0; Wiley Publishing; 2006

Knihovnička softwarového inženýra: Peopleware

Možná jste si všimli, že fanoušek knih z dávnověku softwarového inženýrství. Jednou takovou knihou je i Peopleware jejíž autoři jsou Tom DeMarco a Timothy Lister. První vydání zdobí letopočet 1987. Z názvu můžete soudit, že je to kniha především o lidech. Mohl by ji charakterizovat následující citát:

Hlavní problém naší práce není ve své podstatě ani tak technologický jako spíše sociologický.

Jednotlivé kapitoly popisují problémy, s kterými se naši předci potýkali v dobách temna. Zajímavá je například část druhá, která popisuje pracovní prostředí. Představte si, že tenkrát lidé pracovali v prostorech zvaných openspace. Myšlenka byla taková, že se ušetří spousta peněz tím, že se nacpe co nejvíce lidí na co nejmenší místo. Nějak jim nedošlo, že tím ohromě snižují produktivitu práce lidí, kterým platí dost velké peníze. Zajímavá jsou následující čísla. Vývojář obvykle pracuje

30% času sám
50% času s kolegou
20% času s dvěma nebo více lidmi.

Z toho nám plyne, že 30% času nám hluk vadí a 70% času ho generujeme. Čím více máme lidí na menším místě a čím méně je přepážek mezi nimi, tím méně toho udělají. Jaké štěstí, že v dnešní době už si management umí spočítat, že ztráty způsobené sníženou produktivitou jsou větší než peníze ušetřené na kancelářském prostoru. Jinak bychom si museli postesknout:

Existuje milión cest jak ztratit pracovní den ale neexistuje ani jedna jak ho získat zpět

Další části jsou už dnešku přeci jenom blíže. Jsou o lidech a ti se tak rychle nemění. I když i zde se najdou výjimky. V dávných dobách někteří manažeři žili v iluzi, že jsou všichni lidé stejní. Že jsou něco jako součástky stroje, kde je velmi snadné jednu součástku vyjmout a místo ní strčit stejnou, která okamžitě začne dělat práci té předchozí. Chtěli prý dokonce aby se lidé stejně oblékali – říkali tomu dress code. Dnes už se naštěstí všichni poučili a vědí, že v různorodosti je síla a drobná výstřednost není na překážku.

Celek je víc než jen souhrn všech částí.

Hodně zajímavá je i z pohledu dnešní osvícené doby část čtvrtá – o týmech. Autoři v ní tvrdí, že mít sehraný tým je to nejlepší co se vám na projektu může stát. Když lidé vědí co mohou od sebe navzájem očekávat, když si rozumí a hlavně když je baví pracovat dohromady. Prý je to ta nejlepší motivace. Já osobně bych souhlasil. Pokud jste ale manažer a máte opačný názor, předkládají několik rad, jak tým zaručeně rozbít. Vyberu jich jen pár:

Byrokracie – pokud chcete rozbít tým, je nejlepší je zahrnout hromadou papírů
Fragmentace času – pokud nechcete aby se vám tým semkl, je dobré nechat lidi dělat 20% času na jednom projektu, 30% na druhém a 50% na třetím
Přikrášlené termíny – nerealistické termíny u kterých není vidět, proč všechno musí být hotovo před zvoleným datem. Nejlepší způsob jak lidi demotivovat
Přesčasy – vhodné kombinovat s předchozím. Vždy se nejde jedinec, který nebude moci nebo chtít dělat stejně přesčasů jako ostatní. Můžete si být jisti, že se vám z toho podaří vykřesat krásné negativní emoce, které zajistí, že se tým nesehraje.

Dovolil bych si ještě jednu osobní radu na závěr: Okamžitě po projektu je potřeba tým rozdělit tak, aby se už nikdy nesešel.

Nedostatky JPA

Nenechte se zmást názvem, myslím si, že JPA je dobrý a užitečný standard. Nicméně je nutné mít na mysli, že je to jenom standard, tudíž s sebou nese všechny klady i nedostatky, které jsou se standardy obvykle spojeny.

JPA vznikalo v situaci, kdy bylo na trhu několik dodavatelů O/R mapovacích nástrojů. Mnozí z nich se i na jeho vývoji podíleli. Nemůže nás proto překvapovat, že JPA pokrývá jenom podmnožinu průniku funkčností, které existující nástroje umožňovaly. To co uměl například Hiberante oproti Toplinku se do standardu prostě dostat nemohlo. Platí to samozřejmě i naopak. V tomto článku, bych chtěl shrnout pár věcí, které mi v JPA chybí.

Vlastní typy (UserTypes , Custom types)

JPA umožňuje ukládat jenom následující typy:

Java primitive types; java.lang.String; other Java serializable types (including wrappers of the primitive types, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, user-defined serializable types, byte[], Byte[], char[], and Character[]); enums; entity types and/or collections of entity types; and embeddable classes

Na první pohled by se mohlo stát, že to stačí. Nicméně co dělat, když máme například položku typu java.net.URL a chceme ji uložit jako String? Pomocí JPA se vám ji podaří uložit jedině v serializované podobě. Zajímavou diskuzi k tomuto tématu najdete na TSS.


Criteria API

Criteria API je funkčnost Hibernate, které se hodí, když skládáme databázový dotaz za běhu. Například, pokud máme formulář pro uživatelsky definovaný filtr. Bez criteria API musíme skládat dotaz do řetězce jen proto, aby si ho mohl JPA provider vzápětí naparsovat a složit z něj SQL řetězec. To se mi zdá trochu postavené na hlavu.


Jednosměrné one-to-many vztahy bez join tabulky

Více na jednom z předchozích příspěvků. Například Toplink Essentials tyto vazby opravdu nepodporuje.

Zabíjení sirotečků (delete-orphan)

Umožňuje nám automaticky mazat prvky, které jsme odebrali z one-to-many asociace. Mám-li například třídu klient, která obsahuje kolekci adres, delete orphan mi zajistí automatické smazání adresy poté, co ji odeberu z kolekce. Jelikož JPA tuto funkcionalitu nepodporuji, je nutné adresy mazat ručně, což v některých situacích může být dost komplikované. Více se můžete dočíst v dokumentaci k Hibernate.


Nastavení pro ladění výkonu

Například BatchSize a další. Ladění výkonu je věc, na kterou obvykle v aplikacích typu HalloWord nenarazíte. Pokud ovšem budete psát reálnou aplikaci, bez těchto funkcionalit se neobejdete. A JPA vám kromě možnosti psaní si vlastního SQL mnoho pomoci nenabídne.

Další věci, které nejsou pokryty standardem, ale například Hibernate je umožňuje, můžeme najít na v dokumentaci k Hibernate Extensions.

A co nám z toho plyne? JPA udělalo velikou práci v tom, že sjednotilo metadata pro O/R mapování. Pokud vám nevadí psaní metadat v anotacích, určitě je dobré tento standard používat. Zajistíte si tím snazší přenositelnost na jiného JPA providera. Je ale nepravděpodobné, že se vám podaří napsat a provozovat aplikaci čistě v JPA, aniž by byla závislá na konkrétní implementaci. Pokud se tedy vzdáme iluze o snadné přenositelnosti, je podle mého názoru nejrozumnější používat JPA jenom na definici metadat. Pro DAO vrstvu bych už používal implementaci, na kterou už jsme tak jako tak vázáni. Tzn. v případě Hibernate by to byl Springovský HibernateTemplate, který mi umožní používat HQL a Criteria API.

A to je právě to krásné na JPA, nenutí mě brát všechno nebo nic. Dává mi svobodu vybrat si jak moc ho chci používat. Mohu si vybrat jestli ho chci „degradovat“ jen na formu zápisu metadat nebo jestli mi jeho omezení stojí za tu iluzi snadné přenositelnosti.