SunのRIをシステムクラスローダー以外から読み込む
(http://d.hatena.ne.jp/muimy/20040320#p7 のつづき)
SunのRowSet実装(RI)はシステムクラスパスに通して使う分はいいですが、
サーブレットコンテナやEclipseプラグインなどから使うと、
CachedRowSetImplなどのnew時にNullPointerExceptionになります。
(あ、サーブレットコンテナは試してないけど、たぶん)
ヌルポの元のSyncFactory#initMapIfNecessary を
見ると次のような処理を行っているようです。
String s = System.getProperty("rowset.properties"); if(s != null) { ROWSET_PROPERTIES = s; properties.load(new FileInputStream(ROWSET_PROPERTIES)); parseProperties(properties); } ROWSET_PROPERTIES = "javax" + strFileSep + "sql" + strFileSep + "rowset" + strFileSep + "rowset.properties"; ClassLoader classloader = Thread.currentThread().getContextClassLoader(); properties.load(classloader.getResourceAsStream(ROWSET_PROPERTIES)); parseProperties(properties);
カレントスレッドのクラスローダからrowset.properties読み込んでます。
なので、rowset.jarをクラスパスに持つクラスローダーが、
カレントスレッドのクラスローダーより子にあると、
rowset.propertiesが見つからないことになります。
(普通にSyncFactory.class.getResourceAsStream(...)
してくれればいいかと思うが、、、Tigerに組み込む関係とかあるのかな?)
対処として、次のような感じで使うとエラーなく読み込めるようです。
public static CachedRowSet getCachedRowSet() throws SQLException{ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); ClassLoader newLoader = MyHogeClass.class.getClassLoader(); Thread.currentThread().setContextClassLoader(newLoader); CachedRowSetImpl rowset = new CachedRowSetImpl(); Thread.currentThread().setContextClassLoader(oldLoader); return rowset; }
//CachedRowSet rowset = new CachedRowSetImpl(); CachedRowSet rowset = getCachedRowSet();
やー、これが適切な手段か分からんけどー。
JNDI Explorer for Eclipse で似たような処理をやってたような気がする。