I'd like to solve very specific problem with loading resources in Informix stored procedures written in Java. I have IFX v12 and IBM Java 1.7, when I wanted to load any resource from classpath (i.e. some property file) I've got IOException with message "Resource not found".
At first I thought it'll be problem with Java policies, but when I allowed all permission nothing was changed.
Next when I was able to debug stored procedure remotely I've observed, that stored procedure uses informix specific classloader informix.jvp.dbapplet.impl.JVPClassLoader. In debug I found out, this classloader doesn't have JAR loaded in database on its classpath and thus resources from this JAR wasn't available. I wasn't able to debug it well because I didn't have available source code for this classloader.
I have two workaround solutions, but both are ugly. I can put the JAR in classpath for Java process started for Informix but everytime I'd like to make any change in JAR I have to restart this process. Second solution is to load this resource from file system, but this complicates deployment process and make it not failure resistant (and of course envirnoment specific).
Thanks for any suggestion, how to make my JAR resources available on classpath!
Ok, finally we have got a solution for reading property file from JAR loaded in Informix database. There is no way how to access property file in JAR through the JVPClassLoader (and using system classloader isn't flexible enough, see workaround solution in post above). The only way is reading JAR file from Informix system table retained_jars and read the property file from JAR file directly. Let's look on this piece of Java code:
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 ...)
}
Hope this help to anybody else!