Sun Multi-Schema XML Validator a kompilace schématu
V projektu, na kterém právě pracuji, potřebujeme validátor XML schémat, který
bude sloužit k validaci XML dat na vstupu aplikačního serveru. Řekl jsem si
no problem a šel jsem na to. Samozřejmě jsem netušil, že příští
den a půl strávím hledáním hloupé chyby.
Moje pouť začala u Sun Multi-Schema XML Validator,
který implementuje obecné programové rozhraní JARV určené
pro validátory. Diky tomuto rozhraní je možné programově pracovat s validátorem. Více
na JARV User’s Guide.
JARV mi nabídl ideální možnost, jak uschovat validátor do komponenty, kterou bude
využívat aplikační vrstva. Těch několik schémat, která budeme používat, máme uloženy
v rámci aplikačního serveru a proto jsem zvolil jejich kompilaci v init metodě
validační komponenty.
Kompilace schématu je proces kdy se schéma převádí na objektovou podobu. V chytré příručce
je ukázka Schema schema = factory.compileSchema("http://www.example.org/test.xsd");
Převedeno do kontextu aplikačního serveru, schéma mám jako resource(*.xsd soubory) webové aplikace.
Předběžná kontrola API objektu VerifierFactory
a metody compileSchema, vybírám compileSchema(java.io.InputStream stream).
Výše uvedené dalo vzniknout následujícímu kódu (pouze to nejdůležitější)
factory = VerifierFactory.newInstance("http://www.w3.org/2001/XMLSchema");
.
.
InputStream is = context.getResource("foo.xsd").getInputStream();
Schema schema = factory.compileSchema(is);Připravuji testovací objekt, který má validační komponentu vyzkoušet.
Pouštím test a ejhle inicializační metoda, kde je výše uvedený kód,
vylítne na výjimku. Letmý pohled na stack trace, kde je text, který se mi
na den a půl vryje do paměti
com.sun.msv.verifier.jarv.FactoryImpl$WrapperException: java.lang.NullPointerException (celý stack trace)
Po dni prošpikovaném debuggováním, hledáním alespoň nějaké stopy via. Google
a zkoušením všeho možného a nemožného docházím k závěru, že to postě nejde
a přemýšlím kde udělali soudruzi z NDR chybu. Procházím ještě jednou
příklady a říkám si, safra nějak to přece musí jít a zkouším po vzoru několika
příkladů podstrkovat místo InputStream přímo File compileSchema(java.io.File f) a
WOW ono to funguje!
To není možné, přece nemají chyby v metodě compileSchema(java.io.InputStream stream)
snažím se sám sebe přesvědčit a koukám ještě do API objektu VerifierFactory a vidím něco čeho jsem si nevšiml,
dvě metody s InputStreamem, compileSchema(java.io.InputStream stream) a
compileSchema(java.io.InputStream stream, java.lang.String systemId).
Ta druhá má jako argument systemId (systémová identifikátor schématu např. foo.xsd), hloubám v paměti na co to padalo… ic.systemId.equals(url) v objektu com.sun.msv.reader.GrammarReader metoda
switchSource( InputSource source, State newState ).
Teď už mi to dochází, ic je InclusionContext privátní třída v com.sun.msv.reader.GrammarReader, to jsem již
vyzkoumal při pročítání kódu GrammarReader. Sepnuto, systemId na ic bylo null (to jsem již věděl) a ten důvod byl
prostý.
InclusionContext (jak jsem vyzkoumal) vzniká skrze compileSchema a protože některá schémata mají
externí entity např. import typů vznikne i odpovídající InclusionContext pro tyto entity. Chudák validátor se pak snaží
InclusionContext identifikovat podle jejich systemId viz. ic.systemId.equals(url) a protože jsem použil
compileSchema(java.io.InputStream stream) bez systemId s odkazem na externí entitu, tak to skončilo tím
NullPointerem. Pokud bych měl zrovna štěstí a předhodil soubor bez externích entit, tak by vše proběhlo v pořádku neboť
by vznikl pouze jeden InclusionContext.
Stačila málá úprava kódu a vše běželo podle očekávání
factory = VerifierFactory.newInstance("http://www.w3.org/2001/XMLSchema");
.
.
InputStream is = context.getResource("foo.xsd").getInputStream();
Schema schema = factory.compileSchema(is,"foo.xsd");Z výše uvedeného plyne, hned několik ponaučení a chyb. Za prvé, dokumentace (JavaDoc) k rozhraní JARV
je nedostatečná. V JavaDocu neni o něčem takovém ani zmínka, všechny metody compileSchema
mají stejný dokumentační komentář, nelze tedy určit která by se měla v tom či onom případě
použít.
Opět se mi potvrdilo, že ti co hlásají, že dostupnost zdroj. kódu je k ničemu, nemají pravdu. Bez
zdrojáků bych byl, nejen v tomhle případě, ztracen nebo v lepší variantě zasekán několik dalších
hodin.
Související články
Související epizody CZ Podcastu
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi a Filemon o novinkách v Javě 6 a webových frameworcích.
- #1 · Vývojová prostředí v Javě
První díl CZ Podcastu se věnuje vývojovým prostředím pro Javu.