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
> a) Na co ukazuje reference hello? (Je to home objekt, nějaká proxy, …)
proxy
> b) Musí mít každý klient svoji referenci, nebo je bezpečné ji sdílet?
kazdy vlastni
> c) Je potřeba ji nějak vracet do poolu?
ne
> 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?
zalezi na contextu pouziti, v clusteru se nic nedeje a volani se deleguje na jiny node v pripade single stroje dojde k vyhozeni RemoteException.
1b) Přeformuluji: Můžu ji sdílet mezi requesty, nebo si ji mohu cachovat?
2) ???
> Velcí klienti jako třeba banky mají (nebo spíše měli) nedůvěru k open source řešením.
Pokud se dá věřit prezentacím od Roda Johnsona (tuším), tak zrovna v bankách už se Spring s úspěchem používá.
Kdyz pouzijete Jetty, nebo Tomcat dostanete se jenom k HTTP protokolu, nebo HTTPS. Jenze prave krasa springu je preci v tom, ze muze bezet jak v kontejneru, tak i bez nej.
Takze mam 3 vrstvou aplikaci. Kde servr bezi se springem (a neni v kontejneru) a klient je postaveny na Sping RPC. Tedka pracuju na ajaxovem klientovi, ale server mi dela nadale spring, nesposutim dalsi kontejner.
Respektive asi takhle. knihovny jettyho taham az v ramci sveho projektu, ale nemam definovany zadny web.xml, proste nastaveni je pres springa.
Super je i to, ze spring je super plug-in system. Takze RPC klient je modularni a podle toho ktere moduly zakanik chce, podle toho dostane xml soubory, ktere se natahnou. Tot vse, ukrutne jednoduche a velmi elegantni.