Category Archives: Spring

Resin a Spring autowiring

Nedávno jsem psal o autowiringu ve Springu. V diskuzi Karlos napsal, že mu autowiring nefunguje v Resinu. Měl pravdu, o čemž jsem se přesvědčil o pár dní později, když jsem chtěl aplikaci nasadit právě na Resinu. Chvíli jsem si lámal hlavu s tím čím by to mohlo být, ale věc jsme nakonec vyřešili tím, že jsme se autowiringu vzdali. Dnes jsem si našel chvilku a strávil jsem ji debugováním Springu, abych zjistil kde je chyba. Než vám prozradím řešení, zkuste se zamyslet čím to bylo. Autowiring normálně funguje v Tomcatu, Jetty, ale v Resinu ne. Čím by to tak mohlo být? Tak co už to máte? Musím se přiznat, že bez debuggeru bych na to nepřišel, napadaly mě všelijaké teorie, od nefunkční reflexe po specifické nastavení security.

Odpověď je, ale evidentní. Jde o špatný XML parser. Resin standardně používá svůj XML parser, který ignoruje default hodnoty u atributů. Takže, když ve Spring XML konfiguračním souboru nevyplníme atribut, Resin vrací jako jeho hodnotu prázdný řetězec místo default hodnoty dané XSD. Spring se tedy konfiguroval podle jiných hodnot, než jsme chtěli. Náprava je snadná, stačí používat standardní XML parser. Jak na to se dočtete zde. Pokud vám toto řešení nevyhovuje, musíte u všech beanů nadefinovat autowire atribut, tak aby nemusela být použita implicitní hodnota.

Na závěr mi nezbude nic jiného než si povzdychnout nad svojí nepoučitelností. Poté co jsem před pár lety bojoval se špatnou implementací XML parseru od Oraclu, mě mohlo napadnout, že u Caucho také podlehnou nutkání napsat si vlastní parser. Bohužel rovněž za cenu odchylek od standardu.

EJB 3 – injektujeme SFSB

(aneb vstřikujeme zrnka sezení plná stavu)

Konečně jsem našel odpověď na otázku, která už mi dlouho ležela v hlavě. Přivedl mě na ni kolega, který na jednom firemním setkání Javistů někdy před rokem nadnesl otázku „Co se stane, když injektnu stateful session bean do servletu?“

Zajímavé co? Stejná otázka se samozřejmě nabízí i u stateless beanů. Co se stane, když něco co drží stav injektnu (vnesu??) do objektu, který je bezstavový.



@Statefull
public class Cart {
 ...
}

@Stateless
public class Shop
{
  @EJB private Cart cart;
  ...
}

Tak co, víte co se stane? Já už ano. Odpověď mi poskytla docela pěkná kniha EJB 3 in Action. Na straně 136 se dočteme:

Mějte na paměti, že nesmíte injektovat stateful session bean do bezstavového objektu, jako je stateless session bean nebo servlet, který může být sdílen více souběžně přistupujícími klienty (v takovýchto případech používejte JNDI)

Hurá, otázka zodpovězena. Jak tento problém řeší Spring? Ten sice nemá žádný ekvivalent SFSB, ale od verze 2 má tzv. scopy (rozsahy) beanů. Je tedy možné, injektnout bean, který se váže na HTTP session uživatele, do beanu, který je sdílen mezi všemi uživateli? Co se stane v tomto případě? Nenastane stejný problém jako u EJB? To je to ale napínavé co?

Nenastane! Springu totiž můžete říci, aby neinjektoval původní bean, ale proxy. Ta ohlídá aby každý uživatel (session) dostal svoji verzi i v kódu, který o scopu a stavech vůbec nic netuší. Tato proxy se také stará o vytvoření beanu, pokud je to potřeba. Více podrobností naleznete v dokumentaci Springu.

Spring drobnůstky

Dnes bych chtěl psát o pár ze svých oblíbených Spring vychytávek. Jsou to drobnosti, bez kterých bychom se obešli, ale člověku trochu ušetří práci. Předem upozorňuji, že všechny mají jednu malou vadu na kráse. Tím, že je použijete, stanete se (i váš kód) závislými na Springu.

org.springframework.util.FileCopyUtils

V poslední době často používám FileCopyUtils. To je třída, jejíž hlavním přínosem je snadné kopírování dat z InputStreamu do OutputStreamu. Dále nám umožní snadno kopírovat Reader do Stringu a jiné podobné taškařice. Jeden příklad za všechny:

byte[] data = FileCopyUtils.copyToByteArray(new File("test.txt"));

org.springframework.util.Assert

Další užitečnou drobnůstkou je třída Assert. Ta nám umožní psát něco takového



  public void doSomething(String param)
  {
    Assert.hasText(param, "Param has to be filled.");
    ...
  }

Když v paramtru param bude null, nebo samé mezery, dostaneme IllegalArgumentException. Samozřejmě bychom něco podobného dokázali i dobře mířeným ifem. Uvedený zápis má tu výhodu, že je přehlednější a navíc je jasné, že nejde o součást business logiky, že to je jenom kontrola předpokladů. Pozor v tomto případě není vhodné použít klíčové slovo assert, o důvodech se dočtete zde. Více se o programování kontraktem můžete dočíst zde.

org.springframework.web.filter.CharacterEncodingFilter

Poslední užitečnou drobnůstkou, o které chci dnes psát je CharacterEncodingFilter. Tato třída se používá, když vám ze „záhadných důvodů“ nefunguje čeština ve formulářích na webu. To bývá způsobeno tím, že některé prohlížeče zapomínají poslat informaci, jakým kódováním znakové sady je zakódován HTTP request. Tento filtr umí v takovém případě u requestu nastavit implicitní hodnotu kódování. Podobný filtr najdete například i v Tomcatu, nicméně když už používáme Spring, není důvod přidávat další knihovnu.