validator vs configuration
バリデーションをするのに、XMLを読み込もうとしたらこんな例外になってしまった。
src*1
InputStream in = loader.getResourceAsStream("hoge_validate.xml"); resourcess = new ValidatorResources(in);
例外の内容(適当に折り返し)
[ERROR] Digester - Digester.getParser: <org.xml.sax.SAXNotRecognizedException: Feature: http://apache.org/xml/features/validation/dynamic>org.xml.sax.SAXNotRecognizedException: Feature: http://apache.org/xml/features/validation/dynamic at org.apache.xerces.jaxp.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:100) at org.apache.commons.digester.parser.XercesParser.configureXerces(XercesParser.java:185) (中略) java.lang.NullPointerException at org.apache.commons.digester.Digester.getXMLReader(Digester.java:891) at org.apache.commons.digester.Digester.parse(Digester.java:1591) at org.apache.commons.validator.ValidatorResources.<init>(ValidatorResources.java:156) at org.apache.commons.validator.ValidatorResources.<init>(ValidatorResources.java:133)
なんのこっちゃという内容なのだが、ここをヒントに(見た名前だと思えばid:koichikさんである)。
http://ml.seasar.org/archives/seasar-user/2005-September/000722.html
Xercesのソースが怪しいということで、辿っていくと・・・
org.apache.commons.digester.ParserFeatureSetterFactory
try{ // Use reflection to avoid a build dependency with Xerces. Class versionClass = Class.forName("org.apache.xerces.impl.Version"); isXercesUsed = true; } catch (Exception ex){ isXercesUsed = false; }
public static SAXParser newSAXParser(Properties properties) throws ParserConfigurationException, SAXException, SAXNotRecognizedException, SAXNotSupportedException { if (isXercesUsed){ return XercesParser.newSAXParser(properties); } else { return GenericParser.newSAXParser(properties); } }
つまり、"org.apache.xerces.impl.Version"がクラスパスにあるとxercesをパーサーにしてしまい、結果必要もないfeatureうんたらがでてくると。
プロジェクトのなかでこやつを利用しているのは、テストで利用しているcommons-configurationのみ。
まぁ切り取ってしまっても問題ないでしょう。
<dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.3</version> <scope>test</scope> <exclusions> <exclusion> <artifactId>xerces</artifactId> <groupId>xerces</groupId> </exclusion> </exclusions> </dependency>
これでOK。
xercesをパーサーにするともう一つ問題があって、どうもcommons-configuration自身もWindows-31Jを扱えない「場合がある」ようなのだ。
でも環境によっては読めてしまうので、ちょっと謎なのだけど。
この辺りはクラスがロードされる順番にもよるので、予防しておいた方がよさそうではある。
cf.http://www.ingrid.org/java/i18n/encoding/shift_jis.html