sobota 13. ledna 2007

Syndrom vyhořelého vývojáře

Vyhořený vývojář je takový typ pracovníka, který dokáže zastat svoji práci a jeho nadřízení jsou s ním v rámci možností spokojení. To že je někdo takzvaně vyhořený vývojář, ještě neznamená, že nedokáže svou práci zastat. Ba naopak, v mnoha případech je takový vývojář dokonce považován za vzor, protože svojí práci dělá svědomitě a bez remcání. Problém vyhořeného vývojáře, který většinou jeho nadřízení nedokáží odhalit, spočívá v nulovém vývojovém přínosu. Vývojový přínos představuje kvalitativní posun stávajícího stavu.

Za syndrom vyhoření u daného vývojáře mohou především nadřízení. Samozřejmě důležitou roli hraje i dispozice daného vývojáře, ale prvotní příčinou jsou nadřízení. Ti totiž většinou nedokáží vývojáře dostatečně stimulovat, aby jak se říká, neusnul na vavřínech. Pokud chcete nechat své vývojáře nechat vyhořet, postupujte následujícím způsobem.

  • nechte je pracovat s pocitem bastlení
  • v každém případě se jich neptejte co by chtěli dělat
  • za každých okolností jim zakažte cokoliv, co přímo nesouvisí s jejich prací
  • braňte jakékoliv odchýlení od stávajících pořádků
  • jakoukoliv iniciativu zamítněte s odůvodněním nedostatku času
  • nemotivujte je k inovaci, protože to stojí čas

Pokud jste si předchozí seznam obrátili do správné polohy, tak jste možná rozčarováni jeho v uvozovkách anarchistickým vyzněním. Jenže to co se někomu zdá jako anarchie, je pro jiného svobodné prostředí, které je podle mého, ideální pro realizaci vlastních myšlenek a nápadů. Na druhou stranu, ono svobodné prostředí může jednomu sice poskytovat obrovský potenciál, ale druhému může poskytovat ideální možnost splynout s davem.

Jedním ze stimulu, proto aby vám vývojář nevyhořel je poskytnout mu dostatečný prostor pro vlastní realizaci. Právě možnost oné realizace závisí na svobodě prostředí, ve kterém pracuje. Příkladem svobodného prostředí je možnost nechat své zaměstnance pracovat pětinu pracovní doby na tom, co je zajímá uvnitř firmy, tak jak to dělá například Google.

Dalším stimulem je nechat část pracovní doby na sebevzdělávání a studium a hlavně umožnit nabité vědomosti aplikovat ve vývojovém procesu. Toto sice deklaruje kdejaký zaměstnavatel, ale realita je často odlišná. Nejčastější důvodem bývá nedostatek času, což je mnohdy pouze výmluva ze strachu adoptovat nové myšlenky.

Velice dobré je projevit důvěru vývojářům v tom, že si mohou vybrat (pokud je to možné), co by chtěli v rámci stávajících úkolů dělat. Díky tomu vývojáři nevyhoří, protože májí pocit seberealizace v tom co dělají a dokáží přinášet nové inovace.

Nikdy jsem nepracoval v žádné manažerské pozici, proto je tento pohled možná zkreslený, asi jako pohled blátošlapa (pěšáka) na válku, ale tak to prostě vídím. Musím s povděkem kvitovat, že zatím jsem měl štěstí na nadřízené, kteří mě nenechali vyhořet.

čtvrtek 11. ledna 2007

Podcast volume#4 žádní falešní sobi

Nový rok se rozbíhá a s ním i další podcast s hlavním tématem Spring a J2EE. Mimo hlavní téma se v tomto podcastu dozvíte i plno dalších informací například o Roumenově návštěvě JavaPolis.

středa 10. ledna 2007

Chudokrevné a plnokrevné IoC, EJB vs. Spring

Inversion of Control (IoC) je návrhový vzor, který přesouvá nutnost získání a inicializace závislostí (objektů) mimo rozsah objektu, který je využívá. Vlastní závislost je nastavena z vnějšku (Dependency Injection).

Mějme objekt A, který ke své práci používá objekt B (A má závislost na B). Objekt A má uvnitř kód, který vytváří a inicializuje objekt B. Kód pro vytvoření a inicializaci objektu B úzce svazuje oba objekty dohromady, navíc je to kód specifický danému prostředí, například JNDI lookup.

V případě IoC je "vázající" kód vytažen ven z objektu. Někdo třetí se stará o to, aby se do objektu A dostala v pravou chvíli zinicializovaná instance objektu B. Objekt B je do objektu A nastaven například settrem nebo přes konstruktor, této formě IoC se říká Dependency Injection (injekce závislosti).

Možná víte, možná ne, Dependency Injection (DI) je jedním z klíčových vlastností implementovaných v J2EE 5.0. Masivní rozšíření konceptu IoC resp. DI jako jeho způsoby popularizoval Spring framework a DI se brzo stal jednou z metel tradičního J2EE světa. Právě verze J2EE 5.0 a zavedeni DI se stalo v mnoha případech pro mnoho vývojářů důvodem zatracení Springu.

Pokud pominu samotný fakt, že Spring nabízí mnohem více než DI, samotná úroveň možností DI je silně rozdílná mezi Springem a EJB kontejnerem. Zrekapitulujme fakta.

EJB DI

  • definice závislosti - anotace, XML descriptor
  • aplikovatelnost - Servlet, listener classes, web services end-point, JAX-RPC handlers, DataSource, JMS, Mail, EJB, Environment entries, EntityManager, UserTransaction, EJB Beans, interceptors, web services end-point, DataSource, JMS, Mail, Environment entries, EntityManager, EJB Context, UserTransaction, TimerService
  • nepřímé závislosti - ne
  • způsob nastavení závislosti - setter, anotace proměnné
  • extension pointy - interceptory, lifecycle rozhrani
  • autowiring - ne

Spring DI

  • definice závislosti - XML descriptor, anotace, properties, konfigurační java kód
  • aplikovatelnost - bez omezení cokoliv
  • nepřímé závislosti - ano
  • způsob nastavení závislosti - setter, anotace proměnné, konstruktor
  • extension pointy - AOP, BeanPostProcessor, Factory, lifecycle rozhrani, typová konverze
  • autowiring - typem, jménem

Definice závislosti a aplikovatelnost

EJB v podstatě nabízí pouze anotace a jejich překrytí v XML descriptoru, případně jejich kombinaci. Oproti tomu Spring, krom vyjmenovaných způsobů a jejich kombinací, nelimituje v používání vlastních řešení pro popis závislostí. Právě tak vzniklo rozšíření v podobě anotací, které jsou sémanticky ekvivalentní možnostem DI anotacím.

Jestliže ve světě J2EE je možnost používání anotací limitována pouze na předem specifikovanou skupinu komponent, v Springu žádné takové omezení není. To je problematické především pro třídy, které nejsou ze své povahy managovatelné komponenty např. helpery, kolekce (mapy, seznamy) a nebo třídy mimo mimo EJB kontejner např. ve web vrstvě. Naopak ve Springu žádné takové omezení není.

Vyjadřovací schopnost standardního XML deskriptoru, oproti Spring descriptoru, je silně omezena. Například není možno definovat kolekce. To je problém pokud má objekt například jako dependency seznam určitých objektů. Spring od verze 2.0 navíc umožňuje definovat vlastní tagy, které mohou popisovat dané beany. Popisnost XML deskriptoru ma pro vývojáže řádově vyšší hodnotu.

Způsob nastavení závislosti

Dalším rozdílem je způsob nastavení závislosti, EJB kontejner nabízí setter nebo proměnnou (přes anotací). Spring nabízí krom obou navíc ještě konstruktor. Objekt může příjmat závislost i kontruktorem, pokud je na to jeho API uzpůsobeno. Velice užitečnou vlastností je podpora nepřímé závislosti (má pouze Spring). Pokud máme objekty, které spolu nesouvisí na úrovni kódu a přesto chceme zaručit, například pořadí inicializace, potřebujeme nepřímou závislost. Ta zaručí, že objekt X bude zinicializován před objektem B.

Extension pointy

Extension pointy nebo česky body rozšíření definují možnost rozšíření chování IoC. EJB kontejner nabízí krom lifecycle rozhraní ještě interceptory pro managed komponenty. Stejnou podporu má i Spring s tím rozdílem, že interceptory jsou nahrazeny aspekty. Spring navíc nabízí BeanPostProcessor, který umožňuje customizovat inicializované beany. Velkým plusem je možnost využití Factory objektů, kdy Spring IoC kontejner může vytváření některých objektů delegovat na specifickou klientskou factory.

Typová konverze je způsob převodu hodnot zapsaných v XML descriptoru na reálné objekty. Pokud například zapíšeme v XML descriptoru hodnotu 1.1.1970 a typem parametru settru je objekt foo.MyDateWrapper, pak Spring nabízí možnost definice PropertyEditoru, na který se kontejner obrátí v případě, že narazí na daný typ. Podporuje opět jenom Spring.

Autowiring

Autowiring je nastavení přímých závislostí bez jejich explicitního vyjmenování. Pokud je objekt A a objekt B řízený IoC kontejnerem, pak kontejner může automatický detekovat, závislost objektu A na B podle typu (A ma setter na objekt B) nebo podle jména (A má setter property, která jménem odpovídá jménu objektu B). Možnost autowiringu komponent podporuje pouze Spring.

To jsou jenom ty nejmarkantnější rozdíly, které mě napadly při srovnání Spring IoC kontejneru a EJB kontejneru. Určitě by se jich dalo najít více, ale cílem tohoto článku bylo upozornit na to, že není IoC jako IoC. I když Java 5 ušla velký kus cesty a díky IoC nabídla větší komfort, stále má Spring své silné stránky. Core součást IoC, na které je postavený celý Spring a potažmo všechny aplikace nad Springem postavené, je jednou z nich.

neděle 7. ledna 2007

Základy deploymentu webových aplikací na Tomcatu

V tomto článku se pokusím shrnout základy deploymentu (nasazení) webových aplikací na server Tomcat. Tomcat jsem vybral pro jeho rozšířenost, nicméně mnoho informací zde uvedených je znovupoužitelných i na jiných serverech. Rád bych upozornil, že článek se nezaobírá instalací Tomcatu a taktéž předpokládá alespoň elementární znalost servletů a JSP.

Formát webové aplikace (WARu)

Webová aplikace musí dodržovat určitou adresářovou strukturu, tak aby ji byl schopen server obsloužit. Této struktuře se říká WAR (Web Application Archive) a my se teď na ni v rychlosti podíváme.


adresář aplikace
   |  
   |--- WEB-INF
   |       |
   |       |--- classes
   |       |--- lib
   |       |
   |       web.xml
   |--- veřejné soubory (html, css, jsp, js...)     
    

Nejdůležitější částí je adresář WEB-INF (pozor vždy velká písmena), protože podle něj může server poznat, že se jedná o webovou aplikaci. Další klíčovou částí je soubor web.xml, kde je základní konfigurace webové aplikace jako mapování servletů na patřičná URL. V adresáři classes a lib leží třídy a knihovny, které aplikace používá. V kořenu adresáře aplikace leží veřejně přístupné soubory přes URL aplikace jako jsou JSP a nebo HTML stránky.

Adresář s výše popsanou strukturou lze považovat z hlediska struktury za webovou aplikaci, které bude rozumět jakýkoliv server (raději používám název servletový kontejner. Takto připravenému adresáři budeme dále říkat WAR. WAR lze nechat v takto otevřené struktuře a nebo jej můžeme zkomprimovat (zabalit) ZIPem.

WAR lze tedy mít ve dvouch formách

  • nezabalený WAR se nazývá exploded WAR
  • zabalený WAR

Poznámka na okraj: aplikační server WebSphere neumožňuje deploy exploded WARu. Jinak jsem se nesetkal, že by některý server nedokázal obě dvě varianty.

Deploy WARu

Deploy nebo nasazení WARu lze udělat několika způsoby.

  • nakopírováním WARu do deploy adresáře serveru
  • použitím webového GUI serveru pro deploy
  • použitím specifických nástrojů serveru např. Ant
  • úpravou deploy konfigurace serveru
Nakopírování WARu

V rámci Tomcatu stačí nakopírovat WAR do adresáře TOMCAT_HOME\webapps. Tím je zaručenou, že jej Tomcat nahraje. V případě zabaleného WARu je potřeba, aby měl archív příponu war například test.war. Pokud neobsahuje WAR specifický descriptor, který má samozřejmě každý server jiný, je kontext (část URL) aplikace určen jménem WARu. Ať již nakopírujeme rozbalený WAR např. test a nebo zabalený WAR test.war, bude kontext test a URL http://localhost:8080/test.

Použitím webového GUI

V Tomcatu není webové rozhraní pro deploy aplikace defaultně přístupné resp. žádný z uživatelů nemá patřičnou roli manager. K tomu, aby jí měl je potřeba upravit soubor TOMCAT_HOME\conf\tomcat-users.xml. Jednomu z uživatelů např. tomcat přidáme roli manager tedy <user username="tomcat" password="tomcat" roles="tomcat,manager"/>. Pak stačí zadat URL http://localhost:8080/manager/html a nebo použít odkaz Tomcat manager z hlavní stránky Tomcatu.

V sekci Deploy můžeme WAR deploynout dvěma způsoby, jako zabalený (WAR file to deploy) a nebo jako rozbaleny, či rozbalený se specifikací kontextu a konfigurace (Deploy directory or WAR file located on server).

Použitím Antu

Tomcat nabízí sadu antích tásků, pomocí kterých lze zabezpečit management celé aplikace. Jediná podmínka je, že opět musí existovat uživatel s rolí manager, jak bylo popsáno výše. Stačí si stáhnout předpřipravený ant soubor a upravit si hodnoty následujících properties.

  • <property name="name" value="test" /> - jméno kontextu aplikace
  • <property name="tomcat.home" value="c:\tools\tomcat-5.5.20" /> - domovský adresář Tomcatu
  • <property name="war.path" value="c:\temp\deployment\${name}.war" - cesta k WARu/>

Použitelné targety

  • deploy - deploy WARu (zvládá pouze zabalený WAR)
  • undeploy - deploy WARu
  • reload - reload WARu
  • list - vypíše seznam nainstalovaných aplikací
  • stop - vypne přijímání HTTP požadavků dané aplikace
  • start - zapne přijímání HTTP požadavků dané aplikace
  • serverinfo - vypíše informace o serveru
  • sessions - vypíše informace o sessions dané aplikace
Úpravou konfiguračních skriptů serveru

Další možnost deploynutí WARu představuje úprava konfiguračních skriptů serveru. V případě Tomcatu je to vytvoření XML souboru s definicí kontextu a jeho nakopírováni do TOMCAT_HOME\conf\[enginename]\[hostname] což je většinou TOMCAT_HOME\conf\Catalina\localhost\.

Příklad obsahu takového souboru je následující.

<Context docBase="c:\temp\deployment\test.war"
    path="test"
    privileged="true" 
    antiResourceLocking="false" 
    antiJARLocking="false"  
    reloadable="true">
</Context>    
    

Atribut docBase ukazuje buďto absolutně nebo relativně na WAR (může být jak rozbalený tak zabalený). Atribut reloadable říká jestli se při změně ve /WEB-INF/classes/ a /WEB-INF/lib provede reload aplikace (osobně mi to zafungovalo pouze při změně v lib adresáři). Atribut path určuje kontext aplikace.

Reload aplikace

Mezi nejčastější dotazy při vývoji patří otázka Jak reloadnout aplikaci bez restartu Tomcatu. Nuže způsobů je několik v závislosti na tom co se změnilo.

  • změna veřejných souborů jako JSP stránek nebo HTML souborů nevyžaduje restart. Soubory stačí zkopírovat do WARu a server se postará o zbytek.
  • změna souboru web.xml způsobí automatické znovunačtení celé webové aplikace
  • změna tříd případně knihoven nezpůsobí nic, pokud se neprovede znovunačtení webové aplikace. To můžeme udělat několika způsoby.
    • použijeme výše uvedený ant soubor a target reload
    • zavoláme URL http://localhost:8080/manager/reload?path=/context aplikace např. http://localhost:8080/manager/reload?path=/test (opět musíme mít uživatele s rolí manager viz výše)
    • pokud je WAR zabalený, způsobí nakopírování nové verze do deploy adresáře serveru reload celé aplikace
    • použít kontext definici, která zajistí reload aplikace při změně WEB-INF/classes a WEB-INF/lib (osobně mi to zafungovalo pouze při změně v lib adresáři). Kontext nadefinujeme následujícím způsobem. Ve WARu vytvoříme adresář META-INF a v něm soubor context.xml, do kterého dáme následující element <Context docBase="test" privileged="true" reloadable="true" /> (hodnotu atributu docBase si změnte na kontext aplikace).

Dalším doplňkovým způsobem vhodným pro drobné změny ve třídách je využití HotSwap vlastnosti JVM. Když je Tomcat nebo jakákoliv jiná aplikace puštěna v debug módu, může agent (většinou vývojové prostředí) dělat změny nahraného bajt kódu. Díky této vlastnosti se dají měnit střeva metod, pokud nezasahují do definice třídy např. změna rozhraní apod.

Užitečné odkazy