사용자 도구

사이트 도구


gradle:java

Gradle Java Plugin

apply plugin: 'java'

Java Project 기본 build.gradle

  • 기본적인 자바 프로젝트 구성을 도와주는 build.gradle로 Eclipse 프로젝트를 가정하고 있다.
apply plugin: 'java'
apply plugin: 'eclipse'
 
ext {
  javaVersion='1.6'
}
 
buildDir = 'build'
 
repositories {
  mavenCentral()
}
 
dependencies {
  compile '원하는 모듈'
  testCompile group: 'junit', name: 'junit', version: '4.+'
}
 
task initSrc << {
    project.sourceSets*.allSource.srcDirTrees.flatten().dir.each { dir ->
        dir.mkdirs()
    }
}
 
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
 
// 소스 인코딩 지정방법 1
[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'
// 소스 인코딩 지정밥법 2
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}
javadoc {
    options.encoding = 'UTF-8'
}
 
/* Eclipse 관련 설정들 */
tasks.eclipse.dependsOn cleanEclipse
tasks.eclipse.dependsOn initSrc
 
eclipse {
  classpath {
    downloadSources = true
    defaultOutputDir = file("${buildDir}/classes/main")
  }
}

기본 디렉토리 구조

  • Maven과 동일하다.
  • 소스 : src/main/java, src/main/resources
  • 테스트 : src/test/java, src/test/resources
  • 빌드 결과 : build/*
    • buildDir 를 프로젝트에 상대적인 경로로 바꿔줄 수 있다.
      buildDir = 'target'
    • export GRADLE_OTPS=“-Dorg.gradle.project.buildDir=/path/to/custom-build-dir System Property 옵션으로 buildDir을 명령행에서 변경할 수 있다. 명령행에 지정하면 안 됐고, 항상 환경변수로 해야만 했다.

기본 태스크

  • clean : build 디렉토리 삭제
  • compileJava, compileTestJava : 소스 컴파일
  • assemble : 컴파일 하고 jar 생성. 웹 프로젝트일 경우에는 war 생성. 단위 테스트 실행 안함.
  • check : 컴파일하고 단위테스트 실행.
  • 자세한 것은 Java Plugin의 Tasks 참조.

기본 의존성 설정

repositories {
    mavenCentral()
}
 
dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

Publishing Jar

// 저장소를 지정하고,
uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

gradle uploadArchives 명령으로 퍼블리싱한다.

Source Sets

  • Java 플러그인에는 Source Set이라는 개념이 들어가 있으며, 이는 함께 컴파일과 실행되는 소스 파일들의 그룹을 뜻한다.
  • 소스 셋에는 자바 소스 파일과 리소스 파일들이 들어간다.
  • 다른 플러그인들이 그루비나 스칼라 소스를 추가할 수 있다.
  • 소스 셋은 컴파일 클래스패스와 런타임 클래스패스와 관련된다.
  • 소스 셋의 목적은 소스들를 논리적 그룹으로 묶고 그 목적을 설명하는 데 있다. 통합 테스트용 소스셋, API 인터페이스 클래스들, 구현체 클래스들 형태로 구분 가능하다.
  • 기본 Java Source Set
    • main : 실제 작동 소스코드. 컴파일해서 JAR 파일로 들어간다.
    • test : 단위 테스트 소스코드. 컴파일해서 JUnit이나 TestNG로 실행한다.
  • 아래에서 자세히 다룸.

프로젝트 레이아웃

자바 프로젝트의 기본 프로젝트 레이아웃은 다음과 같다.

  • src/main/java : 실행 자바 소스
  • src/main/resources : 실행 리소스
  • src/test/java : 테스트 자바 소스
  • src/test/resources : 테스트 리소스
  • src/소스셋/java : 특정 소스 셋의 Java 소스
  • src/소스셋/resources : '특정 소스 셋의 리소스

의존성 관리

다음과 같은 의존성 설정(configurations)이 추가되다. 이 의존성 설정은 자바 플러그인의 태스크들에 의해 참조 된다.

이름 부모 사용하는 태스크 의미
compile - compileJava 컴파일 시점 의존성
runtime compile - 실행시 의존성
testCompile compile compileTestJava 테스트를 컴파일할 때 필요한 추가적인 의존성
testRuntime runtime, testCompile test 테스트만 실행할 때 필요한 추가적인 의존성
archives - uploadArchives 해당 프로젝트가 생성한 Artifact(jar 등)
default runtime - 이 프로젝트에서 기본으로 사용되는 의존성. 이 프로젝트의 실행시에 필요한 Artifact들과 의존성을 포함한다.

소스 셋을 추가하면 다음과 같은 의존성 설정도 함께 추가된다.

이름 부모 사용하는 태스크 의미
소스셋Compile - compile소스셋Java 특정 소스셋의 컴파일시점 의존성
소스셋Runtime 소스셋Compile - 특정 소스셋의 실행시 의존성

관례 프라퍼티들

Gradle 문서 참조. JavaPluginConvention, BasePluginConvention 참조.

Source Set 다루기

  • 프로젝트의 소스 셋은 sourceSets 프라퍼티로 접근할 수 있다. SourceSetContainer 타입.
    println sourceSets.main.output.classesDir
    println sourceSets['main'].output.classesDir
     
    sourceSets {
        println "Sources Sets " + main.output.classesDir
    }
    sourceSets {
        main {
            println "Source Sets main " + output.classesDir
        }
    }
    sourceSets.all {
        println "Iterate all Source Sets : " + name
    }
  • 위에서 사용한 sourceSets 접근 방식 중 하나로 소스셋에 접근하고 변경할 수 있다.
    // main java 소스셋의 디렉토리 추가
    sourceSets {
        main {
            java {
                srcDir 'src/java'
            }
            resources {
                srcDir 'src/resources'
            }
        }
    }

저기서 main 은 SourceSet이다.

저기서 'java'와 'resources'는 SourceDirectorySet이며 srcDir()메소드는 소스 디렉토리를 추가하는 것이다.

Source Set 프라퍼티들

  • SourceSet 참조.
  • 기본적인 프라퍼티들
프라퍼티 이름 Type 기본값 설명
name String(read-only) not null 소스셋 이름
output SourceSetOutput not null 소스셋의 출력 디렉토리. 컴파일된 클래스와 리소스를 저장할 곳
output.classesDir File buildDir/classes/name 소스셋의 클래스를 생성할 디렉토리
output.resourcesDir File buildDir/resources/name 소스셋의 리소스를 생성할 디렉토리
compileClasspath FileCollection compileSourceSet configuration 소스를 컴파일할 때 사용할 클래스패스
runtimeClasspath FileCollection output + runtimeSourceSet configuration 클래스 실행시의 클래스패스
java SourceDirectorySet (read-only) not null 소스셋의 자바 소스파일들. *.java 파일만 포함호며 그 외 파일은 제외된다.
java.srcDirs Set<File>, Project.files()에서 사용할 수 있는 모든 값 [projectDir/src/name/java] 자바 소스 파일을 포함하고 있는 소스 디렉토리들, srcDir()로 추가가능
resources SourceDirectorySet (read-only) not null 소스셋의 리소스들. *.java 파일은 제외된다. 플러그인에 때라 제외되는 목록이 추가된다.
resources.srcDirs Set<File>, Project.files()에서 사용할 수 있는 모든 값 [projectDir/src/name/resources] 리소스를 포함하고 있는 소스 디렉토리들
allJava SourceDirectorySet (read-only) java 모든 *.java 파일들. 플러그인에 따라 더 추가 될 수 있음
allSource SourceDirectorySet (read-only) resources + java 모든 소스 파일들(리소스 + *.java). 플러그인에 따라 더 추가 될 수 있음.

main/resources에 java 디렉토리를 추가하면서 *.java 파일은 제외하기

때로는 src/main/java 를 리소스에 포함시켜야 할 경우가 있다. 개발자들이 resources에 리소스를 넣지 않고 java에 넣고서 클래스와 리소스간의 결합성을 쉽게 파악할 수 있고자 할 경우가 있기 때문이다(iBATIS SqlMapper 사용하는 경우 등).

sourceSets {
    main {
        resources {
            srcDir "${project.projectDir}/src/main/java"
            // exclude "**/*.java" : 하지 말것. Gradle에서 문제 없지만 Eclipse에서 문제를 일으킴.
        }
    }
}

새로운 소스셋 만들기

  • sourceSets { } 블럭 안에 정의하면 된다.
  • 소스셋이 추가되면 소스셋 이름으로 시작하는 의존성 설정도 추가된다. 이를 사용해 원하는 대로 의존성 설정을 할 수 있다.
    sourceSets {
      intTest
    }
     
    // 의존성 설정
    dependencies {
        intTestCompile 'junit:junit:4.8.2'
        intTestRuntime 'org.ow2.asm.asm-all:4.0'
    }
  • 소스셋이 추가되면 소스셋 태스크도 추가된다.
    • gradle intTestClasses 형태로 실행.
    • compile소스셋Java : 소스셋의 소스 컴파일
    • process소스셋Resources : 소스셋의 리소스를 클래스 디렉토리로 복사한다.
    • 소스셋Classes : compile소스셋Java와 process소스셋Resources 실행.

소스셋 태스크 예제

  • Jar 묶기 태스크
    task intTestJar(type: Jar) {
        from sourceSets.intTest.output
    }
  • Javadoc 생성 태스크
    task intTestJavadoc(type: Javadoc) {
        source sourceSets.intTest.allJava
    }
  • 단위 테스트 실행 태스크
    task intTest(type: Test) {
        testClassesDir = sourceSets.intTest.output.classesDir
        classpath = sourceSets.intTest.runtimeClasspath
    }
  • java/test 소스셋 디렉토리 자동 생성
    // eclipse 플러그인 실행시 자동으로 기본 Java 디렉토리 구조를 생성하도록 한다.
    task baseDirs << {
    	sourceSets.each { set ->
    		set.java.srcDirs.each { dir ->
    			if (!dir.exists()) dir.mkdirs()
    		}
    		set.resources.srcDirs.each { dir ->
    			if (!dir.exists()) dir.mkdirs()
    		}
    	}
     
    	if (!buildDir.exists()) buildDir.mkdirs()
    }
     
    tasks.eclipse.dependsOn baseDirs

Javadoc

태스크 프라퍼티 타입 기본값
classpath FileCollection sourceSets.main.output + sourceSets.main.compileClasspath
source FileTree sourceSets.main.allJava]]
destincationDir File
title String 프로젝트 이름과 버전

* StandardJavadocDocletOptions (Gradle API 1.10) 참조하여 javadoc 옵션들 지정.

Java 9 HTML5 javadoc

javadoc {
    options.addBooleanOption('html5', true)
}

멀티 모듈의 소스를 합쳐 Javadoc 생성

task javadoc(type: Javadoc) {
    source subprojects.collect {project ->
        project.sourceSets.main.allJava
    }
    destinationDir = new File(buildDir, 'javadoc')
    // Might need a classpath
    classpath = files(subprojects.collect {project ->
        project.sourceSets.main.compileClasspath})
    }
}

Delombok

  • Lombok 사용시 delombok 후에 javadoc 생성을 해야 올바르게 나온다. 참조
    ext {
        lombokVersion = '1.12.4'
    }
     
    configurations {
        lombok
    }
     
    dependencies {
        lombok "org.projectlombok:lombok:${lombokVersion}"
    }
     
    task delombok {
        ext.srcJava = 'src/main/java'
        ext.srcDelomboked = "${buildDir}/src-delomboked"
     
        inputs.files file(srcJava)
        outputs.dir file(srcDelomboked)
        doLast {
            // 보통은 configurations.runtime만으로 충분하지만, 가끔 provided 등의 사용자정의 configuration이
            // 존재 할 경우 classpath에 존재하지 않는 라이브러리라서 경고를 보여줄 수 있으므로
            // 모든 configurations의 의존성을 하나로 모아서 classpath로 지정한다.
            def allDependencies = configurations.lombok.asFileTree
            configurations.all { configuration -> allDependencies = allDependencies + configuration.asFileTree }
     
            // 구버전 Task class : lombok.delombok.ant.DelombokTask
            // 최신버전 Task class: lombok.delombok.ant.Tasks$Delombok
            ant.taskdef(name: 'delombok', classname: 'lombok.delombok.ant.Tasks$Delombok',
                classpath: configurations.lombok.asPath)
            ant.delombok(from: srcJava, to: srcDelomboked, verbose: true,
                encoding: 'UTF-8', classpath: allDependencies.asPath)
        }
    }
  • delombok 후 javadoc 생성
    javadoc {
        dependsOn delombok
        source = fileTree(dir: delombok.srcDelomboked, includes: ['**/*.java', '**/*.html'])
        options.encoding = 'utf-8'
    }
    // 불필요한 리소스가 복사되는 경우에 대비해 java/html 파일만 include

Clean

  • Delete Task의 인스턴스
  • Clean의 프라퍼티
태스크 프라퍼티 타입 기본값
dir File buildDir

Resources

  • ProcessResources 태스크(Copy 상속)
  • ProcessResources 태스크의 프라퍼티들
태스크 프라퍼티 타입 기본값
srcDirs files()가 받을 수 있는 모든 값 sourceSet.resources
destinationDir File sourceSet.output.resourcesDir

CompileJava

  • JavaCompile Task 인스턴스
  • compileTestJava에도 공통 적용된다.
  • 기본적인 옵션들
태스크 프라퍼티 타입 기본값
classpath FileCollection sourceSet.compileClasspath
source FileTree files()가 받을 수 있는 모든 인자]] sourceSet.java
sourceCompatibility String Java 소스의 Java 언어 레벨 (…, 1.4,1.5,1.6,1.7 …) project.sourceCompatibilty
targetCompatibility Strign Java 클래스의 Java 언어레벨 project.targetCompatibility
destinationDir File sourceSet.output.classesDir
options CompileOptions 컴파일 관련 각종 옵션 설정
  • compile 태스크는 Ant의 javac 태스크를 호출한다. options.useAnt=false로 바꾸면 Ant를 건너뛰고 Gradle 기본 컴파일러로 수행한다.
  • 기본적으로 Gradle 프로세스 안에서 컴파일러를 호출하지만 options.fork=true로 설정하면 독립 컴파일러 프로세스가 뜨게 된다. 성능이 떨어질 수 있다.
  • options에서 소스 인코딩 등을 지정할 수 있다.

컴파일 옵션들

아래 값들은 Java 플러그인을 적용한 뒤에 설정해야 한다. 그렇지 않으면 Java 플러그인이 값을 초기화 해 버릴 수도 있다. 아래 값들은 ext 블럭으로 만들면 “안” 된다.

  • 자바 소스 인코딩 지정
    compileJava.options.encoding = 'UTF-8'
     
    // 혹은
    [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
  • 자바 언어 레벨 지정
    // project 단위
    sourceCompatibility = '1.6'
    targetCompatibility = '1.6'
     
     
    // compileJava 단위
    compileJava {
       sourceCompatibility = '1.6'
       targetCompatibility = '1.6'
    }
  • 컴파일러 옵션 지정
    compileJava.options.compilerArgs = ["-Xlint:unchecked", "-Xlint:deprecation", ...]
     
    // 혹은
    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
    }
  • define 사용하여 한번에 여러 CompileOptions options 지정
    compileJava.options.define(
      옵션1: 값,
      옵션2: 값, ...
    )

Test

테스트 실행

  • 테스트는 독립 JVM에서 격리상태로 실행된다.
  • test.debug 프라퍼티를 true로 설정하면 디버그모드로 실행되며 5005 포트로 디버깅할 수 있다.
  • 병렬 테스트
    • 여러 테스트 프로세스를 동시에 실행한 수 있다.
    • maxParallelForks 프라퍼티로 테스트 프로세스 갯수를 설정할 수 있다. 기본값은 1이다.(병렬 테스트 안함)
    • 테스트 프로세스는 org.gradle.test.worker 시스템 프라퍼티를 설정한다.
    • forkEvery 프라퍼티로 몇개의 테스트를 수행한뒤에 프로세스를 재시작 할지 정할 수 있다. 단위 테스트가 JVM Heap을 너무 많이 소모할 경우 이 값을 작게준다. 기본은 재시작 안함.
    • Gradle Goodness: Running Tests in Parallel
      test {
          if (project.hasProperty('maxParallelForks'))
              maxParallelForks = project.maxParallelForks as int
          if (project.hasProperty('forkEvery'))
              forkEvery = project.forkEvery as int
      }
  • ignoreFailures 프라퍼티는 테스트 실패시 행위를 정의한다. 기본값은 false이며 테스트가 실패하면 build를 실표로 표시한다. 단, 실패한 테스트에서 즉시 빌드를 멈추지는 않는다. true일 경우 테스트가 실패해도 멈추지 않고 다음으로 넘어가며 빌드를 진행하고 성공으로 표시한다.
  • failFast : true이면 테스트 실패건에서 즉시 빌드를 중단한다. 테스트 실행시 –fail-fast 옵션을 줘도 된다.
  • testLogging 프라퍼티는 테스트의 로깅 레벨을 설정한다. 기본적으로 모든 실패한 테스트에 대한 요약 메시지를 보여준다. TestLoggingContainer 참조.
    • 표준 출력/에러를 화면에 표시하려면 testLogging.showStandardStreams = true 설정 필요.

성공한 Test 강제 실행(force run test)

  • 성공한 테스트는 다시 테스트를 실행하면 실행이 안된다.
  • 이 때, cleanTest 태스크를 먼저 실행하고 테스트를 하면 된다.
    gradlew cleanTest test

System Properties

  • 시스템 프라퍼티는 gradle -D프라퍼티이름=값 형태로 지정한다.
  • taskName.single=testNamePattern 형태를 지정하면 testNamePattern에 일치하는 테스트만 실행된다.
  • taskName은 멀티프로젝트 패스 형태(:sub1:sub2:test)로 기술하거나 그냥 태스크 이름만 기술해도 된다.
  • testNamePattern**/testNamePattern*.class형태로 기술한다.
  • 패턴은 각 서버 프로젝트에 적용된다. 특정 서브 프로젝트에서 패턴에 매칭되는 테스트가 없으면 예외가 발생한다. 이 경우 패턴에 서브프로젝트를 명시할 수 있다.
gradle -Dtest.single=ThisUniquelyNamedTest test
 
gradle -Dtest.single=a/b/ test
 
gradle -DintegTest.single=*IntegrationTest integTest
 
gradle -Dtest.single=:proj1:test:Customer build
 
gradle -DintegTest.single=c/d/ :proj1:integTest

테스트 감지

  • Test 태스크는 컴파일된 클래스를 분석하여 테스트 클래스를 감지한다. 기본적으로 모든 *.class 파일을 분석한다.
  • 추상클래스는 실행 안한다.
  • 상위 클래스까지 모두 분석한다.
  • scanForTestClassesfalse로 하면 자동감지를 수행하지 않는다. 이 경우 명시적으로 포함/제외 시킨 클래스만 실행한다.
  • scanForTestClasses=false이면서 포함/제외 클래스를 명시하지 않으면 기본적으로 **/*Tests.class**/*Test.class를 실행하고, **/Abstract*.class는 제외한다.

JUnit

  • JUnit 3, 4 테스트 클래스
  • TestCase, GroovyTestCase 상속
  • @RunWith 어노테이션 적용
  • @Test 어노테이션을 가진 메소드가 있는 클래스

TestNG

  • @Test 어노테이션을 가진 메소드가 있는 클래스

테스트의 분리 - 소스셋이 동일하고 이름으로 구분 - 더이상 사용하지 말 것

  • *Test*IntegrationTest를 분리해서 실행하고자 하는 경우가 있을 수 있다.
  • includeexclude를 사용하고 Test를 상속하는 또 다른 태스크를 만들어 지정한다.
test {
    exclude '**/*IntegrationTest.class'
}
 
task integrationTest(type: Test, dependsOn: testClasses) {
    description = 'Integration test'
    group = 'verification'
 
    include '**/*IntegrationTest.class'
    testReportDir file("${buildDir}/reports/integration-test")
}
 
tasks.withType(Test) {
    // Test 들의 공통 설정
    useJUnit()
    maxHeapSize '2048m'
    jvmArgs '-XX:MaxPermSize=256m'
 
    testLogging {
        events 'started', 'passed'
    }
}

테스트의 분리 - 소스셋 분리 - 권장

// 별도 소스셋 구성
sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/integration-test/java')
        }
        groovy { // for Spock
            compileClasspath += main.output + test.output
             runtimeClasspath += main.output + test.output
            srcDir file('src/integration-test/groovy')
        }
        resources.srcDir file('src/integration-test/resources')
    }
}
 
// integrationTest 전용 configuration 지정.
// integrationTest에만 필요한 의존성 지정 가능.
 
configurations {
    integrationTestCompile.extendsFrom testCompile
    integrationTestRuntime.extendsFrom testRuntime
}
 
// Task 생성
task integrationTest(type: Test) {
    testClassesDirs = sourceSets.integrationTest.output.classesDirs // 구버전에서는 Dir 단수형으로만 지정됨.
    classpath = sourceSets.integrationTest.runtimeClasspath
    reports { // reports 는 원하는대로만.
        junitXml.enabled = true
        html.enabled = true
        ignoreFailures = true
    }
}
 
// 의존성 지정으로 check 실행시 자동 테스트
check.dependsOn integrationTest

TestSets Plugin 사용

Convention Values

태스크 프라퍼티 타입 기본값
testClassesDir File sourceSets.test.output.classesDir
classpath FileCollection sourceSets.test.runtimeClasspath
testResultsDir File testResultsDir
testReportDir File testReportDir
testSrcDirs List<File> sourceSets.test.java.srcDirs
jvmArgs List<String> [], 문자열 배열로 JVM 옵션을 지정한다.
maxHeapSize String null, '256m' 형태
systemProperty 키, 값 키, 값 쌍을 인자로 테스트 수행 JVM의 시스템 프라퍼티 지정
include String[] [], '**/*IntgrationTest.class', 'org/foo/**', …
exclude String[] [], '**/*IntgrationTest.class', 'org/foo/**', …

TestLogging

  • TestLoggingContainer
    test {
        testLogging {
            // set options for log level LIFECYCLE
            events "failed"
            exceptionFormat "short"
            showStandardStreams true
            // set options for log level DEBUG
            debug {
                events "started", "skipped", "failed"
                exceptionFormat "full"
            }
        }
    }

test 제외하기

  • build 등을 할 때 테스트를 실행하지 않으려면 gradle build -x test 처럼 -x test 옵션을 준다.

multi project 테스트 결과 모아보기

Creating a unit test report for subprojects

subprojects {
    apply plugin: 'java'
 
    // Disable the test report for the individual test task
    test {
        reports.html.enabled = false
    }
}
 
task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/allTests")
    // Include the results from the `test` task in all subprojects
    reportOn subprojects*.test
}

Test 완료후에 실패건이 있는지 마킹만 하기

  • ignoreFailures=true로 두고 테스트를 진행하고 빌드를 완료하지만, 실패건이 있는지 여부를 나중에 알고자 할 때
  • Gitlab CI 등에서 실패건이 있어도 후속 작업은 진행하기 위해서 만듬.
test {
    ignoreFailures = true
    afterSuite { TestDescriptor desc, TestResult result ->
        if (result.failedTestCount > 0) {
            rootProject.buildDir.mkdir()
            File testFailed = rootProject.file("${rootProject.buildDir}/testFailedMarker")
            if (!testFailed.exists()) {
                testFailed.createNewFile()
                testFailed.text = "이 파일이 존재하면 테스트중 실패한 건이 존재한다는 의미입니다."
            }
            logger.warn("testFailedMarker - {}", result.failedTestCount)
        }
    }
}
  • 다른 stage 에서 <project-root>/build/testFailedMarker 파일의 존재여부를 체크해서 존재하면 테스트 실패로 간주한다.
if [ -f "build/testFailedMarker" ]; then
    echo "file exists"
    exit 1
fi

Jar

  • jar 태스크는 프로젝트의 클래스와 리소스를 포함하는 JAR 파일을 생성한다.
  • 파일명 지정
    jar {
        archiveName = 'nameWhatIWant.jar'
    }

Manifest

  • 모든 jar 혹은 war 객체는 Manifestmanifest 프라퍼티가 있다.
  • 압축 파일이 생성될 때 MANIFEST.MF 파일이 함께 저장된다.
  • MANIFEST.MF 커스터마이징
    jar {
        manifest {
            attributes("Implementation-Title": "Gradle", "Implementation-Version": version)
        }
    }
  • 여러 jar에서 manifest 정보 공유
    ext.sharedManifest = manifest {
        attributes("Implementation-Title": "Gradle", "Implementation-Version": version)
    }
    task fooJar(type: Jar) {
        manifest = project.manifest {
            from sharedManifest
        }
    }
  • Manifest를 병합할 수 있다. 병합할 대상은 다른 Manifest 객체나 파일이 될 수 있다.
    task barJar(type: Jar) {
        manifest {
            attributes key1: 'value1'
            from sharedManifest, 'src/config/basemanifest.txt'
            from('src/config/javabasemanifest.txt', 'src/config/libbasemanifest.txt') {
                eachEntry { details ->
                    if (details.baseValue != details.mergeValue) {
                        details.value = baseValue
                    }
                    if (details.key == 'foo') {
                        details.exclude()
                    }
                }
            }
        }
    }
    • Manifest는 from절에 기술한 순서에 따라 병합된다.
    • 동일 키가 존재할 경우 이후에 병합된 manifest것이 우선한다.
    • eachEntry 를 통해 ManifestMergeDetails 객체를 받아서 조정 가능하다.
    • 병합은 jar 생성시점 혹은 writeTo 아니면 effectiveManifest가 호출되는 시점에 늦은 초기화 방식으로 수행된다.
  • manifest 기록
    jar.manifest.writeTo("$buildDir/mymanifest.mf")

JavaExec

Java 클래스를 실행할 때 Ant를 사용하는 방법JavaExec를 사용하는 방법이 있다. project.javaexec() 메소드를 호출해도 된다. javaexec 메소드는 Closure를 인자로 받는데 거기 들어가는 내용은 JavaExec 설정과 같다. How to use in gradle javaexec with classpath dependency

Gradle Application Plugin도 참조한다.

// 외부 의존성 지정 필요시
configurations {
   newConfForJavaexec
}
 
dependencies {
    newConfForJavaexec "xxxx:xxx:1.1"
    // ...
}
 
task someTask(type: JavaExec) {
    main = 'xxx.yyy.MainClass'
 
    // 외부 의존성의 Java 클래스 실행시
    classpath = configurations.newConfForJavaexec
 
    // 외부 jar가 아닌 현재 프로젝트의 Java 클래스 실행시 - 1번 방식
    classpath = configurations.runtime
    classpath += sourceSets.main.output
    // 외부 jar가 아닌 현재 프로젝트의 Java 클래스 실행시 - 2번 방식
    classpath = sourceSets.main.runtimeClasspath
 
    args '인자1', '인자2', .....
    systemProperty 'simple.message', 'Hello '
    jvmArgs '-Xmx512m'
}

System Properties 전달

Gradle을 통해 실행되는 Java Application에 Gradle의 System Properties를그대로 전달하기 - Gradle Goodness: Pass Java System Properties To Java Tasks

// The run task added by the application plugin
// is also of type JavaExec.
tasks.withType(JavaExec) {
// Assign all Java system properties from
// the command line to the JavaExec task.
    systemProperties System.properties
}
gradle/java.txt · 마지막으로 수정됨: 2022/06/30 16:36 저자 kwon37xi