顯示具有 Gradle 標籤的文章。 顯示所有文章
顯示具有 Gradle 標籤的文章。 顯示所有文章

2018年3月21日 星期三

Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path

前言

最近在 Gradle 載入 Gretty Plugin,讓 Project 自帶 Container,但遇到了 dependency conflicts ,錯誤訊息如下
caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
        at org.slf4j.impl.Log4jLoggerFactory.(Log4jLoggerFactory.java:54)
        ... 37 more
gradle dep 看了一下,發現 Project 本身使用了 slf4j-log4j12,而 Gretty Run Tomcat Container 時需要依賴 log4j-over-slf4j,就是這兩個 library 造成 conflicts。

為什麼

先來看看 slf4j 官網的兩張圖
  • slf4j-log4j12:application 使用的是 slf4j 介面,再透過 adaptation layer 轉由呼叫 log4j framework。
  • log4j-over-slf4j:aplication 使用的是 log4j framework,但可以透過引入這個 library 取代,將原本使用 log4j API 的呼叫轉換至 slf4j 的介面,然後一樣透過 adaptation layer 轉由呼叫除了 log4j 以外的其他 log framework。
這裡有一個唯一的限制,就是不能橋接到相同的 log framework,為了防止 A-to-B.jar 跟 B-to-A.jar 同時出現在 classpath,而導致 A 與 B 一直不停地互相遞迴呼叫,直到發生 StackOverflowError。
SINCE 1.5.11 SLF4J software preempts the inevitable stack overflow error by throwing an exception with details about the actual cause of the problem. This is deemed to be better than leaving the user wondering about the reasons of the StackOverflowError.
…Detail

解法

就像上面解說的,不要讓 classpath 同時出現 log4j-over-slf4j.jar 跟 slf4j-log4j12.jar 就好囉,哈哈,有講跟沒講一樣~XD
好啦,以我自己上面的案例,因為 Gretty Run Tomcat Container 依賴 log4j-over-slf4j,這我沒辦法改,所以要嘛不要使用 Gretty 或改用 Gretty Jetty Container,要嘛改掉自己 Project,俗話說,改變不了環境,只好改變自己適應環境(疑..
解法一:不使用 slf4j-log4j12.jar 改為直接使用 log4j
解法二:使用 providedRuntime。
providedRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.21'

2015年3月2日 星期一

Gradle Build Project Example

  • Build.gradle : Simple Java Project Example

apply plugin: 'java'
sourceSets {
    main {
        java {
            srcDir 'src'
        }
        resources {
            srcDir 'src'
        }
    }
}
repositories {
    maven {
        credentials {
            username 'deployment'
            password ''
        }
        url "http://127.0.0.1:8081/nexus/content/groups/public/"
    }
}
 
dependencies {
    compile 'junit:junit:4.11'
    …
    …
}

  • Build.gradle : Web Project Example

apply plugin: 'eclipse-wtp'
apply plugin: 'jetty'

  • Build.gradle : Application Project Example

apply plugin: 'application'

def createScript(project, mainClass, name) {
  project.tasks.create(name: name, type: CreateStartScripts) {
    outputDir       = new File(project.buildDir, 'scripts')
    mainClassName   = mainClass
    applicationName = name
    classpath       = project.tasks[JavaPlugin.JAR_TASK_NAME].outputs.files + project.configurations.runtime
}

project.tasks[name].dependsOn(project.jar)

  project.applicationDistribution.with {
    into("bin") {
      from(project.tasks[name])
      fileMode = 0755
    }
  }
  
project.tasks[name].doLast {
    unixScript.text = unixScript.text.replace("\$CLASSPATH", ".:\$APP_HOME/lib/*") 
    //windowsScript.text = windowsScript.text.replace("%CLASSPATH%", ".;%APP_HOME%\\lib\\*") 
}
}

startScripts.enabled = false
run.enabled = false

createScript(project, 'com.gigabyte.HelloWorld ', 'helloworld')

2015年2月4日 星期三

Gradle & Nexus

Logdown -> http://villebez.logdown.com/posts/2015/01/27/gradle
最近為了改善程式庫相依、專案建置、佈署效率與正確的版本控管,所以研究了 Gradle 自動化工具。
另外,為了做部門的 Local Repository ,方便上傳、使用自行開發的 lib,所以建置了 Nexus 。
關於Nexus的安裝啟用,官網 nexus-book 已經有很詳細的參考說明了,
step by step就可以執行一個基本的Repository Server了。
推薦qrtt1在Codedata發表一系列關於Gradle的文章,【認識 Gradle】
從ant -> Maven -> Gradle,利用範例講解的很詳細。
如果要了解專案相依管理,可以直接跳到這篇 【認識 Gradle】(7)Java 專案相依管理
這篇並不是要介紹這兩個工具,
只是個紀錄,紀錄用了Gradle遇到的問題與解決方式,所以請先對Gradle有初步的了解。
這些問題可能也是大家剛開始使用常會遇到的,希望可以幫到你/妳。
Q1: apply plugin 是什麼?? 有哪些可以使用
A1.1: 類似於import, include,也就是 reuse logic
A1.2: 請參考這裡,更進階可以自行客製Plugin
Q2: 程式中文註解,造成編譯失敗
A2: 請服用~ compileJava.options.encoding = 'UTF-8'
Q3: 在MVNrepository找不到想要的libs
A3: 幾個方法,1. 上傳到自行建置的Repository Server,2. include local jar file
Q4: 什麼是providedCompile,跟compile有什麼差別
A4: providedCompile也是編譯時,專案會用到的jar,但跟compile最大的差異在,宣告為providedCompile的jar file不會打包到war file,所以當我的專案需要用到tomcat-catalina libs時,如果將它宣告為compile,則war檔在tomcat server執行時會造成library conflict錯誤。
Q5: 如何改變webapp dir
A5: project.webAppDirName = 'WebContent'