如何使用 informix.jvp.dbapplet.impl.JVPClassLoader 从类路径加载资源?
How to load resource from classpath with informix.jvp.dbapplet.impl.JVPClassLoader?
我想解决在用 Java 编写的 Informix 存储过程中加载资源的非常具体的问题。我有 IFX v12 和 IBM Java 1.7,当我想从类路径(即一些 属性 文件)加载任何资源时,我得到了带有消息 "Resource not found".
的 IOException
一开始我以为 Java 策略会有问题,但当我允许所有权限时,什么都没有改变。
接下来,当我能够远程调试存储过程时,我观察到该存储过程使用了 informix 特定的类加载器 informix.jvp.dbapplet.impl.JVPClassLoader。在调试中我发现,这个类加载器没有在其类路径上的数据库中加载 JAR,因此来自这个 JAR 的资源不可用。我无法很好地调试它,因为我没有这个类加载器的可用源代码。
我有两个解决方案,但都很丑陋。我可以将 JAR 放在为 Informix 启动的 Java 进程的类路径中,但每次我想在 JAR 中进行任何更改时,我都必须重新启动该进程。第二种解决方案是从文件系统加载此资源,但这会使部署过程复杂化并使其无法抗故障(当然还有特定于环境的)。
感谢任何关于如何使我的 JAR 资源在类路径上可用的建议!
好的,我们终于找到了从 Informix 数据库中加载的 JAR 读取 属性 文件的解决方案。无法通过 JVPClassLoader 访问 JAR 中的 属性 文件(并且使用系统类加载器不够灵活,请参见上面 post 中的变通解决方案)。唯一的方法是从 Informix 系统 table retained_jars 读取 JAR 文件并直接从 JAR 文件读取 属性 文件。让我们看一下这段 Java 代码:
public Properties loadPropertiesFromInformixRetainedJarsTable(final String propertyFileName) {
final Connection conn = ...;
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt.executeQuery("SELECT jarname, jardata FROM retained_jars");
if (rs.next()) {
final JarInputStream jar = new JarInputStream(rs.getBinaryStream("jardata"));
JarEntry jarEntry;
while ((jarEntry = jar.getNextJarEntry()) != null) {
if (jarEntry.getName().equals(propertyFileName)) {
// read JAR entry content
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final byte[] buf = new byte[2048];
int readCnt;
// reading from JarInputStream reads from current JarEntry
while ((readCnt = jar.read(buf, 0, 2048)) != -1) {
baos.write(buf, 0, readCnt);
}
final Properties properties = new Properties();
// load properties from byte array through StringReader
properties.load(new StringReader(new String(baos.toByteArray())));
return properties;
}
}
}
// here should be of course some usual cleaning of resources (like connection, input stream ...)
}
希望这对其他人有帮助!
我想解决在用 Java 编写的 Informix 存储过程中加载资源的非常具体的问题。我有 IFX v12 和 IBM Java 1.7,当我想从类路径(即一些 属性 文件)加载任何资源时,我得到了带有消息 "Resource not found".
的 IOException一开始我以为 Java 策略会有问题,但当我允许所有权限时,什么都没有改变。
接下来,当我能够远程调试存储过程时,我观察到该存储过程使用了 informix 特定的类加载器 informix.jvp.dbapplet.impl.JVPClassLoader。在调试中我发现,这个类加载器没有在其类路径上的数据库中加载 JAR,因此来自这个 JAR 的资源不可用。我无法很好地调试它,因为我没有这个类加载器的可用源代码。
我有两个解决方案,但都很丑陋。我可以将 JAR 放在为 Informix 启动的 Java 进程的类路径中,但每次我想在 JAR 中进行任何更改时,我都必须重新启动该进程。第二种解决方案是从文件系统加载此资源,但这会使部署过程复杂化并使其无法抗故障(当然还有特定于环境的)。
感谢任何关于如何使我的 JAR 资源在类路径上可用的建议!
好的,我们终于找到了从 Informix 数据库中加载的 JAR 读取 属性 文件的解决方案。无法通过 JVPClassLoader 访问 JAR 中的 属性 文件(并且使用系统类加载器不够灵活,请参见上面 post 中的变通解决方案)。唯一的方法是从 Informix 系统 table retained_jars 读取 JAR 文件并直接从 JAR 文件读取 属性 文件。让我们看一下这段 Java 代码:
public Properties loadPropertiesFromInformixRetainedJarsTable(final String propertyFileName) {
final Connection conn = ...;
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt.executeQuery("SELECT jarname, jardata FROM retained_jars");
if (rs.next()) {
final JarInputStream jar = new JarInputStream(rs.getBinaryStream("jardata"));
JarEntry jarEntry;
while ((jarEntry = jar.getNextJarEntry()) != null) {
if (jarEntry.getName().equals(propertyFileName)) {
// read JAR entry content
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final byte[] buf = new byte[2048];
int readCnt;
// reading from JarInputStream reads from current JarEntry
while ((readCnt = jar.read(buf, 0, 2048)) != -1) {
baos.write(buf, 0, readCnt);
}
final Properties properties = new Properties();
// load properties from byte array through StringReader
properties.load(new StringReader(new String(baos.toByteArray())));
return properties;
}
}
}
// here should be of course some usual cleaning of resources (like connection, input stream ...)
}
希望这对其他人有帮助!