quinta-feira, 20 de outubro de 2011

Log4j mistura logs entre as aplicações no Weblogic


Tenho um Web Service JWS executado em Weblogic 10.2 e seus logs estavam sendo misturados com outra aplicação web rodando no mesmo servidor.

Eu pensei que as aplicações foram totalmente independentes dentro do servidor, mas elas não são. Elas compartilham alguns classloaders. Veja imagem abaixo:



Esse problema ocorre porque o jog4j.jar é compartilhado entre as aplicações e isto ocorre porque ele é buscado do mesmo classloader.

Para resolver este problema, é necessário que cada aplicativo tenha o seu próprio log4j.jar dentro do .war. (ou .ear quando aplicável). É importante que todas as aplicações tenham seu próprio log4j. Se um deles não tiver, o problema vai continuar.

Além de ter o log4j.jar, também é necessário editar o weblogic-application.xml para avisar o Weblogic para  usar as classes do log4j do classloader da aplicação.

Segue um exemplo de weblogic-application.xml:

<?xml version='1.0' encoding='UTF-8'?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<prefer-application-packages>
   <package-name>org.apache.log4j.*</package-name>
</prefer-application-packages>
</weblogic-application>


Se você estiver usando ant para construir o seu webservice JWS no Weblogic com a task jwsc, segue um trecho de build.xml que você pode usar para colocar o log4j no .war e usar um weblogic-application.xml personalizado.

No .war o log4j.jar deve ser colocado na pasta WEB-INF/lib e no .ear o weblogic-application.xml deve ser colocado na pasta META-INF.

<target name="jwsc" description="build web service">
  
    <delete dir="${build.dir}"/>
    <mkdir dir="${build.dir}"/>  
  
    <jwsc
        srcdir="${webapp.dir}"
        destdir="${build.dir}" 
     verbose="on" debug="on"
     keepGenerated="no" >

     <jws file="${jwsc.file}"
           compiledWsdl="${jwsc.jws.compiledWsdl}"
           contextPath="${jwsc.jws.contextPath}" 
           type="JAXWS" explode="false" >
</jws>
    </jwsc>
  
    <war destfile="${war.built}" update="true" >
        <fileset dir="${webapp.dir}">
           <include name="**/*.jar" />
   </fileset>
    </war>

    <copy file="${service.src}/resource/weblogic-application.xml" todir="${build.dir}/META-INF/" overwrite="true" />
  
 </target>



É importante que ${war.built} aponte para o ,war e o ${webapp.dir} aponte para a pasta com o fonte do webservice que possui pasta WEB-INF, que possui pasta lib, que possui log4j.jar.


Links:
http://download.oracle.com/docs/cd/E12840_01/wls/docs103/programming/classloading.html
https://forums.oracle.com/forums/thread.jspa?threadID=689458
http://www.coderanch.com/t/554020/Web-Services/java/adding-jar-files-building-war
http://ant.apache.org/manual/Tasks/war.html

quarta-feira, 19 de outubro de 2011

Por que o log4j não está logando?


Recentemente tive um problema com o mecanismo de log em um sistema que tive que dar manutenção.


Ele simplesmente estava ignorando a configuração log4j.properties e logava as mensagens com nível INFO.


Depois de algum tempo eu descobri que ele estava usando common-logging ao invés do log4j puro.


Não há nenhum problema em usar o commons-logging, ela funciona bem. O problema real era que apenas o commons-logging-api.jar e o log4j.jar foram incluídos no classpath. Estava faltando o commons-logging.jar.


Para suportar o log4j, o commos-logging precisa de dois jars no classpath: commons-logging e commons-logging-api.


Depois de adicionar o commons-logging.jar no classpath, o log4j.properties começou a ser lido e respeitado.


Leia mais sobre commons-logging aqui: http://commons.apache.org/logging/guide.html#Jars Included in the Standard Distribution