Discussion:
jar y archivo de configuración
(demasiado antiguo para responder)
dm242
2006-07-28 17:04:16 UTC
Permalink
hola tengo el siguiente problema, tengo un jar ejecutable el cual
dentro de una de sus clases, hay un a llamada a un archivo de
connfiguracion que esta en el mismo directorio que el jar, la cosa es
que cuando yo ejecuto el programa sin utilizar el jar o sea java
paquete.clase.Principal se ejecuta todo bien, pero cuando trato de
ejecutar lo mismo pero con el jar no me resulta, la idea no es dejar el
archivo de configuracion dentro del jar sino en la misma carpeta que
este
Guevonaso
2006-08-07 06:20:20 UTC
Permalink
Post by dm242
hola tengo el siguiente problema, tengo un jar ejecutable el cual
dentro de una de sus clases, hay un a llamada a un archivo de
connfiguracion que esta en el mismo directorio que el jar, la cosa es
que cuando yo ejecuto el programa sin utilizar el jar o sea java
paquete.clase.Principal se ejecuta todo bien, pero cuando trato de
ejecutar lo mismo pero con el jar no me resulta, la idea no es dejar el
archivo de configuracion dentro del jar sino en la misma carpeta que
este
¿Quizás estás cargando el fichero de configuración a través del
classpath?

Si es así, ejecutando un
java -classpath . paquete.Clase

Si funciona, porque encuentra el ficher de configuracion dentro del
classpath ("la raiz") mientras que ejecuntandolo con un :

java -jar nombredeljar.jar

El fichero de configuración está fuera de este classpath.
BaByTuX
2006-08-31 07:20:44 UTC
Permalink
Post by Guevonaso
Post by dm242
hola tengo el siguiente problema, tengo un jar ejecutable el cual
dentro de una de sus clases, hay un a llamada a un archivo de
connfiguracion que esta en el mismo directorio que el jar, la cosa es
que cuando yo ejecuto el programa sin utilizar el jar o sea java
paquete.clase.Principal se ejecuta todo bien, pero cuando trato de
ejecutar lo mismo pero con el jar no me resulta, la idea no es dejar el
archivo de configuracion dentro del jar sino en la misma carpeta que
este
¿Quizás estás cargando el fichero de configuración a través del
classpath?
Si es así, ejecutando un
java -classpath . paquete.Clase
Si funciona, porque encuentra el ficher de configuracion dentro del
java -jar nombredeljar.jar
El fichero de configuración está fuera de este classpath.
La forma en la que debes de llamar a los ficheros dentro del jar, es con


getClass().getResource("images/babytux.gif"))

Saludos
_________________________________________
Usenet Zone Free Binaries Usenet Server
More than 140,000 groups
Unlimited download
http://www.usenetzone.com to open account
Ricardo Palomares Martinez
2006-08-31 13:30:18 UTC
Permalink
Post by BaByTuX
Post by Guevonaso
Post by dm242
hola tengo el siguiente problema, tengo un jar ejecutable el cual
dentro de una de sus clases, hay un a llamada a un archivo de
connfiguracion que esta en el mismo directorio que el jar, la cosa es
que cuando yo ejecuto el programa sin utilizar el jar o sea java
paquete.clase.Principal se ejecuta todo bien, pero cuando trato de
ejecutar lo mismo pero con el jar no me resulta, la idea no es dejar el
archivo de configuracion dentro del jar sino en la misma carpeta que
este
¿Quizás estás cargando el fichero de configuración a través del
classpath?
Si es así, ejecutando un
java -classpath . paquete.Clase
Si funciona, porque encuentra el ficher de configuracion dentro del
java -jar nombredeljar.jar
El fichero de configuración está fuera de este classpath.
La forma en la que debes de llamar a los ficheros dentro del jar, es con
getClass().getResource("images/babytux.gif"))
Como a mí me acaba de funcionar es así:

// We try to get the bundled en-US install.properties
ClassLoader cl = this.getClass().getClassLoader();
bis = (BufferedInputStream) // follows in next line
cl.getResourceAsStream("org/mozillatranslator/resource/install.properties");


Lo encontré en una página web buscando precisamente sobre esto y
alguien propuso tu solución, y creo recordar que otros contestaron que
eso funciona sólo dentro del JAR (fallaría al usarlo con los archivos
.class directamente dentro de un directorio, como suele pasar mientras
depuras en un IDE).

Saludos.
--
If it's true that we are here to help others,
then what exactly are the OTHERS here for?
Eduardo Yáñez Parareda
2006-08-31 14:29:00 UTC
Permalink
Post by Ricardo Palomares Martinez
// We try to get the bundled en-US install.properties
ClassLoader cl = this.getClass().getClassLoader();
bis = (BufferedInputStream) // follows in next line
cl.getResourceAsStream("org/mozillatranslator/resource/install.properties");
Hombre, tamopco hace falta acceder al ClassLoader:

this.getClass().getResourceAsStream("org/mozillatranslator/resource/install.properties");

funciona perfectamente.

O si estás en un método estático:

NombreClase.getResourceAsStream(.....
Ricardo Palomares Martinez
2006-09-03 17:19:12 UTC
Permalink
Post by Eduardo Yáñez Parareda
Post by Ricardo Palomares Martinez
// We try to get the bundled en-US install.properties
ClassLoader cl = this.getClass().getClassLoader();
bis = (BufferedInputStream) // follows in next line
cl.getResourceAsStream("org/mozillatranslator/resource/install.properties");
this.getClass().getResourceAsStream("org/mozillatranslator/resource/install.properties");
funciona perfectamente.
¿Y si no funciona perfectamente? Lo digo porque ni mi solución ni la
tuya sin ClassLoader() me funciona. Me funcionaba dentro del IDE,
porque en realidad no estaba buscando el recurso dentro del JAR, sino
en el directorio build/ con las clases y los archivos de recursos
copiados, pero al intentar ejecutar el JAR directamente no va. He
probado un montón de cosas y ninguna funciona.

Al parecer el problema es que la URL que se genera está mal (al menos
eso opino yo), porque tras "file:" no van tres barras, sino sólo una
(lo normal es que una URL file: tenga la forma
file:///home/pepito/loquesea, o si es en Windows, file:///C|/loquesea).

¿Alguna sugerencia sobre cómo averiguar la causa del problema?

Gracias por anticipado.
--
If it's true that we are here to help others,
then what exactly are the OTHERS here for?
Eduardo Yáñez Parareda
2006-09-04 07:20:06 UTC
Permalink
Post by Ricardo Palomares Martinez
Post by Eduardo Yáñez Parareda
Post by Ricardo Palomares Martinez
// We try to get the bundled en-US install.properties
ClassLoader cl = this.getClass().getClassLoader();
bis = (BufferedInputStream) // follows in next line
cl.getResourceAsStream("org/mozillatranslator/resource/install.properties");
this.getClass().getResourceAsStream("org/mozillatranslator/resource/install.properties");
funciona perfectamente.
¿Y si no funciona perfectamente?
Pues es no tienes el recurso en el classpath, o que el método es estático, en cuyo caso
tienes que usar el segundo método.
Además, el path siempre tiene que empezar con /

Es decir si el recurso lo tienes en

proyecto/classes/recurso.txt

hay que buscarlo en /resurso.txt (si classes está en el classpat claro).

Si estuviese en

proyecto/classes/org/dir2/dir2/recurso.gif

hay que buscarlo en:

/org/dir1/dir2/recurso.gif
Ricardo Palomares Martinez
2006-09-06 19:58:07 UTC
Permalink
Post by Eduardo Yáñez Parareda
Post by Ricardo Palomares Martinez
¿Y si no funciona perfectamente?
Pues es no tienes el recurso en el classpath, o que el método es
estático, en cuyo caso tienes que usar el segundo método.
Ante todo, muchas gracias por contestar. Lo que me cuentas viene a ser
lo que he leído que tiene que pasar, pero no es lo que pasa. :-(
Post by Eduardo Yáñez Parareda
Además, el path siempre tiene que empezar con /
Si no usas getClassLoader(), sí, en caso contrario no, porque la ruta
se presupone absoluta dentro del directorio raíz de ejecución.
Post by Eduardo Yáñez Parareda
Es decir si el recurso lo tienes en
proyecto/classes/recurso.txt
hay que buscarlo en /resurso.txt (si classes está en el classpat claro).
Si estuviese en
proyecto/classes/org/dir2/dir2/recurso.gif
/org/dir1/dir2/recurso.gif
Lo de .getResourceAsStream() tiene miga, la verdad. El sitio en el que
lo explican más claro para mi gusto es aquí:

http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html

Pero el caso es que a mí no me funciona dentro del JAR. El JAR tiene
esta estructura:

(...otros archivos...)
org/mozillatranslator/resource/install.properties
(...otros archivos...)
org/mozillatranslator/runner/WriteXPIRunner.class
(...)

Dentro de WriteXPIRunner he probado esto:

bis = (BufferedInputStream)
this.getClass().getClassLoader().getResourceAsStream("org/mozillatranslator/resource/install.properties");

y esto:

bis = (BufferedInputStream)
this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties");

Incluso copié el archivo install.properties al directorio runner para
que estuviera junto a la clase y probé esto:

bis = (BufferedInputStream)
this.getClass().getResourceAsStream("install.properties");

Todo lo anterior funciona cuando estoy en modo de depuración (en cuyo
caso Netbeans usa las clases generadas en el directorio
build/org/mozillatranslator/...) pero no si ejecuto el JAR, ya sea
dentro de Netbeans o no.

Ojalá me digáis qué estoy haciendo algo mal, pero si no, me conformo
con que me digáis que *debería* funcionar, aunque no lo haga.

Gracias por anticipado.
--
If it's true that we are here to help others,
then what exactly are the OTHERS here for?
Eduardo Yáñez Parareda
2006-09-07 07:56:53 UTC
Permalink
Post by Ricardo Palomares Martinez
Post by Eduardo Yáñez Parareda
Además, el path siempre tiene que empezar con /
Si no usas getClassLoader(), sí, en caso contrario no, porque la ruta
se presupone absoluta dentro del directorio raíz de ejecución.
getResourceAsStream se apoya en el ClassLoader, por eso para llamarlo usas getClass() :)

Vamos a ver, he hecho un test, he creado un proyecto con esta estrructura:

org/mozillatranslator/runner/WriteXPIRunner.java
org/mozillatranslator/resource/install.properties con una property llamada configuración.

El código es el siguiente:

package org.mozillatranslator.runner;

import java.util.Properties;

/**
* @author Eduardo.
*/
public class WriteXPIRunner {
/**
*
*/
public WriteXPIRunner() {
super();
try {
Properties props = new Properties();
props.load(this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties"));
int valor = Integer.parseInt(props.getProperty("configuracion"));
System.out.println("configuracion => " + valor);
} catch (Exception ex) {
ex.printStackTrace();
}
}

/**
* @param args
*/
public static void main(String[] args) {
WriteXPIRunner runner = new WriteXPIRunner();
}
}


Luego he generado un jar (test-jar.jar), y he ejecutado:

java -jar test-jar.jar

El resultado es:

configuracion => 1


Ahora crea tú el mismo proyecto, genera el jar y dime que no te funciona. Si no te funciona es que probablemente
estés creando el jar mal, porque no tiene más miga el asunto.
Ricardo Palomares Martinez
2006-09-18 16:27:37 UTC
Permalink
Lo primero, muchas gracias por las molestias que te estás tomando.
Post by Eduardo Yáñez Parareda
java -jar test-jar.jar
configuracion => 1
Ahora crea tú el mismo proyecto, genera el jar y dime que no te
funciona.
Sí, funcionó, pero con [prácticamente] las mismas instrucciones, el
proyecto problemático seguía sin funcionar.
Post by Eduardo Yáñez Parareda
Si no te funciona es que probablemente
estés creando el jar mal, porque no tiene más miga el asunto.
Al final no van por ahí los tiros. Lo que he hecho es trasladar el
código relevante de mi proyecto a tu prueba de concepto, para que mi
frase de por ahí arriba no necesite llevar "[prácticamente]"... y
Post by Eduardo Yáñez Parareda
Properties props = new Properties();
props.load(this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties"));
int valor = Integer.parseInt(props.getProperty("configuracion"));
System.out.println("configuracion => " + valor);
Properties props = new Properties();
props.load((BufferedInputStream) this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties"));
// También he probado lo siguiente para depurar
// URL thisRes = this.getClass().getResource("/org/mozillatranslator/resource/install.properties");
// BufferedInputStream bis = (BufferedInputStream) thisRes.openStream();
// props.load(bis);
int valor = Integer.parseInt(props.getProperty("configuracion"));
System.out.println("Configuración : " + valor);
y casca con un java.lang.ClassCastException:
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream. Parece
que el problema está en que un BufferedInputStream no puede crearse a
partir de un JAR. :-? Por eso cuando lo ejecuto dentro del IDE
funciona (parece que Netbeans siempre tira de los .class en el disco
duro, no abre el JAR), pero al salir a la línea de órdenes no funciona.

Ahora tengo que mirar si puedo prescindir del "Buffered". Se supone
que conviene usarlo para no ralentizar la lectura, ¿no?

Saludos y muchas gracias por tu ayuda.
--
If it's true that we are here to help others,
then what exactly are the OTHERS here for?
Eduardo Yáñez Parareda
2006-09-19 09:21:23 UTC
Permalink
Post by Eduardo Yáñez Parareda
Properties props = new Properties();
props.load((BufferedInputStream) this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties"));
Es que no puedes hacer un casting a BufferedInputStream porque no sabes si lo que te devuelve getResourceAsStream es de
esa clase, por eso te da el ClassCastException.

No puedes hacer:

Casa casa = new Casa();
Integer num = (Integer) casa;

Pues lo mismo te pasa con eso que estás intentando. El uso de BufferedInput y Output lo tienes que hacer cuando
eres tú el que estás creando los Streams.
Ricardo Palomares Martinez
2006-09-20 20:50:17 UTC
Permalink
Post by Eduardo Yáñez Parareda
Post by Eduardo Yáñez Parareda
Properties props = new Properties();
props.load((BufferedInputStream)
this.getClass().getResourceAsStream("/org/mozillatranslator/resource/install.properties"));
Es que no puedes hacer un casting a BufferedInputStream porque no sabes
si lo que te devuelve getResourceAsStream es de
esa clase, por eso te da el ClassCastException.
Casa casa = new Casa();
Integer num = (Integer) casa;
Pues lo mismo te pasa con eso que estás intentando. El uso de
BufferedInput y Output lo tienes que hacer cuando
eres tú el que estás creando los Streams.
Bueno, de hecho lo he solucionado definitivamente usando un
InputStream y punto, que es lo que devuelve .getResourceAsStream().

Aún así, no acabo de entender por qué en modo depuración, tirando de
los .class en el directorio build/ sí podía hacer el cast, y en cambio
en ejecución normal, tirando del JAR, no me lo permitía.

getResourceAsStream() devolverá un InputStream se ejecute de un modo u
otro, ¿no? ¿Es que internamente crea un BufferedInputStream, o algo
que se puede tratar como tal, cuando está leyendo de disco, y un tipo
distinto de InputStream no convertible a BufferedInputStream cuando
lee de JAR?

Aunque "formalmente" no me pueda quejar de que Java ha hecho algo
"raro" (vale, la documentación sólo me garantiza un InputStream), no
deja de ser algo inesperado el hecho de que en algunos casos pueda
considerar ese InputStream como BufferedInputStream y en otros no.

En fin, solucionado en cualquier caso. De nuevo, muchas gracias por tu
ayuda.
--
If it's true that we are here to help others,
then what exactly are the OTHERS here for?
Eduardo Yáñez Parareda
2006-08-07 07:23:03 UTC
Permalink
Tienes que definir el classpath en un archivo MANIFEST.MF en un directorio META-INF dentro del JAR.
En ese fichero tienes que especificar el classpath y la clase que contiene el main.
Por cierto, el fichero tiene que acabar con salto de línea.

Más info: http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html#JAR%20Manifest
Continúe leyendo en narkive:
Loading...