Using Gradle in IntelliJ IDEA for your build

I first came across the IntelliJ IDEA when I switched from Eclipse with an Android plugin to Android Studio for my Android development after it was announced at the Google I/O conference in May 2013.

Always one for standardisation and a sucker for upgrades. Show me a ‘Check for Updates’ and I’ll click it and install the upgrade. Something that Eclipse didn’t have at the time. I decided to standardise my Java and Android development on a single IDE and promptly purchased IntelliJ IDEA Ultimate edition.

My preferred choice for the deployment of EE applications onto an Application Server is an EAR file containing the JAR and WAR. IntelliJ Ultimate handles this superbly with ‘Artifacts’. Where you can define and create your WAR and JAR files with the classes, external JARs and configuration files and XHTML to include, then package the two into a single EAR. This is built in seconds from the click of the ‘Build Artifact’ drop-down.

After having had a poor experience with an early version of Maven at a mobile Telco in the Summer of 2006 I’d stuck with ANT as my build tool and ran it from Jenkins in my Continuous Integration environment.

Experiencing the power of Gradle, with its ‘Maven like features’ in Android Studio, where it is the default build tool it seemed sensible to follow my standardisation mantra and use Gradle for building my EARs. Afterall IntelliJ IDEA Ultimate has built-in support for Gradle.

To compile your project IntelliJ looks for the external JARs in the ‘Libraries’ section of ‘Project Settings’. Here you can add the JARs from either Java (from your local hard drive) or Maven, where it searches for them in the Maven Central Repository.

To create an Artifact go to the ‘Artifacts’ section of ‘Project Settings’, where you can create your WAR, JAR & EAR files.

To replicate the ‘Libraries’ part of the ‘Project Settings’ with Gradle you need to create a ‘dependencies’ tasks in your gradle.build.

This is my gradle.build file which adds all the required JARs to ‘Project Settings | Libraries’ through the dependencies task of Gradle.

Add this ‘gradle.build’ file to the root of your project. Note that it includes plugins for ‘static code checkers’.

plugins {
    id 'java'
    id 'war'
    id 'ear'
    id 'idea'

    // Static Code Checkers
    id 'checkstyle'
    id 'findbugs'
    id 'pmd'
    id 'org.sonarqube' version "2.6"
}

//defaultTasks 'assemble'

sourceCompatibility = 1.8

repositories {
    jcenter()
    mavenCentral()

    flatDir {
        dirs 'lib'
    }
}

checkstyle {
    toolVersion '8.11'
    configFile file("config/checkstyle/checkstyle.xml")
}

dependencies {
    // JUnit 5 (Jupiter)
    testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0', 'org.junit.vintage:junit-vintage-engine:5.1.0')
    compile 'org.junit.vintage:junit-vintage-engine:5.3.0-M1'

    compile group: 'javax.ejb', name: 'javax.ejb-api', version: '3.2'
    compile group: 'org.jboss.spec.javax.ejb', name: 'jboss-ejb-api_3.2_spec', version: '1.0.1.Final'
    compile group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.2.0'
    compile group: 'javax.inject', name: 'javax.inject', version: '1'

    compile group: 'javax.faces', name: 'javax.faces-api', version: '2.3'
    compile group: 'javax.enterprise', name: 'cdi-api', version: '2.0'
    compile group: 'org.hibernate', name: 'hibernate-core', version: '5.3.2.Final'
    compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.3.2.Final'
    compile group: 'org.hibernate', name: 'hibernate-commons-annotations', version: '3.2.0.Final'
    compile group: 'org.hibernate', name: 'hibernate-search-orm', version: '5.10.2.Final'
    compile group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: '3.6.0.Final'

    compile 'org.apache.httpcomponents:httpclient:4.5.6'
    compile 'org.apache.httpcomponents:httpcore:4.4.10'

    compile group: 'org.omnifaces', name: 'omnifaces', version: '3.1'
    compile group: 'org.primefaces', name: 'primefaces', version: '6.2.7'
    compile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.8.0'
    compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
    compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
    compile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.1'

    compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'

    providedCompile 'javax.ejb:javax.ejb-api:3.2'
    providedCompile 'org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.1.Final'
    providedCompile 'org.eclipse.persistence:javax.persistence:2.2.0'
    providedCompile 'javax.inject:javax.inject:1'

    providedCompile 'javax.faces:javax.faces-api:2.3'
    providedCompile 'javax.enterprise:cdi-api:2.0'
    providedCompile 'org.hibernate:hibernate-core:5.3.2.Final'
    providedCompile 'org.hibernate:hibernate-entitymanager:5.3.2.Final'
    providedCompile 'org.hibernate:hibernate-commons-annotations:3.2.0.Final'
    providedCompile 'org.hibernate:hibernate-search-orm:5.10.2.Final'
    providedCompile 'org.jboss.resteasy:resteasy-jaxrs:3.6.0.Final'

    //providedCompile 'org.omnifaces:omnifaces:3.1'
    //providedCompile 'org.primefaces:primefaces:6.2'

    providedCompile 'org.mongodb:mongo-java-driver:3.8.0'
    providedCompile 'com.google.code.gson:gson:2.8.5'
    providedCompile 'org.slf4j:slf4j-api:1.7.25'
    providedCompile 'javax.ws.rs:javax.ws.rs-api:2.1'

}

checkstyleMain {
    source = ['src/main/java']
}

findbugs {
    ignoreFailures = true
    toolVersion = "3.0.1"
    sourceSets = [sourceSets.main]
    reportsDir = file("build/reports/findbugs")
    effort = "max"
}

tasks.withType(FindBugs) {
    reports {
        xml.enabled false
        html.enabled true
    }
}

pmd {
    ignoreFailures = true
    reportsDir = file("build/reports/pmd")
    ruleSets = [
        'java-basic',
        'java-braces',
        'java-clone',
        'java-codesize',
        'java-comments',
        'java-controversial',
        'java-coupling',
        'java-design',
        'java-empty',
        'java-finalizers',
        'java-imports',
        'java-optimizations',
        'java-strictexception',
        'java-strings',
        'java-typeresolution',
        'java-unnecessary',
        'java-unusedcode'
    ]
}

tasks.withType(Pmd){
    reports{
        xml.enabled=true
        html.enabled=true
    }
}

task deleteFiles(type: Delete) {
    //project.logger.lifecycle('>>>>> 1 deleteFiles')

    delete fileTree('./src/main/application') {
        include '**/NOTiFYwell*.war'
        include '**/NOTiFYwell*.jar'
        include '**/NOTiFYwell*.ear'
    }
}


task NOTiFYwellWAR(type: War) {
    //project.logger.lifecycle('>>>>> 2 NOTiFYwellWAR')

    dependsOn deleteFiles

    archiveName 'NOTiFYwellWAR.war'

    webInf {
        from 'WEB-INF'
    }

    rootSpec.exclude("**/dto/*")
    rootSpec.exclude("**/ean/*")
    rootSpec.exclude("**/ejb/*")
    rootSpec.exclude("**/entity/*")
    rootSpec.exclude("**/filter/*")
    rootSpec.exclude("**/gson/*")

    rootSpec.exclude("**/model/*")

    // Exclude push PushEvent.class
    rootSpec.exclude("**/push/PushEvent.class")

    rootSpec.exclude("**/sqlite/*")
    rootSpec.exclude("**/tesco/*")
    rootSpec.exclude("**/webservices/*")

    rootSpec.exclude("**/NOTiFYwell*.jar")
    rootSpec.exclude("**/NOTiFYwell*.war")
}

task NOTiFYwellJAR(type: Jar) {
    //project.logger.lifecycle('>>>>> 3 NOTiFYwellJAR')

    dependsOn NOTiFYwellWAR

    archiveName 'NOTiFYwellJAR.jar'

    from ('./src/main/java') {
        include 'META-INF/**'
    }

    // Exclude
    rootSpec.exclude("**/jsf/IngredientBean.class")
    rootSpec.exclude("**/jsf/SliderViewBean.class")
    rootSpec.exclude("**/push/PushBean.class")

    from ('./build/classes/java/main') {
        include '*/**'
    }
}

task copyNOTiFYwellWAR(type: Copy) {
    //project.logger.lifecycle('>>>>> 4 copyNOTiFYwellWAR')

    dependsOn NOTiFYwellJAR

    from file('./build/libs/NOTiFYwellWAR.war')
        into file('./src/main/application')
}

task copyNOTiFYwellJAR(type: Copy) {
    //project.logger.lifecycle('>>>>> 5 copyNOTiFYwellWAR')

    dependsOn copyNOTiFYwellWAR

     from file('./build/libs/NOTiFYwellJAR.jar')
        into file('./src/main/application')
}

task NOTiFYwellEAR(type: Ear) {
    //project.logger.lifecycle('>>>>> 6 NOTiFYwellEAR')

    apply plugin: 'ear'

    dependsOn copyNOTiFYwellJAR

    archiveName 'NOTiFYwell.ear'

    manifest {
        from ('./src/main/resources/META-INF/MANIFEST.MF')
    }

    exclude '**/*.class'
    exclude '**/asm-5.2.jar'
    exclude '**/jboss-deployment-structure.xml'

    dependencies {
        earlib group: 'com.google.code.gson', name: 'gson', version: '2.8.5', ext: 'jar'
        earlib group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1', ext: 'jar'
        earlib group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6', ext: 'jar'
        earlib group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.4.10', ext: 'jar'
    }
}

test {
    //project.logger.lifecycle('>>>>> 7 useJUnitPlatform')
    useJUnitPlatform()

Once you add a gradle .build file to your project IntelliJ tells you that you have an “Unlinked Gradle Project” and do you want to “import it’.  Say yes.

From the command line run:

$ gradle clean build 

Your Gradle ‘Project Settings | Libraries’ will now look like this:

The Project Settings | Artifacts will look like this:

Then from the command line run:

$ gradle clean NOTiFYwellEAR 

In the <Your Project>/build/libs/ folder there will be the EAR:

Ready to be deployed through the WildFly Management Console.

Leave a Reply

Your e-mail address will not be published. Required fields are marked *