What's the best way to add behaviour to an existing task?

I’d like to integrate JavaScript file concatenation and minification as part of my java war project build and I’d appreciate some pointers on the best way to do this.

In the java plugin I understand that it is the processResources task that copies the files over from the sources to the build and I know how to concatenate and minify the files as a separate task but what I’m a bit stuck on is how I can prevent the copying of the *.js file as part of processResources and also do the concatenation+minification as part of a regular build.

Hi, to prevent the copying of the js files in the processResources task, you need to add an "exclude " to the processResources task:

processResources {
      exclude '**/*.js'
}

Now you can add a doLast section to the processResources task, that takes care of the concatenation and magnification of your js files:

processResources {
      exclude '**/*.js'
      doLast{
        //do some concatenation and minification
      }
}

To avoid further issues, ensure that the output directory of this is the same as the output folder of the processResources task.

regards, René

Thanks for that it puts me on the right track.

My mistake though I see it’s actually the war task that copies my JavaScript files from the webapp dir, however the war task doesn’t seem to have a staging area where I can copy the minified files to so they will get incorporated in to the resulting war.

How would I go about accomplishing this?

In that case I would suggest to create an extra task for tweaking your js sources. After you’ve created that task you can modify the given war task to ignore your js folder and add a from clause, that takes the output of your jstweaking task:

class JsTweak extends DefaultTask{
   @InputDirectory inputFolder;
 @OutputDirectory outputFolder;
     @TaskAction
 public void doTweak(){
  //do some js minimization and optimization
 }
}
  task tweakJs(type:JsTweak){
 inputFolder = file("$webAppDirName/js")
 outputFolder = file("$buildDir/tweakedJs")
}
  war {
 exclude '**/js'
 from tweakJs{
  into("js")
 }
}

hope that helps

Another even more concise solution might be to extend your JsTweak Task from SourceTask. This task type provides some convenient methods for dealing with sources. Have a look at javadoc:org.gradle.api.tasks.SourceTask for further information. If you have any further questions, don’t hesitate to ask.

regards, René

Thank you, that’s most helpful!

I’m nearly there, just one last thing, the following copies all of my webapp files into the ‘js’ directory and not just the output of jsMini. How do I keep the defaults for all files except the jsMini output?

war {
  exclude '**/js/*'
  from jsMini {
    into("js")
  }
}

hmm, can you try it again with putting the jsMini in parentheses:

war {
  exclude '**/js/*'
  from (jsMini) {
    into("js")
  }
}

If that does’'t work, it would be helpful if you can share your jsMini task implementation.

regards, René

That works :slight_smile: Here’s the implementation for reference:

  buildscript {

 dependencies {



classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'

 }  }

 task jsMini(type: CatPack) {

 inputFolder = file("src/main/webapp/js")

 outputFile = file("$buildDir/jsmin/modules.min.js")  }

 class CatPack extends DefaultTask {

 @InputDirectory

 File inputFolder;



@OutputFile

 File outputFile;



@TaskAction

 public void doCatPack() {



def fw = new FileWriter(outputFile)



inputFolder.eachFileMatch(~/.*\.js/) { File file ->



  def c = new JavaScriptCompressor(file.newReader(), new SystemOutErrorReporter())



  // 0 = line breaks after each rule, -1 = no line breaks



  c.compress(fw, -1, false, false, false, false)



}



fw.flush()



fw.close()

 }  }  

I am trying to take the class CatPack extends DefaultTask and add it to my build.gradle and I cannot get this to run:

* What went wrong:
    Could not compile build file 'C:\usr\SYNCH\PACKT166\Chapters_Code\build.gradle'.
    Cause: startup failed:
    build file 'C:\usr\SYNCH\PACKT166\Chapters_Code\build.gradle': 664: unable to resolve class JavaScriptCompressor
     @ line 664, column 21.
                   def c = new JavaScriptCompressor(file.newReader(), new SystemOutErrorReporter())
                           ^

I originally did not add:

buildscript {

dependencies {

classpath group: ‘com.yahoo.platform.yui’, name: ‘yuicompressor’, version: ‘2.4.6’

}

}

This was because I have a multi-module build I am covertiing from maven so I have several war’s in one script.

I then ended up with this

allprojects {
    apply plugin: 'java'
    apply plugin: 'groovy'
    ...
    repositories {
        mavenLocal()
        mavenCentral()
    }
}
  subprojects {
    configurations.compile.transitive = true
// Make sure transitive project dependencies are resolved.
    dependencies { // more dependencies for each module project}
      }
  classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'
  configurations {
    tools
}
  dependencies {
    tools files('/libs/yuicompressor-2.4.8pre.jar')
    tools 'com.tidyslice:YUICompressorPlugin:0.1-SNAPSHOT'
}
  project('ch03') {/*war*/}
  buildscript {
      dependencies {
        classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'
    }
}
task jsMini(type: CatPack) {...}
class CatPack extends DefaultTask {...}

But I still get this error:

20:20:33.723 [ERROR] [org.gradle.BuildExceptionReporter] Could not find group:com.yahoo.platform.yui, module:yuicompressor, version:2.4.6.
20:20:33.723 [ERROR] [org.gradle.BuildExceptionReporter] Required by:
20:20:33.733 [ERROR] [org.gradle.BuildExceptionReporter]
   :Chapter_Code:unspecified
20:20:33.743 [ERROR] [org.gradle.BuildExceptionReporter]
20:20:33.743 [ERROR] [org.gradle.BuildExceptionReporter] * Exception is:
20:20:33.753 [ERROR] [org.gradle.BuildExceptionReporter] org.gradle.api.internal.artifacts.ivyservice.ModuleVersionNotFoundException: Could not find group:com.yahoo.platform.yui, module:yuicompressor, version:2.4.6.

Any help would be greatly appreciated.

Looks like you are missing ‘repositories {…}’ within the ‘buildscript’ block.

I added the ropo but still get this issue:

05:50:34.559 [ERROR] [org.gradle.BuildExceptionReporter] build file 'C:\usr\SYNCH\PACKT166\Chapters_Code\build.gradle': 651: unable to resolve class JavaScriptCompressor
    05:50:34.575 [ERROR] [org.gradle.BuildExceptionReporter] build file 'C:\usr\SYNCH\PACKT166\Chapters_Code\build.gradle': 651: unable to resolve class SystemOutErrorReporter

I then noticed that com.yahoo.platform.yui:yuicompressor was not in my maven local repo

When I navigated to my .gradle artifact repo, it lives there, but keeps downloading one that is 0kb and I have tried several times to delete this. C:\Users\mknuts6173c.gradle\caches\artifacts-7\artifacts\56865c09425cc6ecda8606d7e6035ceb\com.yahoo.platform.yui\yuicompressor\2.4.6\jar

But that seems to be a link to another file 5b8477e867040ba58b6c8a7ac6deb6da22109237 which is the same 82k as the one that should be in the mvnrepo.

I also cannot seem to figure out how to force gradle to download this artifact as I have it listed. Why wont the jar’s download into my mavenLocal ?

Here is the new bottom section :

classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'
  buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'
    }
}
task jsMini(type: CatPack) {
    inputFolder = file("src/main/webapp/js")
    outputFile = file("$buildDir/jsmin/modules.min.js")
}
  import com.yahoo.platform.yui.compressor.JavaScriptCompressor
  class CatPack extends DefaultTask {
    @InputDirectory
    File inputFolder;
    @OutputFile
    File outputFile;
    @TaskAction
    public void doCatPack() {
        def fw = new FileWriter(outputFile)
        inputFolder.eachFileMatch(~/.*\.js/) { File file ->
            def c = new JavaScriptCompressor(file.newReader(), new SystemOutErrorReporter())
            // 0 = line breaks after each rule, -1 = no line breaks
            c.compress(fw, -1, false, false, false, false)
        }
        fw.flush()
        fw.close()
    }
}

To answer one of your question, Gradle never downloads anything into the local Maven repository, but always into its own cache.

When I navigated to my .gradle artifact repo, it lives there, but keeps downloading one that is 0kb and I have tried several times to delete this.

C:\Users\mknuts6173c.gradle\caches\artifacts-7\artifacts\56865c09425cc6ecda8606d7e6035ceb\com.yahoo.platform.yui\yuicompressor\2.4.6\jar

Could it be 0KB because it’s just a link?

What’s the first line about?

The build script looks weird. Is there a problem with how it’s rendered in the forum?

This works fine for me:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'com.yahoo.platform.yui', name: 'yuicompressor', version: '2.4.6'
    }
}
  import com.yahoo.platform.yui.compressor.JavaScriptCompressor
  task doit << {
    println(new Object() instanceof JavaScriptCompressor)
}

If you still need help with this, please start a new topic.