Custom gradle task classes: is there a "post-construction" hook? - gradle

Is there some sort of "post-construction hook" available on custom task classes, so I can call methods like inputs and outputs in class-specific logic?
Let's say I'm defining a custom Gradle task class like
class ExampleTask extends DefaultTask {
def exFile = null
}
Now, I'd like to instantiate it via
task('ex', type: ExampleTask) {
exFile = file("some-example.json")
}
... and I'd like to automatically run the equivalent of inputs(exFile) on the instance. Where does the logic go to handle this kindof configuration? I see that I could add an #InputFiles decorator on a method in my custom task class, like
#InputFiles
def getFiles(){
file(exFile)
}
... but this doesn't seem very general. I'd rather just use the existing inputs() functionality, rather than rewriting portions of it. But I can't figure out where to call it from.

If necessary, you can do these initializations in the zero-argument constructor of the task class. Default property values are often set by a plugin (especially if a default value depends on information from outside the task class). Input/output annotations should be preferred over the input/output API. (The latter exists for ad-hoc tasks that don't have their own task class.)

I need the exact same thing, and to my understanding, the answers are more or less - no, that is currently not possible.
See https://discuss.gradle.org/t/custom-task-with-extensions/12491

Related

gradle DSL to api: how translation from DSL to class method call is done?

I'm trying to understand deeply how gradle is working.
Let's take the case of a basic dependencies {} declaration in a build.gradle script.
dependencies is a method on Project object.
DSL Project object = org.gradle.api.Project interface:
void dependencies​(Closure configureClosure)
Configures the dependencies for this project.
This method executes the given closure against the DependencyHandler for this project. The
DependencyHandler is passed to the closure as the closure's delegate.
So: method receives as parameter a configuration closure and establish that closure's delegate object is DependencyHandler class, than execute the closure against it's delegate object.
Having this example:
dependencies {
// configurationName dependencyNotation
implementation 'commons-lang:commons-lang:2.6'
}
This is translated in a call of method add of DependencyHandler class:
Dependency add​(String configurationName, Object dependencyNotation) Adds a dependency to the given configuration.
And now the question:
How exactly is done the translation of the line
implementation 'commons-lang:commons-lang:2.6'
into a class method call (e.g. DependencyHandler.add()) and who is responsable ?
My impression is that there is a missing explanation in the documentation, something like: default method on this delegate object DependencyHandler is add(...), so each configClosure's line, if matching notation configurationName dependencyNotation, will be translate into delegate's object default method.
But this is just a possible interpretation.
Ideea is: I give a closure with multiple lines, this is executed agains a delegation object which happens to have methods add(), and magically for each line this method is called ... how is this happening, based on what mechanism ? Is the Project.dependencies() method doing this, is the delegate object itself, or some other groovy specific mechanisms, etc.
Thank you.
If you want to get deeper insight on how Gradle (or its DSL) work under the hood, you can always check the actual source code. However, since this is not required to understand how to write build scripts, it is not included in the documentation.
Regarding your specific example, I have to admit that I do not exactly know how it is done, but I have a guess. If someone else has better insights, feel free to prove me wrong.
While Gradle indeed uses AST transformations to extend the regular Groovy syntax in some cases (e.g. the task definition syntax), I think they just rely on dynamic methods for dependency definitions.
Groovy is a dynamic language. This includes a method called methodMissing that may be defined by any class and will be called whenever a missing method is called on an object of that class:
class Example {
def methodMissing(String name, args) {
println name
}
}
def example = new Example()
example.method1()
You can find a more detailed example in Mr. Hakis blog.
Since Groovy allows omitting parentheses for method calls with arguments, your example implementation 'commons-lang:commons-lang:2.6' is basically nothing else but calling the method implementation with the dependency notation string as its argument.
Now Gradle could catch these calls via methodMissing and then call DependencyHandler.add() if the configuration actually exists. This allows you to dynamically add configurations in your build script:
configurations {
myConfig
}
dependencies {
myConfig 'commons-lang:commons-lang:2.6'
}

what does this closure looking code in groovy means?

I am experimenting with some gradle at a new project, and in its settings.gradle, file I see these few lines that I am unable to make sense of as to what groovy structure or a language feature it is and what it does and how it works:
plugins {
id "com.gradle.build-scan" version "1.12.1"
id "cz.malohlava" version "1.0.3"
}
buildScan {
server = "some.host.com"
publishAlways()
}
I was suspecting it was either a a closure or an interface of some sort, but could not make head or tail of it.
Any help in understanding following will be a great help:
what it does?
How plugins and buildScan works here from the language's perspective?
From the language perspective, the closures are executed in the context of another objects than the build script. This is called delegation in Groovy.
http://groovy-lang.org/closures.html#_delegation_strategy
plugin delegates to https://docs.gradle.org/current/dsl/org.gradle.plugin.use.PluginDependenciesSpec.html
buildScan delegates to Build Scan Plugin's extension object which configures the plugin.
There may be some trickery here that I don't understand, particularly as I can't find either plugins() or buildScan() in the API docs. Nonetheless, the following is a reasonable reading of what the syntax means.
plugins {} and buildScan {} are both methods that take a closure (see other answers for explanation of this) as an argument.
Each closure has a delegate object of a particular type that's different depending on the method using the closure, i.e. the delegate of plugins() will be of a different type to the delegate of buildScan()
Within the closure, unqualified methods and properties will be executed against the delegate object. So for the plugins {} block, id(...).version(...) will be called against its delegate. For buildScan {}, you're setting the property server on the delegate and calling its publishAlways() method.
Honestly, I don't know how useful the above information is for using and understanding Gradle, but I think it's what you're asking for. Hope it helps!

How to make afterInsert / afterUpdate GORM method an async methods

Grails users know that Data access layer of this framework offer an AOP programming via seperation cross-layer from other soft layers : afterInsert, afterUpdate,beforeInsert .... methods .
class Person{
def afterInsert(){
//... Will be executed after inserting record into Person table
}
}
I search on the type of this methods vis-a-vis Constructor(instantiation ): Asynchronous or not . And i don't find the answer .
My question : if not, Does GORM will be breaked if we force those methods to be asynchronous.
UPDATE :
Indeed, we want send mails without using a ready plugin as we have our own API.
There are a great number of ways to accomplish what you are looking for, and without knowing all your requirements it's difficult to give you a solution that meets all of them. However, based on your question and the comments provided you could use the built in Asynchronous features in Grails to accomplish this.
This is just a sketch/example of something I came up with off the top of my head.
import static grails.async.Promises.*
class Person {
...
def afterUpdate() {
def task1 = task {
// whatever code you need to run goes here.
}
onComplete([task1]) {
// anything you want to run after the task completes, or nothing at all.
}
}
...
}
This is just one option. Again, there are a lot of options available to you. You could send a JMS message instead and have it processed on a different machine. You could use some type of eventing system, you could even use Spring AOP and Thread pools and abstract this even further. It depends on what your requirements are, and what your capabilities are as well.

How to run the same class multiple times?

I have a puppet module which deploys a JAR file and writes some properties files (by using ERB templates).
Recently we added a "mode" feature to the application, meaning the application can run in different modes depending on the values entered in the manifest.
My hierarchy is as follows:
setup
*config
**files
*install
Meaning setup calls the config class and the install class.
The install class deploys the relevant RPM file according to the mode(s)
The config class checks the modes and for each mode calls the files class with the specific mode and directory parameters, the reason for this structure is that the value of the properties depends on the actual mode.
The technical problem is that if I have multiple modes in the manifest (which is my goal) I need to call the files class twice:
if grep($modesArray, $online_str) == [$online_str] {
class { 'topology::files' :
dir => $code_dir,
mode => $online_str
}
}
$offline_str = "offline"
$offline_suffix = "_$offline_str"
if grep($modesArray, $offline_str) == [$offline_str] {
$dir = "$code_dir$offline_suffix"
class { 'topology::files' :
dir => $dir,
mode => $offline_str
}
However, in puppet you cannot declare the same class twice.
I am trying to figure out how I can call a class twice or perhaps a method which I can access its parameters from my ERB files, but I can't figure this out
The documentation says it's possible but doesn't say how (I checked here https://docs.puppetlabs.com/puppet/latest/reference/lang_classes.html#declaring-classes).
So to summarize is there a way to either:
Call the same class more then once with different parameters
(Some other way to) Create multiple files based on the same ERB file (with different parameters each time)
You can simply declare your class as a define:
define topology::files($dir,$mode){
file{"${dir}/filename":
content=> template("topology/${mode}.erb"),
}
}
That will apply a different template for each mode
And then, instantiate it as many times as you want:
if grep($modesArray, $online_str) == [$online_str] {
topology::files{ "topology_files_${online_str}" :
dir => $code_dir,
mode => $online_str
}
}
$offline_str = "offline"
$offline_suffix = "_$offline_str"
if grep($modesArray, $offline_str) == [$offline_str] {
$dir = "$code_dir$offline_suffix"
topology::files{ "topology_files_${online_str}" :
dir => $dir,
mode => $offline_str
}
Your interpretation of the documentation is off the mark.
Classes in Puppet should be considered singletons. There is exactly one instance of each class. It is part of a node's manifest or it is not. The manifest can declare the class as often as it wants using the include keyword.
Beware of declaration using the resource like syntax.
class { 'classname': }
This can appear at most once in a manifest. Parameter values are now permanently bound to your class. Your node has chosen what specific shape the class should take for it.
Without seeing the code for your class, your question makes me believe that you are trying to use Puppet as a scripting engine. It is not. Puppet only allows you to model a target state. There are some powerful mechanics to implement complex workflows to achieve that state, but you cannot use it to run arbitrary transformations in an arbitrary order.
If you add the class code, we can try and give some advice on how to restructure it to make Puppet do what you need. I'm afraid that may not be possible, though. If it is indeed necessary to sync one or more resources to different states at different times (scripting engine? ;-) during the transaction, you should instead implement that whole workflow as an actual script and have Puppet run that through an exec resource whenever appropriate.

How to declare dependencies of a Gradle custom task?

If I've created a custom task:
class MyTask extends DefaultTask {
...
}
I can at another time create an instance and declare dependencies:
task(["type": MyTask, "dependsOn": importantThing], "MyTaskName")
However, it seems a bit weird to separate the task definition from the declaration of dependencies. That is, it seems like everything defining the task should be in one place, or else it would be easy to instantiate the task without the right dependencies. Is there some better way to do this?
Tasks should be generic and self-contained. They should only operate on their own input properties, and should not assume existence of other tasks. Declaring tasks and their dependencies is the responsibility of build scripts and/or plugins.

Resources