1. 程式人生 > >Weblogic 12c 執行使用Slf4j日誌框架應用解決方案

Weblogic 12c 執行使用Slf4j日誌框架應用解決方案

Weblogic 12c版本使用slf4j作為logging facade,bind的logger為jdk14。這樣在引擎(Weblogic)中載入的應用如果使用了slf4j+其他binder,執行時就會出現問題。


有人提出如下解決方案為:
刪除weblogic lib中的slf4j相關jar檔案(org.slf4j.api_1.6.1.0.jar\org.slf4j.ext_1.6.1.0.jar\org.slf4j.jdk14_1.6.1.0.jar.bak),但是這樣在weblogic啟動時會丟擲

ClassNotFoundException。
<2012-8-14 上午11時30分20秒 CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to STANDBY.> 
<2012-8-14 上午11時30分20秒 CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to STARTING.> 
<2012-8-14 上午11時30分21秒 CST> <Error> <Deployer> <BEA-149205> <Failed to initialize the application "name" due to error weblogic.management.DeploymentException: 
weblogic.management.DeploymentException: 
        at weblogic.application.internal.BaseDeployment.throwAppException(BaseDeployment.java:123)
        at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:239)
        at weblogic.application.internal.SingleModuleDeployment.prepare(SingleModuleDeployment.java:48)
        at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:158)
        at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:60)
        Truncated. see log file for complete stacktrace
Caused By: java.lang.ClassNotFoundException: org.slf4j.cal10n.LocLoggerFactory
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        Truncated. see log file for complete stacktrace
> 


這是意料之中的。weblogic啟動時也要進行日誌的初始化、slf4j的繫結等操作。從上述錯誤日誌可以看出,weblogic通過org.slf4j.cal10n.LocLoggerFactory來進行初始化工作,該類位於org.slf4j.ext_1.6.1.0.jar包中。


若不刪除weblogic中slf4j相關jar檔案,應用啟動會報如下異常(或org.slf4j.impl.JDK14LoggerFactory不能cast的異常)。目前對該異常的產生原因不是很理解:如下日誌應當是應用啟動後產生的,在slf4j初始化的時候(在測試應用的一個serlvet中),無論是org.slf4j.impl.JDK14LoggerFactory.class還是org.slf4j.helpers.NOPLoggerFactory都是ch.qos.logback.classic.LoggerContext的繼承類,不應當丟擲該類異常。除非在weblogic中的某個jar檔案中有相同全限定名的類。

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
<2012-8-14 上午10時51分46秒 CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to STANDBY.> 
<2012-8-14 上午10時51分46秒 CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to STARTING.> 
................logback start................./webapps/name/WEB-INF/conf/logback.xml
**** end ****
java.lang.ClassCastException: org.slf4j.helpers.NOPLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext


後參考stackflow中的一個問題答案,問題得到解決:
在應用WEB-INF目錄下建立一個名為weblogic.xml的配置檔案,內容為:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>

但是官方的推薦寫法為:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
  <container-descriptor>
    <prefer-web-inf-classes>false</prefer-web-inf-classes>
    <prefer-application-packages>
      <package-name>javax.faces.*</package-name>
      <package-name>com.sun.faces.*</package-name>
      <package-name>com.bea.faces.*</package-name>
    </prefer-application-packages>
 
    <prefer-application-resources>
      <resource-name>javax.faces.*</resource-name>
      <resource-name>com.sun.faces.*</resource-name>
      <resource-name>com.bea.faces.*</resource-name>
      <resource-name>META-INF/services/javax.servlet.ServletContainerInitializer</resource-name>
      </prefer-application-resources>
  </container-descriptor>
</weblogic-web-app>

必須要加上<prefer-web-inf-classes>false</prefer-web-inf-classes>屬性,且為false。

對該屬性的解釋為:

/** 
* If true, classes located in the WEB-INF directory of a web-app will be
* loaded in preference to classes loaded in the application or system
* classloader. 
* @default false 
*/ 

不需要對weblogic-server做任何調整。此配置的作用為在應用啟動時,使用應用的classpath的loader進行類載入。


參考文章:

http://stackoverflow.com/questions/9734503/prevent-weblogic-12c-from-using-systems-slf4j-binding