Mi aplicación de servlet incluye varios archivos .jar de biblioteca, algunos de los cuales contienen archivos embedded log4j.xml o log4j.properties. ¡Me gustaría asegurarme de que log4j encuentre mi log4j.xml primero! He intentado buscar alguna especificación de las prioridades de los diversos elementos classpath en un servlet (p. Ej., ¿Las clases WEB-INF/preceden siempre a WEB-INF/lib?), O alguna forma de configurar o modificar el cargador de clase del servlet para que el directorio de recursos dado aparece temprano en el classpath. Hasta ahora, he dibujado un espacio en blanco. ¿Alguna sugerencia para garantizar que un archivo .war del servlet cargue el log4j.xml correcto a través del cargador de clases?Controlar el classpath en un servlet
Respuesta
Por lo que tengo entendido, la selección de recursos del classpath no es determinista (desde el punto de vista del desarrollador de la aplicación). Incluso si el mismo archivo se carga constantemente, el comportamiento podría cambiar: 1. Cuando actualice la versión de su contenedor actual. 2. Si cambia contenedores.
La solución más simple será eliminar los archivos de configuración de log4j incorporados desde los archivos de la biblioteca. Casi nunca es una buena idea insertar las configuraciones de log4j ya que conduce al problema que está viendo aquí ...
¿Son jarras o tarros de terceros que usted desarrolló?
Es necesario tener log4j.properties en su CLASSPATH. El mejor lugar es en WEB-INF/classes.
También debe asegurarse de utilizar su versión de log4j.jar. Por lo tanto, colóquelo en WEB-INF/lib, solo para asegurarse de que no está utilizando uno de las carpetas de tomcat, ya que puede causar problemas de carga de clases extrañas.
que en realidad no responder a la pregunta que hice. ¿Está garantizado que WEB-INF/classes esté en el classpath antes de WEB-INF/lib? ¿Qué pasa si quiero que mi log4j.xml no esté en WEB-INF/classes sino en otro directorio? No es una clase después de todo. –
Pero tiene que estar en classpath – Marko
We the Spring Log4jConfigListener
en nuestro archivo web.xml.
Se puede especificar como un parámetro de contexto la ubicación del archivo de configuración de log4j, es decir, se podría configurar como /WEB-INF/log4j.xml
¿Esto sería una opción para usted? Si no está usando Spring, sé que puede establecer la ubicación de Log4j de forma programática, lo que también podría funcionar.
La primavera no es una opción en este proyecto, pero es un consejo útil a tener en cuenta para el futuro, ¡así que gracias! –
En mi experiencia, WEB-INF/classes generalmente tiene prioridad sobre los archivos jar en WEB-INF/lib, sin embargo, eso también depende del contenedor de servlets que use (nunca pude averiguar el comportamiento de JRun, por ejemplo) . Sería de gran ayuda si pudieras decirme qué contenedor estás usando.
Además, ¿está seguro de que la configuración de log4j ofensiva está en un contenedor en WEB-INF/lib? Por lo general, cuando me he encontrado con problemas de ruta de clases en una situación contenedor de servlets, es a causa de las bibliotecas que residen fuera de la aplicación web.
Las especificaciones de servlets recomiendan que los cargadores de clases de aplicaciones web se cargan sus propias clases antes de delegar a cargador de clases del contenedor (SRV.9.7.2), pero ya que es contraria a la especificación de Java, no todos los vendedores hacen esto por defecto (de hecho, Tomcat es el único contenedor que he usado que hace esto por defecto). Dicho esto, siempre es posible configurar el comportamiento de carga de clase de su aplicación web del contenedor. Si me dices qué contenedor estás utilizando, puedo ayudarte (específicamente, lo he hecho antes con éxito en WebLogic, WebSphere, Glassfish y JRun)).
Hola Jack, Actualmente estoy usando Tomcat 6 (tomcat6-6.0.18-1.1.fc9.noarch) y Jetty 6.1.11. Y no, no estoy del todo seguro de que el choque provenga de las configuraciones de log4j en mis .jars ... tenemos un comportamiento de registro extraño, y las configuraciones conflictivas parecen una buena hipótesis atm. –
No he usado Jetty, pero en Tomcat, probablemente pueda descartar la configuración del cargador de clases como problema. ¿Está log4j.jar en su directorio WEB-INF/lib? –
Si no puede controlar la ruta de clase, como Tomcat la está configurando, ¿al menos puede establecer una propiedad del sistema para log4j.configuration
? Creo que la ubicación señalada por esa propiedad se puede establecer fuera de la ruta de clases.
De lo contrario, otro enfoque, aunque desagradable, sería ejecutar explícitamente uno de los configuradores en el código de la aplicación.
Tomcat 8.5
Ditto Tomcat 8.0.
Ver documentación: Class Loader HOW-TO.
Tomcat 8.0
La respuesta es simple, tomado de la página de documentación de Tomcat, Class Loader HOW-TO. En particular, tenga en cuenta el uso del directorio/carpeta /WEB-INF/
.
Por lo tanto, desde la perspectiva de una aplicación web, la clase o el recurso de carga se ve en los siguientes repositorios, en este orden:
- clases de archivos de inicio de la JVM
/WEB-INF/classes
de su aplicación web/WEB-INF/lib/*.jar
de su aplicación web- clases de cargador de clases Sistema (descrito anteriormente)
- clase clases del cargador común (descrito anteriormente)
Si la aplicación cargador de clases Web es configured con
<Loader delegate="true"/>
entonces el orden se convierte en:
- clases de archivos de inicio de la JVM
- clases de cargador de clases del sistema (descritos arriba)
- Clases comunes del cargador de clases (descrito anteriormente)
/WEB-INF/classes
de su aplicación web/WEB-INF/lib/*.jar
de su aplicación web
Tomcat 6
Extraído de Tomcat página 6, Class Loader HOW-TO.
Por lo tanto, desde la perspectiva de una aplicación web, la clase o el recurso de carga se ve en los siguientes repositorios, en este orden:
- clases de archivos de inicio de la JVM
- clases de cargador de clases del sistema (descritos arriba)
/WEB-INF/classes
de su aplicación web/WEB-INF/lib/*.jar
de su aplicación web$CATALINA_HOME/lib
$CATALINA_HOME/lib/*.jar
- 1. ¿Se puede controlar el escaneo classpath en Weld?
- 2. Controlar programáticamente el inicio de sesión con Servlet 3.0
- 3. System.exit en el servlet
- 4. iniciando un nuevo hilo en el servlet
- 5. leer el archivo en classpath
- 6. Cómo dar prioridad a un archivo jar en classpath eclipse?
- 7. ¿Qué es un classpath?
- 8. Contenedores de servlets y classpath
- 9. threadlocal variables en un servlet
- 10. Guice inject en el servlet
- 11. Incluir el contenido de un JSP en un servlet
- 12. Jetty Classpath issues
- 13. Falta un archivo .classpath en el proyecto Eclipse
- 14. Limitación Classpath en Linux
- 15. ¿Servlet es el singleton?
- 16. ¿Cómo edito el classpath (runtime) en Eclipse?
- 17. ¿Cómo detectar duplicados JAR en el classpath?
- 18. ¿Cómo puedo controlar el tiempo de renderizado en un navegador?
- 19. Controlar el valor de 'esto' en un evento de jQuery
- 20. Cómo controlar el número de filas en un JasperReports
- 21. ¿Cómo controlar un dispositivo serial en Android?
- 22. Espacios en blanco en CLASSPATH
- 23. controlar una excepción lanzada en un generador
- 24. Llamar a un servlet al hacer clic en el hipervínculo
- 25. cómo inicializar un servlet en el inicio del servidor
- 26. Controlar un cambio en la propiedad
- 27. Usando CDI de inyección en un servlet
- 28. Registrar programáticamente un servlet en Jetty 7
- 29. ¿Cómo redirigir en un filtro de servlet?
- 30. Procesamiento asíncrono en Java desde un servlet
De terceros, de ahí el problema. –
A riesgo de sonar despiadado, tal vez debería nombrarlos y avergonzarlos en la pregunta, y también presentar un error ... – johnstok
Sugeriría eliminar manualmente el archivo de configuración log4j del jar de terceros. Sin embargo, esto será un dolor si usa maven, ivy, etc. para administrar dependencias. – johnstok