lucene_logo_green_300

Gradle Webinar – Explore the latest features in Gradle Cloud Services September 2016

updated_logo_for_gradle
The Gradle Scan is data captured during the execution of the build. It allows better understanding of the execution and provides opportunities for improvements including speedup of the execution, diagnosing issues and sharing build data.
The Scan is implemented as Gradle plugin which collects and uploads the build data.

I participated in the September 2016 webinar and some new useful features were introduced, now I want to share them. But first let’s do a Scan with the initial release (1.0). This will allow to identify the new features easily.

For the Scan execution, a plugin named com.gradle.build-scan must be applied. It is provided by Gradle. To use it, it must be available at the classpath of the buildscript. To do that, following snippet can be used:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "com.gradle:build-scan-plugin:1.0"
  }
}

The repositories block defines a Mavan layout repository from which can be downloaded the scan plugin. When the repository is available, the actual buildscript dependency for the classpath has to defined. For now I will use the plugin with group: com.gradle, name: build-scan-plugin and version: 1.0 (first release of the scan plugin).
As next step the plugin must be applied in the build script. This provides the logic which performs the scan:

apply plugin: 'com.gradle.build-scan'

The usage of the build scan requires explicit agreement with the terms of service. They are available at Gradle Scan Terms of Service. I recommend to read them before any further actions. To accept the agreement, in the build script must be added:

buildScan {
    licenseAgreementUrl = 'https://gradle.com/terms-of-service'
    licenseAgree = 'yes'
}

Continue reading “Gradle Webinar – Explore the latest features in Gradle Cloud Services September 2016”

lucene_logo_green_300

Gradle Equinox Plugin – Part 5: How to install bundles in custom container

updated_logo_for_gradle

In the previous part, I described, how to create a container with available console. But at the current state, the user cannot choose what to install in the framework. To solve this issue, must be provided a mechanism for configuration. Two options are possible:

  • Implement plugin configuration properties, e.g. convention mapping
  • Externalize the tasks from the plugin’s apply method as separate task class. I prefer to use this option. It allows to define custom tasks with that type, not using only the default one.

Let’s start, but first I want to write a little more about how Gradle framework works.
What is the buildscript? – The build script is a set of actions that will be executed in some predefined order and perform certain operations. These actions or group of actions are called Task, which is a part of parent entity called Project. The smallest unit which Gradle can execute is a Task.
Gradle is a language for dependency based programming. This means that can be defined tasks and dependencies between tasks. These tasks are executed in the order of their dependencies and each task is executed only once. Gradle builds a complete dependency graph (DAG) before any task execution.
Gradle build lifecycle is based on three phases:

  1. Initialization – Gradle determines which projects are going to take part in the build and creates a Project instance for each of these projects.
  2. Configuration – Gradle configurates the project objects. Executes the build scripts of all projects which are part of the build, but tasks will not be executed, only the DAG (Directed Analityc Graph) would be created for all tasks.
    Since Gradle 1.4 is supported configuration on demand allowing to configure only the relevant projects – Configuration On Demand
  3. Execution – Gradle executes all tasks (actions) as per the order given in the command line. If any dependencies exist between tasks, those relationships will be honored first before the command like ordering.

I externalized the logic from the plugin class as separate task. The code is available at github if you are looking the whole file.

To define a Gradle task, the DefaultTask class from the Gradle API must be extended:

class CreateEquinoxContainer extends DefaultTask{

As next step, must be specified a task action which will be executed. To do that, a method must be annotated with @TaskAction:

@TaskAction
def build() {

}

As I mentioned above, a mechanism for task configuration is needed. The Gradle API provides annotations (@Input, @Optional) which specify the required properties for the configuration of the task.

  • @Input – annotates a property or getter method indicating that the property specifies some input value for the task. The task will be considered out-of-date when the property is changed. I will not describe the up-to-date check in this article, for more information – Gradle Up-to-date checks (AKA Incremental build) doc. Just want to mention, if you need to use the check for a file content not for the path, the @InputFile or @InputDirectory annotations must be used.
  • @Optional – mark the property as optional.

Continue reading “Gradle Equinox Plugin – Part 5: How to install bundles in custom container”

lucene_logo_green_300

Gradle Equinox Plugin – Part 4: How to install bundles providing console commands

updated_logo_for_gradle

In the previous part, I described how to implement the creation of an empty Equinox, but this is not very functional yet. So in this post I’ll write down how to code the part which installs bundles in the container.

    Equinox is a framework using units which are divided into two types:

  1. Bundles – a set of Java class files with much more detailed MANIFEST.MF file. The manifest describes the behavior of the bundle in the framework, e.g. what is needed from the outside world to fulfill its dependencies, the packages that should be exported, what must be executed when the bundle is being started or stopped, etc.
    MANIFEST.MF example file:
    Bundle-Name: Hello OSGi World
    Bundle-SymbolicName: name.mazgalov.helloworld
    Bundle-Description: A Hello World bundle
    Bundle-ManifestVersion: 2
    Bundle-Version: 1.0.0
    Bundle-Activator: name.mazgalov.helloworld.Activator
    Export-Package: name.mazgalov.helloworld;version="1.0.0"
    Import-Package: org.osgi.framework
    

    The lines from the example are called OSGi headers and describe the behavior of the bundle in the environment. These are not all of them, a list can be found here: OSGi bundles headers reference

    The headers above are the most used ones. They serve for:
    Bundle-Name: Defines a human-readable name for the bundle.
    Bundle-SymbolicName: The only mandatory header. It specifies a unique identifier for a bundle, based on the reverse domain name convention (similar to the java packages).
    Bundle-Description: A description of the functionality of the bundle.
    Bundle-ManifestVersion: The OSGi specification which must be used for reading the bundle.
    Bundle-Version: The version number of the bundle.
    Bundle-Activator: Indicates the class name to be invoked when the bundle is activated.
    Export-Package: A list with Java packages contained in the bundle which will be made available to the outside world.
    Import-Package: A list with Java packages which are required from the outside world to fulfill the dependencies needed in a bundle.

  2. Fragment – Java archive file with specific manifest headers that enable it to attach to a specified host bundle. Fragments are treated as part of the host, including any permitted headers. The fragment uses the host classloader and it must never have own. To specify the fragment host, must be used the Fragment-Host manifest header. Typically it is used to provide files for different locales and to provide some platform specific code.

Continue reading “Gradle Equinox Plugin – Part 4: How to install bundles providing console commands”

lucene_logo_green_300

Gradle Equinox Plugin – Part 3: How to create an empty Equinox container

updated_logo_for_gradle

In this part, I’ll implement a code which creates an empty Equinox container.
As first step must be defined a task which creates the container and a script which starts it. For the definition of the task can be used the Project object provided by the Gradle framework. It represents the project which applies the plugin, The apply method of the plugin class which implements org.gradle.api.Plugin passes the object as parameter.  In my case that is the EquinoxPlugin class:

class EquinoxPlugin implements Plugin {
    @Override
    void apply(Project project) {
		TaskContainer tasks = project.tasks
	
        tasks.create 'buildEquinoxConfig', {
            
        }
    }
}

To create an Equinox container will be needed an Equinox kernel jar and some configuration properties. To get the kernel, first must be defined a configuration and dependency to it. The Gradle Project ConfigurationContainer can be used to define the required Equinox dependency:

void apply(Project project) {
	ConfigurationContainer configurations = project.configurations
	DependencyHandler dependencies = project.dependencies
	TaskContainer tasks = project.tasks

	project.repositories {
		mavenCentral() // Using the Maven Central repository to download the Equinox kernel
	}

	configurations.create 'equinoxKernel'
	dependencies.add 'equinoxKernel', [group:'org.eclipse', name: 'osgi', version: '3.10.0-v20140606-1445', configuration: 'runtime']

	tasks.create 'buildEquinoxConfig', {
		
	}
}

When the plugin is being executed, Equinox will be downloaded at the file system. As next step must be created a configuration which will start the container. To achieve that a configuration file called config.ini is required in dedicated directory which will be used by Equinox during the  runtime.

Continue reading “Gradle Equinox Plugin – Part 3: How to create an empty Equinox container”

lucene_logo_green_300

Gradle Equinox Plugin – Part 2: How to apply the dummy plugin

updated_logo_for_gradle

In the previous part, the skeleton of the projects was created. Now let’s create the actual plugin. To achieve that the Gradle Plugin interface must be implemented:

class EquinoxPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {
        println 'Success!!!'
    }
}

The interface has one method which must be implemented. It will be executed, when the plugin is being applied. For now only a string message will be printed, just to verify that the plugin is successfully applied.

As next step, the plugin ID must be defined. To do that the properties file under src/main/resources/META-INF/gradle-plugins must be modified. As I explained in the previous post, the file is being used by the Gradle framework to define a string ID for specific plugin. At the current point, the file is empty and Gradle still doesn’t know which class file must be associated to the ID. To define the class a property named implementation-class, must be set:

implementation-class=name.mazgalov.equinox.plugin.EquinoxPlugin

Now all required steps for the application of the plugin are satisfied and the next question is how to test the plugin?

Gradle provides a few mechanisms for writing and testing of plugins:

  1. To place the plugin under a buildSrc directory in the root Gradle project – any code placed under this directory will be compiled and set at the execution classpath before the actual execution of the root Gradle project. This is the easiest way, but in every Gradle execution, the buildSrc code will be compiled, which slows the build. Other negative impact is that the plugin cannot be used in other projects. As you can see, the Equinox plugin started as separate project and this options is not applicable for it, but I wanted to describe it.
  2. To create a separate Gradle project which publishes the plugin to local/remote repository – this option is a good choise and it eliminates the cons mentioned in the previous point. The negative side of this is that the all projects which depend on it cannot take the change directly. The plugin must be rebuilt and republished to the repository which the projects refer.
  3. To create a separate Gradle project without an initial sourceSet – to use this options during the development, all classes must be defined in Gradle script files and when the major work is finished, the code must be placed in sourceSet. After that the development must continue like the second option.
  4. To create a separate Gradle project with tests which execute builds applying the plugin – this options ensures that the tests will use the latest changes and publishing is not required. I chose to take this way, because to execute some functionality a test must be created covering a huge amount of the code, also a separate project only for testing is not required. I do not claim that this is the best solution and do not commit anyone to it.

Continue reading “Gradle Equinox Plugin – Part 2: How to apply the dummy plugin”

lucene_logo_green_300

Gradle Equinox Plugin – Part 1: How to create the project skeleton

updated_logo_for_gradle

I decided to start a new  Gradle plugin project which will ease the creation process of OSGi Equinox container during the development.

In this post, I’ll try to describe how I’m developing Gradle plugins and how I’m using IntelliJ IDEA as IDE. I choose IntelliJ , because in my opinion, IDEA  has better support for Groovy and Gradle than Eclipse (including the available plugins at the marketplace).

As first step, I created a new repository at Github and skeleton project on the file system:

equinox-skeleton

The file structure has:

  • a build.gradle file – the main build file
  • a properties file under src/main/resources/META-INF/gradle-plugins named name.mazgalov.equinox.properties – this file represents the name of the plugin. It is needed to apply the plugin with string constant in the builds after the ‘apply plugin:’ statement. The name of the file represents the string which MUST be used. If such file not present, the full plugin class name must be used. In this case to apply the plugin, the build script has to contain apply plugin: ‘name.mazgalov.equinox’. The domain  notation is used due to gradle.org restrictions for publishing of custom plugins.  For more information how to publish, visit https://plugins.gradle.org/docs/submit

I prefer the Gradle Wrapper for the builds startup, because it doesn’t need a Gradle installation, you need just to start a script and the required Gradle version will be downloaded and executed. It is OS independenct as well, the wrapper can be started on Linux and Windows with gradlew. For more information: https://docs.gradle.org/current/userguide/gradle_wrapper.html

Continue reading “Gradle Equinox Plugin – Part 1: How to create the project skeleton”

lucene_logo_green_300

SASS compiler Gradle plugin based on Vaadin

I developed a Gradle plugin which compiles SASS files to CSS. It uses  jar files published by Vaadin. The code can be found on github. In the readme file is explained how to use the plugin.

The plugin defines dynamically a configuration and sets Vaadin libraries (SASS compiler and Vaadin themes) as dependencies. During the compilation these jars are available on the classpath allowing an extension of the default Vaadin themes.

I think it is very easy to use it, only the input (cscc file) and output (css file) are mandatory (see the examples). The plugin also provides mechanisms for additional configuration like the Vaadin versions which should be used (default versions are latest milestone from the Maven Central repository) and configuration which should be used for the compilation.

The plugin provides a Gradle task which can be used to write a custom compilation tasks with type CompileSass.