Posts by Hubert Klein Ikkink

Gradle Goodness: Show Hidden Model Objects

Posted on by  
Hubert Klein Ikkink

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 →

Gradle Goodness: Get Model Report In Short Format

Posted on by  
Hubert Klein Ikkink

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 →

Gradle Goodness: Adding Task With Rule Based Model Configuration

Posted on by  
Hubert Klein Ikkink

Gradle has an incubating feature Rule based model configuration. This is a new way to configure Gradle projects where Gradle has more control of the configuration and the dependencies between configuration objects. This allows Gradle to resolve configuration values before they are used, because Gradle knows there is a dependency. With this new model we don't need any lazy evaluation "tricks" we had to use. For example there was an internal convention mapping mechanism for tasks to assign values to a task configuration after the task was already created. Also the project.afterEvalute is a mechanism to have late binding for task properties. With the new rule based model Gradle can do without these options, we can rely on Gradle resolving all dependent configuration values when we create a task.

In Gradle we already know about the "project space" where the Project object is the root of the object graph. For example repositories are part of the project space. Gradle can get some useful information from the project space, but it is mostly a graph of objects that Gradle only partially can reason about. Then we have the "model space". This is part of a project and we can use it in our build script with the model configuration block. The model space is separate from the project space and contains objects that are managed by Gradle. Gradle knows dependencies between the objects and how to create and change them. This helps Gradle to optimise build logic. To help Gradle we must define rules to work with objects in the model space. Each rule is like a recipe for Gradle on how to work with the model. Gradle can build a graph of models and know about dependencies between models. This way Gradle guarantees that model objects are completely configured before being used. For example if a rule needs a VersionFile model configuration object then Gradle makes sure that the VersionFile is created and all properties are set. So we don't need any lazy or late binding anymore, because the properties will be set (Gradle makes sure) when we want to use them. The rules are defined a class that extends RuleSource. Such a class is stateless and only contains methods to work with the model objects. Gradle has some specific annotations that can be used on methods to indicate what a method should do.

Continue reading →

Awesome Asciidoctor: Using Ruby Extensions With Asciidoctor Gradle Plugin

Posted on by  
Hubert Klein Ikkink

Asciidoctor is a Ruby tool, but luckily we can use AsciidoctorJ to use Asciidoctor in Java code. The Asciidoctor Gradle plugin relies on AsciidoctorJ to run. AsciidoctorJ allows us to write custom extensions in Java (or Groovy), but we can still use Asciidoctor extensions written in Ruby with the Gradle plugin.

In the following example we use the emoji-inline-macro from Asciidoctor extensions lab. This is an extension written in Ruby. We create a new directory for our sample and create a lib folder. Inside the lib directory we copy the file emoji-inline-macro.rb and the supporting directory emoji-inline-macro. These files are all in the Asciidoctor extensions lab repository. After we have copied the files we should have the following structure:

Continue reading →

Gradle Goodness: Custom Plugin Repositories With Plugins DSL

Posted on by  
Hubert Klein Ikkink

To apply a plugin in our Gradle build script we can use the plugins DSL. The plugins DSL is very concise and allows Gradle to be more efficient and more in control when loading the plugin. Normally the plugin we define is fetched from the Gradle plugin portal. If we have our own repository, for example on the intranet of our company, we have to define that extra repository with a pluginRepositories configuration block in the settings.gradle file of our project.

In the following sample we have a plugin mrhaki.gradle.version-file that is stored in the company intranet repository with the URL http://intranet/artifactory/libs-release/.

Continue reading →

Ratpacked: Creating Pairs From Promises

Posted on by  
Hubert Klein Ikkink

The Pair class in Ratpack is an easy way to create a growing data structure, passed on via Promise methods. A Pair object has a left and right part containing data. These parts can even be other Pair objects. Since Ratpack 1.4.0 the Promise class has methods to set the right or left part of a Pair: left, flatLeft, right and flatRight. The result of these methods is a Promise<Pair> object. The input can be Promise type or a Function that can use a previous Promise.

In the following example specification we use the different new methods to create a Pair. We also create a simple Ratpack server with a asynchronous HTTP client implementation to simulate remote calls returning a Promise:

Continue reading →

Groovy Goodness: Identity Closure

Posted on by  
Hubert Klein Ikkink

In functional programming we have the concept of an identity function. An identity function returns the same result as the input of the function. Groovy has a lot of functional paradigms including a identity function. Of course in Groovy's case it is an identity closure. It is defined as a constant in the Closure class: Closure.IDENTITY. If we use this closure we get the same result as the argument we provide.

In the following example we first create our own identity closure. Next we use the built-in Closure.IDENTITY closure:

Continue reading →

Groovy Goodness: Interrupted Sleeping

Posted on by  
Hubert Klein Ikkink

Groovy adds a lot of useful methods to the Java JDK classes. One of them is the sleep method that is added to all objects. With the sleep method we can add a pause to our code. The sleep method accepts a sleep time in milli seconds. The implementation of the method will always wait for he given amount of milli seconds even if interrupted. But we can add a closure as extra argument, which is invoked when the sleep method is interrupted. We should return true for the closure to really interrupt, otherwise we use false.

In the following example we use the sleep method to pause the bedtime method of the User class. We run the bedtime method in a thread and after 2000 milli seconds we intercept the thread. The sleep method still wait for 5 seconds, before ending:

Continue reading →

Grails Goodness: Skip Bootstrap Code

Posted on by  
Hubert Klein Ikkink

Grails normally will run any *Bootstrap classes at startup. A Bootstrap class has a init and destroy closure. The init closure is invoked during startup and destroy when the application stops. The class name must end with Bootstrap and be placed in the grails-app/init folder. Since Grails 3.2 we can skip the execution of Bootstrap classes by setting the Java system property grails.bootstrap.skip with the value true.

In the following example Bootstrap class we simply add a println to see the effect of using the system property grails.bootstrap.skip:

Continue reading →

Groovy Goodness: Direct Field Access In (Super) Classes

Posted on by  
Hubert Klein Ikkink

When we use the property syntax of Groovy to get the value for a property, Groovy will actually try to invoke a get method for that property if it is available. So for example if we have the statement user.name actually user.getName() is invoked. If we want to reference a property field directly, so bypassing the get method, we must place an @ in front of the property field name. In the previous example we would write user.@name to get the field value directly. The same rules apply for setting a value for a property with the Groovy syntax. If we write user.name = 'mrhaki' then actually user.setName('mrhaki') is invoked. We can use the @ prefix also to set a value without invoking the set method for that property. So in our example it would be user.@name = 'mrhaki' and the setName method is not used.

In the following example we have a class Person with a name property. We add a getName method which formats the name field and returns the value. In a subclass User we access the name property from the super class using the Groovy property syntax and with the @ prefix:

Continue reading →

Awesome Asciidoctor: Trick To Use Caption Labels And Numbers In References

Posted on by  
Hubert Klein Ikkink

In Asciidoctor we can add an anchor with an ID to a section or title and then reference it in a link. The title of the section is used as link text. We can alter that when we define the link, but if we rely on the default behaviour we create a title for our section including the caption label and number. This way the created link points to the correct section and the text contains the caption text and number for that section.

In the following example markup we can see how we can use the caption label and section counter as attributes in the title. We do this with the title attribute of a section. By using the single quotes we tell Asciidoctor to interpret the attributes. We must also make sure we set the caption attribute to an empty string value. This disables the default caption creation of Asciidoctor for our section. Finally we need to provide an ID for the section using the #ID syntax:

Continue reading →

Awesome Asciidoctor: Use Captions For Listing Blocks

Posted on by  
Hubert Klein Ikkink

Asciidoctor has some built-in attributes to work with captions for certain content blocks. For example the table-section attribute defines the caption label (by default Table) that is prefixed to a counter for all tables in the document. When we transform our markup Asciidoctor will insert the text Table followed by the table number. By default the caption for listing blocks is disabled, but we can easily enable it with the listing-caption attribute.

In the following markup we enable the caption for listing blocks and set the value to Listing. This will add the text Listing followed by the listing section counter to the output.

Continue reading →

shadow-left