Skip to content


Divertida carga de recursos Java

Nunca he tenido muchas necesidades en relación a la carga de recursos Java (esos archivos que uno agrega en los Jars.) Hace poco tuve algunos requerimientos que me obligaron a revisar el tema.

Java proporciona un soporte relativamente genérico para la obtención de los recursos mediante la asociación de un “URL”. La idea aparentemente es que los recursos pueden provenir de diversas fuentes (es decir, se pueden acceder por medio de distintos “protocolos”) y además podría ser eficiente no capturarlo completo (en otras palabras, mejor obtener una conexión para leerlo conforme se requiere, que capturarlo completamente.) Como conveniencia, las APIs de Java proporcionan un InputStream para los casos en que no estamos interesados en toda la información aportada por el URL.

En mi caso, deseaba cargar (en array de bytes) archivos arbitrarios de un Jar. La solución inmediata consiste en invocar a getClass().getResourceAsStream(). Esto Funcionará bien en muchos casos, sin embargo puede fallar si el “Classloader actual” no tiene acceso al recurso.

Esta es una excelente lectura relevante. Esta otra es es de caracter instructivo.

Mi requerimiento se complicó debido a que mi utilitario de carga de recursos estaba en un Jar que iba a ser cargado dinámicamente; incluso, este utilitario sería invocado por otros objetos también cargados dinámicamente; y estas cargas dinámicas se harían desde un WAR, que también es cargado dinámicamente por el Web Container. La idea es que el utillitario también sea útil en aplicaciones standalone que lo incluyeran estáticamente. Finalmente, la versión que propongo va a continuación. En mi caso específico, el segundo intento es el que está dando resultados, lo cual tiene sentido: La clase ResourceUtil es cargada dinámicamente (por un classloader auxiliar que carga todos estos Jars) por lo que sólo dicho classloader tiene acceso a los recursos de estos Jars (el classloader del Web Container no los conoce.)


public class ResourceUtil {

private static byte[] loadResource(String name) {
try {
InputStream is;
is = new Object().getClass().getResourceAsStream(name);
if(is == null) {
is = ResourceUtil.class.getClassLoader().getResourceAsStream(name);
if(is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
if(is == null) {
return null;
}
}
}
BufferedInputStream bif = new BufferedInputStream(is);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int n;
while((n = bif.read()) != -1) {
baos.write(n);
}
bif.close();
baos.close();
return baos.toByteArray();
} catch(IOException ex) {
throw new RuntimeException(ex);
}
}
}

Categoria: Java. Tagged with , , .

0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Some HTML is OK

(required)

(required, but never shared)

(required)

or, reply to this post via trackback.