Freitag, 21. September 2018

Gradle Kotlin DSL: Creating Tasks

This post is about a basic but very powerful feature of Gradle (which Maven is missing): Custom task creation.
The Kotlin DSL introduced a breaking change with Gradle 4.10 which included the new API for lazy task declaration and configuration. This new API will eventually replace the existing one, so I will not be covering the old API in this post.

There are basically 3 different approaches for introducing custom build logic into Gradle:
  1. Create a completely new task
  2. Extend an existing task
  3. Change the configuration of existing tasks

1. To create a new task,

it must first be registered:
tasks {
    register("myTask")
}
or
tasks.register("myTask")

To also obtain a reference to the task to be used for type safe use later:
tasks {
    val myTask by registering
}
or
val myTask by tasks.registering
By declaring the variable outside the tasks block it can be accessed anywhere in the build script which is useful for some tasks (like a task for creating a sources JAR for the Maven Publish Plugin). In most cases it will make sense to declare all tasks inside one tasks block.

A registered tasks can then be configured:
tasks {
    register("myTask")
    "myTask" {
        doLast {
            println("Hello World")
        }
    }
}
or
tasks.named("myTask") {
    // logic goes here
}
Most pre-existing tasks, like the ones introduced through plugins can also be accessed this  way.

It is possible to combine declaration and configuration into one command:
tasks {
    register("myTask") {
        // logic goes here
    }
}
or
tasks.register("myTask") {
    // logic goes here
}

And for completeness sake, declaring and configuring a task while obtaining a reference:
val myTask by tasks.registering {
    // logic goes here
}
or
tasks {
    val myTask by registering {
        // logic goes here
    }
}
Note that the variable will hold a TaskProvider instead of a Task due to the new lazy API. In most cases it still can be used anywhere where a Task reference was used before. In the rare cases where this is not possible, the task can be obtained by calling get() on the provider.

References for tasks can also later be obtained via the existing delegate:
val myTask by tasks.existing
By using the existing delegate it is possible to accurately define the scope in which a reference should exist.


2. To inherit from an existing task,

the class of the parent task must be passed to the register() function or the registering delegate:
tasks.register("myTestTask", Test::class) {
    // logic goes here
}
or
val myTestTask by tasks.registering(Test::class) {
    // logic goes here
}
This is possible for all cases mentioned under 1.

Existing options of the parent task can then be reconfigured and/or logic can be added:
tasks.register("myTestTask", Test::class) {
    setForkEvery(1)
    doLast {
        println("my test task was run")
    }
}
Note that this task won't run instead of the test tasks or at all if not explicitly called or configured!


3. To configure existing tasks,

it is possible to reconfigure all existing tasks:
tasks {
    configureEach {
        group = "myGroup"
        doLast {
            println("running task $name")
        }
    }
}

or all tasks of a certain type:
tasks {
    withType<Test>().configureEach {
        useJUnitPlatform()
        setForkEvery(1)
    }
}

Like mentioned before, you can also access most tasks that were registered by plugins:
"test"(Test::class) {
    useJUnitPlatform()
}
or
val test by existing(Test::class) {
    useJUnitPlatform()
}
This will modify the actual test task that is being executed during a build. Tasks like wrapper or init are not accessible in this way.

UPDATE: Starting with Gradle 5.0, most existing tasks can be accessed in a type safe manner:
test {
    useJUnitPlatform()
}

Note that all configuration and logic outside of a doLast or a doFirst block will be executed at configuration time. Logic inside these blocks will be executed when the task is executed.

Freitag, 14. September 2018

Gradle Kotlin DSL: UPDATE Using the Maven Publish Plugin

This post is an update of the old one on using the Maven Publish Plugin which is not incubating anymore.
The main reason for this update is the introduction of the new lazy API for task configuration with Gradle 4.9 and the change of the Strings invoke() function in Gradle Kotlin DSL with Gradle 4.10. Invoke() is now built on top of this new API and won't work the way it is described in the old post anymore. Also, the way source sets are accessed was changed.

The recommended way to declare the task for creating the Jar file with the sources is:
val sourcesJar by tasks.registering(Jar::class) {
    classifier = "sources"
    from(sourceSets["main"].allSource)
}

We will use the new API and its new delegate registering() to lazily create the task. 
The variable for the task is declared outside of the tasks block to make it accessible inside the publishing block.
Also note that the java prefix for accessing source sets is gone.

With the new API the variable sourcesJar is not of type Task anymore but of type TaskProvider. By calling get() on the provider, the task can be accessed:
publishing {
    publications {
        register("mavenJava", MavenPublication::class) {
            from(components["java"])
            artifact(sourcesJar.get())
        }
    }
}
Analogous to the creation of the sourcesJar task we use the new API and its new register() function to create the publishing task. And because of that, the publications block can be used as intended without braces.

Freitag, 16. März 2018

Gradle Kotlin DSL: Using the Maven Publish Plugin

If you want to publish your libraries built with Gradle to a Maven Repository you need to create the necessary artifacts and a corresponding POM-file. To do that Gradle offers the Maven Plugin and the new incubating Maven Publish Plugin which is used in this post.
Please note that the Maven Publish Plugin does not yet support all the features of the Maven Plugin which it will eventually replace.
plugins {
    ...
    `maven-publish`
}
After declaring the plugin, a publication needs to be defined inside the publishing block. In the Kotlin DSL you have two ways to create an actual publication: as String or as a variable. When using a String to declare a publication the syntax changes slightly:
publishing {
    (publications) {
        "mavenJava"(MavenPublication::class) {
            from(components["java"])
        }
    }
}
The publications function cannot be used since it does not declare the necessary invoke() function on Strings. By putting parenthesis around publications we instead invoke getPublications() which enables the use of Strings as a publication.
When using a variable instead of the String the publications block can be used:
publishing {
    publications {
        val mavenJava by creating(MavenPublication::class) {
            from(components["java"])
        }
    }
}
Additional artifacts can be added to the publication by defining and adding an artifact creating task to it. In this example another JAR file is created containing all the source files from the main source set:
tasks {
    "sourcesJar"(Jar::class) {
        classifier = "sources"
        from(java.sourceSets["main"].allSource)
        dependsOn("classes")
    }  
}

publishing {
    (publications) {
        "mavenJava"(MavenPublication::class) {
            from(components["java"])
            artifact(tasks["sourcesJar"])
        }
    }
}

Gradle Kotlin DSL: Creating additional jars

Sometimes you want to create more than one JAR file for your project. It could for example contain some source code or your compiled test classes. To do that in Gradle you first need create a task that inherits from the Gradle Jar task and will produce your JAR file:

"testJar"(Jar::class) {
    classifier = "tests"
    from(java.sourceSets["test"].output)
    dependsOn("testClasses")
}
Then you add the artifact itself:
artifacts {
    add("archives", tasks["testJar"])
}

Your build will now create an additional JAR file with the specified content which are the compiled class files for tests in this example.

Samstag, 10. März 2018

Gradle Kotlin DSL: Using JUnit 5


Since I ended up spending a lot of time figuring out how to do certain things in the Kotlin DSL for Gradle, I decided to share my findings in a series of small posts.

On todays menu is JUnit 5 and the built-in support in Gradle 4.6. Use the following code snippet to enable JUnit 5 tests in your Gradle build:

tasks {    
    withType<Test>{        
        useJUnitPlatform()
    }
}

UPDATE:
Gradle 4.9 introduced a new API for creating tasks which reflects in the Gradle Kotlin DSL in Gradle 4.10.

Using the new API to configure tasks of type Test looks the following:
tasks {
    withType<Test>().configureEach {
        useJUnitPlatform()
    }
}

Alternatively the test task can be configured directly:
tasks {
    "test"(Test::class) {
        useJUnitPlatform()
    }
}
This is now possible because the invoke() function on Strings was changed to look up existing tasks.

Montag, 21. August 2017

JavaFX on Raspberry - It's still possible!

Hello everybody!

Although Oracle has stopped supporting JavaFX on embedded systems, it is still possible to run JavaFX on Raspberry and no, we do not use the Gluon plugin, even if it is not so bad. If you are looking for a tutorial, you will find only complex tutorials that usually leave out important points or which are still from the time of Oracle's official support. Therefore, I thought to write a quick and easy guide to get JavaFX applications on a Raspberry Pi to run. But let's say that I've tried this on a new Raspberry Pi 3 with Raspbian and therefore does not know if it works on the other boards as well! [go to german version]

Okay, let's go!

Audio visualization in JavaFX - AudioSpectrumListener

Hello everybody!

In this article I would like to show you how to visualize audio in JavaFX without additional frameworks or libraries, for example, to create a visualizer for an mp3 player. [go to german version]

ATTENTION!
I assume that it is already known how to play audio files over the MediaPlayer in JavaFX. Otherwise, simply search on Google ;). Also, this does not work on a raspberry because the media API of JavaFX does not work there!

Okay, let's go!

Dienstag, 18. Juli 2017

Howto - Sicher mit Chrome ins Internet

Hallo zusammen, nach langer Zeit mal endlich wieder ein Blogeintrag von mir. Da es hier diesmal nicht um JavaFX geht sondern um das sichere surfen mit dem Google Browser Chrome bzw. alle Browser die auf Chromium basieren, ist dieser Blogeintrag für jeden geeignet. Wichtiger Hinweis direkt zu Beginn, diese Anleitung sorgt nicht dafür das ihr im Internet anonym oder absolut sicher seid (beide Aspekte können nie 100% erreicht werden), also keine krummen Sachen machen und immer schön aufpassen!

Bild von einem verschlossenen Schloss in Google Chrome Farben

Motivation

Warum eigentlich diese Anleitung? Mir ist immer wieder aufgefallen, das viele verschiedene Personen sehr viel im Internet surfen, sich auf Facebook und Co. anmelden, auf Amazon einkaufen und dergleichen. Dabei fällt den meisten noch nicht mal auf ob dies über eine unverschlüsselte oder verschlüsselte Verbindung passiert, was auch nicht schlimm ist, da die meisten vermutlich keine Ahnung haben sondern einfach nur schnell diese Dinge im Internet machen wollen. Daher wollte ich eine Anleitung geben was man einmalig machen kann um weiterhin einfach seine Dinge im Internet zu machen und sich gleichzeitig ein wenig sicherer zu fühlen.

Montag, 24. Oktober 2016

Audio-Visualisierung in JavaFX - AudioSpectrumListener

Hallo zusammen!

In diesem Beitrag möchte ich zeigen wie man in JavaFX ohne zusätzliche Frameworks oder Bibliotheken Audio visualisieren kann, um zum Beispiel einen Visualizer für einen mp3-Player zu erstellen. [gehe zur englischen Version]

ACHTUNG!
Ich gehe davon aus, dass bereits bekannt ist wie man in JavaFX Audio-Dateien über den MediaPlayer abspielt. Ansonsten einfach mal danach bei Google suchen ;). Außerdem funktioniert dies nicht auf einem Raspberry, da die Media-API von JavaFX dort generell nicht funktioniert!

Okay los gehts!

Montag, 10. Oktober 2016

JavaFX: Strategische / Technologische Bewertung

Hallo zusammen!

Nach nun etwas mehr als 2 Monaten, gibt es mal wieder einen Blogeintrag von mir. Warum erst jetzt wieder? Naja weil meine Masterarbeit in der entscheidenden Phase war und daher meine volle Konzentration verlangte. Man kann sich also denken worauf dies hinausläuft, ja ich habe vorletzte Woche meinen Master of Science erhalten :D. Da ich aber sehr viel Zeit in die Masterarbeit gesteckt habe und es zudem um das Thema JavaFX ging, wollte ich hier an dieser Stelle nochmals ein bisschen Werbung für meine Masterarbeit machen.

Donnerstag, 21. Juli 2016

JavaFX auf Raspberry - Es geht immer noch!

Hallo zusammen!

Obwohl Oracle den Support für JavaFX auf eingebetteten Systemen eingestellt hat, ist es weiterhin möglich JavaFX auf Raspberry auszuführen und nein wir nutzen dafür nicht das Gluon Plugin, auch wenn dieses nicht so schlecht ist. Wenn man nach einer Anleitung dazu sucht, findet man leider nur komplexe Tutorials die meistens wichtige Punkte auslassen oder welche, die noch aus der Zeit des offiziellen Supports von Oracle stammen. Daher habe ich mir gedacht hier nun eine schnelle und leichte Anleitung zu schreiben um JavaFX Anwendungen auf einem Raspberry Pi zum laufen zu kriegen. Hierbei sei jedoch gesagt, dass ich dies nur auf einem neuen Raspberry Pi 3 mit Raspbian ausprobiert habe und daher nicht weiß ob es auf den anderen Boards ebenfalls so funktioniert! [gehe zur englischen Version]

Okay los gehts!

Montag, 27. Juni 2016

1.Platz HackARThon TH Köln

Hallo zusammen!

Nach langer Pause geht es nun weiter mit einem Blogeintrag. Eigentlich wollte ich als nächstes über ein anderes Thema schreiben, aber es ergab sich kurzfristig, dass ich mit meinem Kollegen Nico Bastian an einem Hackathon an der Technischen Hochschule Köln Campus Gummersbach teilgenommen habe. Das Event fand zwar schon vor einiger Zeit statt, nämlich am 12.Mai 2016, aber der offizielle Artikel der Hochschule wurde erst letzte Woche veröffentlicht. Und ja, wir haben tatsächlich den 1.Platz belegt. Yeah!

Samstag, 30. April 2016

JavaFX Performance #3 - BenchmarkJFX

[Hinweis: Die folgenden Ergebnisse stammen aus meiner veröffentlichten Masterarbeit "JavaFX - Strategische / Technologische Bewertung"]

Hallo und willkommen zurück zum 3. und vorerst letzten Part des JavaFX Performance Beitrags!

Einleitung

Im letzten Part haben wir anhand des Bubblemark Benchmarks JavaFX 2 und JavaFX 8 miteinander verglichen und gesehen, dass JavaFX 8 ca. 17% schneller war als JavaFX 2. Jedoch war ich nicht ganz zufrieden mit dem Ergebnis, da ich der Meinung bin, dass Bitmaps bewegen nicht wirklich Praxis-relevant ist. Ausgenommen natürlich man möchte ein JavaFX Spiel entwickeln ;). Daher habe ich mich kurzerhand dazu entschlossen einen eigenen Benchmark, welcher auf dem Bubblemark Benchmark aufbaut, zu entwickeln. Das Ergebnis ist der BenchmarkJFX!

Mittwoch, 20. April 2016

JavaFX Performance #2 - JavaFX 2 und JavaFX 8

[Hinweis: Die folgenden Ergebnisse stammen aus meiner veröffentlichten Masterarbeit "JavaFX - Strategische / Technologische Bewertung"]

Hallo und willkommen zurück zum 2.Part des JavaFX Performance Beitrags!

Einleitung

Im letzten Part haben wir anhand des Bubblemark Benchmarks und des Ergebnisses von TBEERNOT gesehen, dass JavaFX2 mehr FPS erzeugen kann als Swing. Nun schauen wir mal was herauskommt, wenn wir den Bubblemark Benchmark mit Java 1.7 kompilieren und jeweils mit JavaFX2 und JavaFX8 ausführen. Da wir aber nun beides mal JavaFX ausführen können wir zusätzlich den VectorBall Benchmark mit ausführen, dieser erstellt die Bälle nicht anhand von Bitmaps, sondern anhand von Vectoren. Dadurch kann nun auch die Vector-Performance gemessen werden.

Donnerstag, 14. April 2016

JavaFX Performance #1 - Swing und JavaFX

[Hinweis: Die folgenden Ergebnisse stammen aus meiner veröffentlichten Masterarbeit "JavaFX - Strategische / Technologische Bewertung"]

Im Rahmen meiner Masterarbeit welche JavaFX behandelt, habe ich die Performance von JavaFX und Swing sowie von JavaFX 2, JavaFX 8 und JavaFX 9 (Early Access Build 110) betrachtet. Jedoch bin ich der Meinung, dass meine Erkenntnisse vielleicht auch anderen weiterhelfen können und möchte diese daher hier in meinem Blog teilen. Wie im Titel bereits zu sehen, ist dies der 1.Part, welcher sich mit der Performance zwischen JavaFX 2 und Swing beschäftigen wird. Der 2.Part wird sich dann mit der Performance zwischen den verschiedenen JavaFX Versionen befassen und der 3.Part mit einem selbst entwickelten Benchmark. Ich hoffe es wird euch gefallen!