Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Gradle: The Better Build Tool

No description
by

John Hurst

on 28 January 2015

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Gradle: The Better Build Tool

Gradle: The Better Build Tool
Concepts
Basics
A Java project
Gradle Advantages
Use standard build conventions
But change what you need to
Customize with Groovy scripting
But don't get carried away
Java Build Tools
Flexible
Easy to understand
Lots of 3rd-party tool support

Too much boilerplate
Lack of standardization
Procedural
Standardized
Convention over Configuration
Declarative
Dependency Management
Some 3rd-party too support
Hard to understand
Inflexible
Somewhat verbose (XML)
Standardized
Flexible
Powerful
Elegant
Declarative (DSL)
Project
Task
Dependency
Configuration
Repository
Plugin
Recipes
Publish test artifacts for sharing in other (sub)projects
Use common version numbers
Customize JAR
Use arbitrary Java code
repositories {
mavenCentral()
mavenLocal()
jcenter()
}
apply plugin: 'java'

group = 'org.myorg'
version = '1.0'

repositories {}

configurations {}

dependencies {}

subprojects {}
Language Plugins
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'scala'
IDE Plugins
apply plugin: 'eclipse'
apply plugin: 'idea'
Deployment/Packaging Plugins
apply plugin: 'war'
apply plugin: 'jetty'
apply plugin: 'application'
apply plugin: 'ear'
Reporting Plugins
apply plugin: 'checkstyle'
apply plugin: 'codenarc'
apply plugin: 'findbugs'
apply plugin: 'jacoco'
apply plugin: 'jdepend'
apply plugin: 'pmd'
apply plugin: 'sonar'
task distDdlZip(type: Zip, dependsOn: createDdl) {
classifier = 'src'
appendix = 'ddl'
into('sql') {
from 'build/ddl/owner','build/ddl/user'
}
String fullVersion = version.replaceAll( "-SNAPSHOT","")
into('sql') {
from ("src/main/sql/migrate") {
include "update_${fullVersion}.sql"
include "update_${fullVersion}_user.sql"
include "update_${fullVersion}_read.sql"
}
}
}

configurations {
antClasspath
compileGwt.extendsFrom compile
developmentGwt.extendsFrom compileGwt
}

dependencies {
runtime "postgresql:postgresql:$postgresqlVersion"

runtime files("lib/schemaSpy_5.0.0.jar")

compile project(":myproject-domain")
}

configurations {
myextra
}

task configs << {
configurations.each {println it}
}
class Mytask extends DefaultTask {
String foo
}

task mytask(type: Mytask)

mytask {
foo = 'one'
}

mytask << {
println foo
}
Compile all source with groovyc
sourceSets {
main {
java { srcDirs = [] }
groovy { srcDir "src/main/java" }
}
}

Extend configurations with new entry
configurations {
provided
}

dependencies {
provided "javax.servlet:javax.servlet-api:$javaxServletVersion"
// ...
}

sourceSets {
main { compileClasspath += configurations.provided }
test {
compileClasspath += configurations.provided
runtimeClasspath += configurations.provided
}
}

idea.module.scopes.PROVIDED.plus += [configurations.provided]

configurations {
tests
}

task testJar(type: Jar, dependsOn: testClasses) {
baseName = "${project.archivesBaseName}-test"
from sourceSets.test.output
}

artifacts {
tests testJar
}

subprojects {
project.ext {
commonsCollectionsVersion = "3.2"
commonsIoVersion = "1.4"
commonsLangVersion = "2.5"
ehcacheVersion = "2.4.7"
groovyVersion = "2.3.7"
hibernateVersion = "3.6.6.Final"
junitVersion = "4.10"
logbackVersion = "1.0.9"
servletApiVersion = "3.0.1"
slf4jVersion = "1.7.2"
springVersion = "4.0.2.RELEASE"
}
}

dependencies {
compile "org.springframework:spring-core:$springVersion"
}
jar {
def buildString = version + " built on " +
new Date().format("yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("Australia/Melbourne"))
manifest {
attributes(
"Built-By": System.properties["user.name"],
"Implementation-Title": project.name,
"Implementation-Version": buildString
)
}
}

dependencies {
compile "org.antlr:antlr:$antlrVersion"
}

task(antlr, type: JavaExec) {
main = "org.antlr.Tool"
classpath = sourceSets.main.runtimeClasspath
args = [
'-o src/main/java/myproject/lang',
'src/main/java/myproject/lang/EqlQuery.g',
'src/main/java/myproject/lang/EqlQueryWalker.g'
]
}

dependencies {
runtime "postgresql:postgresql:$postgresqlVersion"
runtime files("lib/schemaSpy_5.0.0.jar")
}

class SchemaSpyTask extends DefaultTask {
String driver = "org.postgresql.Driver"
String host = project.property("db.serverName")
String database = project.property("db.databaseName")
String user = project.property("db.user")
String password = project.property("db.password")
String schema = project.property("db.schema")

@TaskAction
def run() {
project.javaexec {
main = "net.sourceforge.schemaspy.Main"
maxHeapSize = "2048m"
classpath = project.configurations.runtime
args = [
"-t", "pgsql",
"-host", host,
"-db", database,
"-u", user,
"-p", password,
"-s", schema,
"-o", "build/schemaspy",
"-hq"
]
}
}
}

task schemaspy(type: SchemaSpyTask)

Utilise Ant
class SqlTask extends DefaultTask {
String script
String onerror = "abort"

@TaskAction
def run() {
ant.sql(
driver: "org.postgresql.Driver",
url: project.property("db.url"),
userid: project.property("db.user"),
password: project.property("db.password"),
onerror: onerror
) {
classpath(path: project.configurations.runtime.asPath)
fileset(dir: "src/main/resources/ddl", includes: script)
}
}
}

task createAll(type: SqlTask) {
script = "create_all.sql"
}

task dropAll(type: SqlTask) {
script = "drop_all.sql"
onerror = "continue"
}

task deleteSchemaData(type: SqlTask) {
script = "delete_schema_data.sql"
}

configurations {
antBuild
other
}

dependencies {
// ...
antBuild "com.oracle:ojdbc6:$oracleVersion"
// ...
}

ant.properties["foo"] = "bar"
ant.path(id: "classpath.build", path: configurations.antBuild.asPath)
ant.importBuild "build.xml"


...

build.xml:

<project>
<target name="runSql">
<sql> ... </sql>
</target>
...
</project>
Adding Dependencies
Adding Tests
Tweaking the Project
// build.gradle:

apply plugin: 'java'

// project structure:

simple-java
├── build.gradle
└── src
└── main
└── java
└── Library.java
apply plugin: 'java'

repositories {
jcenter()
}

dependencies {
compile 'org.slf4j:slf4j-api:1.7.7'
runtime 'org.slf4j:slf4j-simple:1.7.7'
}
dependencies {
testCompile 'junit:junit:4.11'
}

simple-tests
├── build.gradle
└── src
├── main
│   └── java
│   └── Library.java
└── test
└── java
└── LibraryTest.java
dependencies {
testCompile "org.concordion:concordion:$concordionVersion"
}

sourceSets {
test {
groovy {
srcDir "src/specs/groovy"
}
resources {
srcDir "src/specs/resources"
}
}
}

test {
systemProperties "concordion.output.dir": "build/concordion"
}

The Gradle Wrapper
Multimodule
// settings.gradle:
include "multimodule-domain",
"multimodule-service-api",
"multimodule-service-impl"
multimodule
├── build.gradle
├── multimodule-domain
│   └── src
│   └── main
│   └── java
│   └── Domain.java
├── multimodule-service-api
│   ├── build.gradle
│   └── src
│   └── main
│   └── java
│   └── Service.java
├── multimodule-service-impl
│   ├── build.gradle
│   └── src
│   └── main
│   └── java
│   └── ServiceImpl.java
└── settings.gradle
wrapper {
gradleVersion = "2.2"
}
function gw() {
[ -x ./gradlew ] && ./gradlew $@
[ -x ../gradlew ] && ../gradlew $@
}

Configuration
~/.gradle/init.gradle
~/.gradle/init.d/*.gradle
def redrepo = "file:///Users/jhurst/repo-local"

beforeProject {p ->
p.repositories {
mavenLocal()
maven {
name = "local"
url redrepo
}
maven {
name = "artifactory"
url "http://artifactory/all"
credentials { ... }
}
}
}

Lifecycle
Plugins
duplicate-classes
├── build.gradle
└── src
├── main
│   ├── groovy
│   │   ├── DuplicateClasses.groovy
│   │   ├── DuplicateClassesPlugin.groovy
│   │   ├── DuplicateClassesTask.groovy
│   └── resources
│   └── META-INF
│   └── gradle-plugins
│   └── duplicateClasses.properties
└── test
└── groovy
   └── DuplicateClassesTest.groovy

import org.gradle.api.Plugin
import org.gradle.api.Project

class DuplicateClassesPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('duplicateClasses', type: DuplicateClassesTask)
}
}
implementation-class = DuplicateClassesPlugin
(don't forget demo!)
(there is a demo for this, too!)
(yup, another demo!)
(it wouldn't be the same without a demo!)
(haven't had a demo for a little while!)
(but wait, there's more!)
(time for another demo!)
(you guessed it, demo time!)
(you can't really mean to have a demo of this!?)
(last but not least, the demo!)
wrapper-project
├── build.gradle
├── gradle
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
Full transcript