Gradle
Gradle is a next-generation build tool, in my opinion, it will replace Maven and Ant.
Below is my build.gradle for one of my projects:
1 apply plugin: 'war' 2 // 'war' plugin will apply 'java' plugin automatically 3 apply plugin: 'java' 4 apply plugin: 'eclipse' 5 // run web application 6 apply plugin: 'jetty' 7 8 /** 9 * Gradle includes 2 phases: configuration and execution, refer to 10 * http://stackoverflow.com/questions/11558824/gradle-tar-task-not-executed. 11 * 12 * - CONFIGURATION PHASE 13 * In configuration phase, all codes except doFirst() and doLast() will be executed from top to bottom of the script. 14 * The 'dependsOn' doesn't make any sense in configration phase, for example, the 'jar' and 'svnrev' tasks, if we put 15 * 'svnrev' after 'jar', then variable 'svnrev.lastRev' can't be parsed at 'jar' task, as it completely hasn't been 16 * initilized at all. 17 * 18 * - EXECUTION PHASE 19 * In execution phase, the dependency mechanism of task will work. Be reminded that only doFirst() and doLast() will be 20 * executed at execution phase, and gradle will finished configuration of whose script first to initialize and determine 21 * what tasks should be executed and what is the execution order. 22 */ 23 24 logger.quiet(">> Start building of $_name.$version.") 25 /** 26 * SHIT, here you can't give a statement like 'compileJava.options.encoding = $_sourcecode_encoding', if do so, 27 * "Could not find property '$_sourcecode_encoding'" will be thrown out. '$_encoding' can't only be used in String? 28 */ 29 compileJava.options.encoding = _sourcecode_encoding 30 compileTestJava.options.encoding = _sourcecode_encoding 31 // Define a temporary variable. 32 //_tmp="define a temporary variable" 33 //logger.quiet(">> Define a temporary variable: _tmp: $_tmp") 34 35 // Properties added by the java plugin 36 sourceCompatibility="1.6" 37 targetCompatibility="1.6" 38 //Properties added by the war plugin 39 webAppDirName="src/main/WWW" 40 41 configurations { 42 provided { 43 description = 'Non-exported comiple-time dependencies.' 44 } 45 } 46 47 /** 48 * In Gradle dependencies are grouped into configurations, and there are 4 pre-defined configuration: 49 * compile, runtime, testCompile and testRuntime. In general dependencies of the later one will contain previous one. 50 */ 51 dependencies { 52 // configurationName dependencyNotation1, dependencyNotation2, ... 53 // compile group: 'commons-collections', name: 'commons-collections', version: '3.2' 54 55 provided files('lib/DEV/j2ee/servlet-api.jar') 56 compile fileTree(dir: 'lib', include: '**/*.jar', exclude: 'DEV/**/*.jar') 57 /** 58 * Below dependency will result in a exception: 59 * Circular dependency between tasks. Cycle includes [task ':compileJava', task ':classes']. 60 * As sourceSets.main.output is generated by task 'compileJava', however if we declare the dependency here, it means task 61 * 'compileJava' will depend on this file too, then a circular dependency occurs. 62 */ 63 //compile sourceSets.main.output 64 testCompile fileTree(dir:"lib", include:"DEV/**/*.jar") 65 } 66 67 sourceSets { 68 /** 69 * The Java plugin defines two standard source sets, called main and test. 70 * Changing the project layout, the default project layout is as below: 71 * - src/main/java Production Java source 72 * - src/main/resources Production resources 73 * - src/test/java Test Java source 74 * - src/test/resources Test resources 75 * - src/sourceSet/java Java source for the given source set 76 * - src/sourceSet/resources Resources for the given source set 77 * Refer to http://gradle.org/docs/current/userguide/java_plugin.html and 78 * http://gradle.org/docs/current/dsl/org.gradle.api.tasks.SourceSet.html for more information. 79 */ 80 main { 81 compileClasspath = compileClasspath + configurations.provided 82 //compileClasspath.collect().each({println it}) 83 resources { 84 srcDir 'src/main/resource' 85 } 86 } 87 test { 88 java { 89 srcDir 'src/test/unittest' 90 // integration test needs database, and need to import test data first. 91 srcDir 'src/test/integration' 92 } 93 resources { 94 srcDir 'src/test/resource' 95 } 96 } 97 } 98 99 // Retrieve the last revision of project, refer to http://stackoverflow.com/questions/9044354/checkout-svn-using-gradle. 100 task svnrev { 101 // use ant to retrieve revision. 102 ant.taskdef(resource: 'org/tigris/subversion/svnant/svnantlib.xml') { 103 classpath { 104 fileset(dir: 'lib/DEV/svnant-1.2.1', includes: '*.jar') 105 } 106 } 107 ant.svn(javahl: 'false', svnkit: 'true', username: "${_svn_user}", password: "${_svn_password}", failonerror: 'false') { 108 ant.info(target: "${_svn_source_url}", propPrefix: 'svninfo') 109 } 110 // retrieve property of ant project and assign it to a task's property, refer to: 111 // http://gradle.1045684.n5.nabble.com/can-t-find-or-extract-properties-from-svnant-info-function-in-gradle-td3335388.html 112 ext.lastRev = ant.getProject().properties['svninfo.lastRev'] 113 // retrieve property of gradle project 114 //getProject().properties['buildFile'] 115 } 116 117 import org.gradle.api.java.archives.internal.DefaultManifest 118 import org.gradle.api.internal.file.IdentityFileResolver 119 task generateManifest { 120 // define a task's property 121 ext.m = new DefaultManifest(new IdentityFileResolver()) 122 123 // add some attributes 124 m.attributes([ 125 'Implementation-Title':"$_name", 126 'Implementation-Version':"${version}_${svnrev.lastRev}", 127 'Implementation-Vendor':"$_company", 128 'Created-By' : _team, 129 'Build-Time' : new Date() 130 ]) 131 //manifest.writeTo('build/mymanifest.mf') 132 } 133 war.dependsOn 'generateManifest' 134 135 war { 136 archiveName = _name + ".war" 137 manifest = generateManifest.m 138 } 139 140 // Define a global variable 141 def user_tag 142 143 task svntag <<{ 144 def console = System.console() 145 if (console) { 146 user_tag = console.readLine("> Please enter your tag(${version}): ") 147 if (!user_tag) { 148 logger.error "Please give a tag definition." 149 System.exit(0) 150 } 151 } else { 152 logger.error "Cannot get console." 153 } 154 /** 155 * We must define below logic in doFirst/Last(), otherwise it will try to make a tag each time as it is in configuration phase. 156 */ 157 ant.svn(javahl: 'false', svnkit: 'true', username: "${_svn_user}", password: "${_svn_password}", failonerror: 'false') { 158 ant.copy(srcurl: "${_svn_source_url}", desturl:"${_svn_tag_url}/${user_tag}", message:"Create tag: ${_svn_tag_url}/${user_tag}") 159 } 160 } 161 162 task dist(type: Zip) { 163 description = "Build a distribution package containing war and shell script." 164 165 archiveName = _name + "_v${version}.zip" 166 167 // if use include, gradle will inform 'Skipping task ':zip' as it has no source files'...why? 168 // include 'config' 169 170 from('.') { 171 include 'README.txt' 172 include 'CHANGELOG.txt' 173 } 174 from war.destinationDir 175 into('bin') { 176 from('bin'){ 177 include 'app_backup.sh' 178 include 'gen-keypair.sh' 179 include 'gen-serialkey.sh' 180 } 181 } 182 from 'etc/manual' 183 184 doLast { 185 //print 'source of zip:' + project['zip'].source.each({println it}) 186 } 187 } 188 189
Grails
Grails is competing with Play!, however after trying a period time of scala, it makes me dismayed and indeed its learning curve is really hard. At present, I haven't even give Groovy a simple try, my only experience is gradle build script, what makes me dizzy is its closure. Maybe after put more effort to learn Groovy, those closures will be more friendly to me.
Grinder
A great distributed performance testing tool, at present it only support jython and closure. Python is my 2nd language, in fact just knew more than scala than groovy. I have found that someone also looking for the groovy supports of grinder, and has put real effort to implement it.