IntelliJ IDEA 2016.3 re-introduced the Grails view for Grails 3 applications. Grails 2 applications already were supported with a Grails view in IDEA. Using this view we get an overview of all the Grails artifacts like controller, services, views and more. We can easily navigate to the the class files we need. Now this view is also available for Grails 3 applications. To enable the view we must click on the view selector in the project view:
Continue reading →
In a previous post we learned how to create a class that extends RuleSource
with methods that define rules on how to create and change objects in the Gradle model space. With the model
configuration block in a build file we can also define creation rules for Rule based model configuration.
In the following build file we define a model
block and define a creation rule for creating the object versionInfo
of type VersionFile
. Also we add a new task to the tasks
object of type ModelMap<Task>
:
Continue reading →
Rule based model configuration in Gradle allows us to have a graph of objects with dependencies that are resolved by Gradle. To make this work Gradle needs to know about the object in this model space. The model space is populated with objects of our own and with objects from Gradle. At time of writing this blog post we can not interact with the Gradle Project
object in our rule based model configuration. It is not officially part of the model space. Probably in the future this might change and will the Project
object managed by Gradle be part of the model space. Which means we can use then a Project
object as input parameter for any rule methods we have. For now the official way to pass project information to the rule based model space is via the model
configuration block in our build script. The model
configuration block can be used to set properties on objects with values from our Project
object.
In the following example we have VersionFile
object that is part of the model space.
Continue reading →
Rule based model configuration gives Gradle more knowledge about the objects and their dependencies. This information can be used by Gradle to optimise the build process. We define rules on how we want Gradle to create objects and how we want to mutate objects in a class that extends RuleSource
. We can also add rules to validate objects available in the Gradle model space. We use the @Validate
annotation on methods that have validation logic. The first argument of the method is of the type of the object we want to validate. This type must be managed by Gradle.
In the following example we use the sample from a previous post. In this sample we have a VersionFile
class that is managed by Gradle. The class has a version
and outputFile
property. The version
must be set and must start with a v
. The outputFile
property is also required.
Continue reading →
Gradle 3.2 deprecates the <<
operator to add actions to a task. The <<
operator maps to the leftShift
method of a task. This operator confuses a lot people that are new to Gradle. Because without the operator we are configuring a task instead of adding actions. I can tell from experience the mistake is easily made. If we use the <<
in our build script with Gradle 3.2 we get a warning on the console. The warning message already mentions a solution: use the doLast
method to add actions.
In the following example build script we define the task deprecatedSample
using the <<
operator. The other task newSample
uses the doLast
method to add an action:
Continue reading →
When we use Rule based model configuration in our Gradle project we can give Gradle rules on how to manage objects from the model space. These rules are defined in a class that extends RuleSource
. When we want to set some default values for properties of a model object (in Gradle terms this is a subject) we can use the @Defaults
annotation. Rules annotated with @Defaults
are invoked right after the object is created and before any other methods that can mutate the state of the object.
The method, to set the default values, must have the type of the object as first parameter. Other parameters are considered input parameters and can be used to set a default value based on other model objects.
Continue reading →
Some time ago I went to a Meetup session “Death To Null” by Ties van de Ven from JDriven.
During the presentation it became clear that it wasn‘t so much about null checks and NullPointerExceptions but more about Immutability and how it can help keep your software free of bugs and NullPointerExceptions.
One of the statements that got me thinking was (something along the lines of): “Java chose the wrong default.
Instead of making everything explicitly final when we want an immutable variable, everything should be implicitly final unless the developer makes it explicitly mutable”.
Not knowing that much about the implementation of annotations I thought it would be fun to try to write an annotation which would do exactly that.
The first bump I encountered is that annotations cannot modify the programmers source code, or the classes generated from this source code; they can generate new sources or validate code.
This quickly turned my attention to project Lombok which does that already.
If you use project Lombok for the generation of getters and setters these never show up in your source code.
How can your IDE still hint at the existence of the getters and setters?
Continue reading →
We use the model
task to see which objects are available in the Gradle model space. The model spaced is managed by Rule based model configuration. Objects can be defined as hidden by the object author(s). By default a hidden object is not shown in the model report. We must use the task option --showHidden
to show also the hidden objects in the model report.
$ gradle -q model --showHidden
------------------------------------------------------------
Root project
------------------------------------------------------------
+ buildDir
| Type: java.io.File
| Value: /Users/mrhaki/Projects/sample/build
| Creator: Project..buildDir()
+ extensionContainer
| Type: org.gradle.api.plugins.ExtensionContainer
| Creator: Project..extensionContainer()
+ fileOperations
| Type: org.gradle.api.internal.file.FileOperations
| Creator: DefaultProject.BasicServicesRules#fileOperations(ServiceRegistry)
+ instantiator
| Type: org.gradle.internal.reflect.Instantiator
| Creator: DefaultProject.BasicServicesRules#instantiator(ServiceRegistry)
+ nodeInitializerRegistry
| Type: org.gradle.model.internal.core.NodeInitializerRegistry
| Creator: DefaultProject.BasicServicesRules#nodeInitializerRegistry(ModelSchemaStore, StructBindingsStore)
+ projectIdentifier
| Type: org.gradle.api.internal.project.ProjectIdentifier
| Value: root project 'versionrule'
| Creator: Project..projectIdentifier()
+ proxyFactory
| Type: org.gradle.model.internal.manage.instance.ManagedProxyFactory
| Creator: DefaultProject.BasicServicesRules#proxyFactory(ServiceRegistry)
+ schemaStore
| Type: org.gradle.model.internal.manage.schema.ModelSchemaStore
| Creator: DefaultProject.BasicServicesRules#schemaStore(ServiceRegistry)
+ serviceRegistry
| Type: org.gradle.internal.service.ServiceRegistry
| Value: ProjectScopeServices
| Creator: Project..serviceRegistry()
+ sourceDirectorySetFactory
| Type: org.gradle.api.internal.file.SourceDirectorySetFactory
| Creator: DefaultProject.BasicServicesRules#sourceDirectorySetFactory(ServiceRegistry)
+ structBindingsStore
| Type: org.gradle.model.internal.manage.binding.StructBindingsStore
| Creator: DefaultProject.BasicServicesRules#structBindingsStore(ServiceRegistry)
+ taskFactory
| Type: org.gradle.api.internal.project.taskfactory.ITaskFactory
| Creator: DefaultProject.BasicServicesRules#taskFactory(ServiceRegistry)
+ tasks
| Type: org.gradle.model.ModelMap | Creator: Project..tasks()
| Rules:
⤷ VersionFileTaskRules#createVersionFileTask(ModelMap, VersionFile)
+ buildEnvironment
| Type: org.gradle.api.tasks.diagnostics.BuildEnvironmentReportTask
| Value: task ':buildEnvironment'
| Creator: tasks.addPlaceholderAction(buildEnvironment)
| Rules:
⤷ copyToTaskContainer
+ components
| Type: org.gradle.api.reporting.components.ComponentReport
| Value: task ':components'
| Creator: tasks.addPlaceholderAction(components)
| Rules:
⤷ copyToTaskContainer
+ dependencies
| Type: org.gradle.api.tasks.diagnostics.DependencyReportTask
| Value: task ':dependencies'
| Creator: tasks.addPlaceholderAction(dependencies)
| Rules:
⤷ copyToTaskContainer
+ dependencyInsight
| Type: org.gradle.api.tasks.diagnostics.DependencyInsightReportTask
| Value: task ':dependencyInsight'
| Creator: tasks.addPlaceholderAction(dependencyInsight)
| Rules:
⤷ HelpTasksPlugin.Rules#addDefaultDependenciesReportConfiguration(DependencyInsightReportTask, ServiceRegistry)
⤷ copyToTaskContainer
+ dependentComponents
| Type: org.gradle.api.reporting.dependents.DependentComponentsReport
| Value: task ':dependentComponents'
| Creator: tasks.addPlaceholderAction(dependentComponents)
| Rules:
⤷ copyToTaskContainer
+ generateVersionFile
| Type: mrhaki.gradle.VersionFileTask
| Value: task ':generateVersionFile'
| Creator: VersionFileTaskRules#createVersionFileTask(ModelMap, VersionFile) > create(generateVersionFile)
| Rules:
⤷ copyToTaskContainer
+ help
| Type: org.gradle.configuration.Help
| Value: task ':help'
| Creator: tasks.addPlaceholderAction(help)
| Rules:
⤷ copyToTaskContainer
+ init
| Type: org.gradle.buildinit.tasks.InitBuild
| Value: task ':init'
| Creator: tasks.addPlaceholderAction(init)
| Rules:
⤷ copyToTaskContainer
+ model
| Type: org.gradle.api.reporting.model.ModelReport
| Value: task ':model'
| Creator: tasks.addPlaceholderAction(model)
| Rules:
⤷ copyToTaskContainer
+ projects
| Type: org.gradle.api.tasks.diagnostics.ProjectReportTask
| Value: task ':projects'
| Creator: tasks.addPlaceholderAction(projects)
| Rules:
⤷ copyToTaskContainer
+ properties
| Type: org.gradle.api.tasks.diagnostics.PropertyReportTask
| Value: task ':properties'
| Creator: tasks.addPlaceholderAction(properties)
| Rules:
⤷ copyToTaskContainer
+ tasks
| Type: org.gradle.api.tasks.diagnostics.TaskReportTask
| Value: task ':tasks'
| Creator: tasks.addPlaceholderAction(tasks)
| Rules:
⤷ copyToTaskContainer
+ wrapper
| Type: org.gradle.api.tasks.wrapper.Wrapper
| Value: task ':wrapper'
| Creator: tasks.addPlaceholderAction(wrapper)
| Rules:
⤷ copyToTaskContainer
+ typeConverter
| Type: org.gradle.internal.typeconversion.TypeConverter
| Creator: DefaultProject.BasicServicesRules#typeConverter(ServiceRegistry)
+ versionFile
| Type: mrhaki.gradle.VersionFile
| Creator: VersionFileTaskRules#versionFile(VersionFile)
| Rules:
⤷ versionFile { ... } @ build.gradle line 8, column 5
+ outputFile
| Type: java.io.File
| Value: /Users/mrhaki/Projects/sample/build/version.txt
| Creator: VersionFileTaskRules#versionFile(VersionFile)
+ version
| Type: java.lang.String
| Value: 1.0.1.RELEASE
| Creator: VersionFileTaskRules#versionFile(VersionFile)
$
Continue reading →
The Gradle model
task shows the objects in the model space of Gradle. The output shows the object hierarchy. By default a full report is shown, with a lot of information. We can customize the output format with the --format
task argument. The default value is full
, but we can also use the value short
. With the value short
a lot less information is shown.
Let's see the output of the model
task for a sample project:
Continue reading →