Blogeinträge aus dem Jahr 2016

25. Januar 2016 JavaFX-Gradle-Plugin, Statischen Website mit Gulp, Bower und Markdown

JavaFX-Gradle-Plugin

Eine JavaFX-Applikation mit Gradle zu generieren war bisher mit dem Gradle-Plugin "javafx-gradle" von Danno Ferrin möglich, da dieser jedoch das Projekt seit mehr als 18 Monaten nicht mehr weiterentwickelt hat, und auch seitens Oracle wohl unklare Policies herrscht, sammeln sich die Bug-Tickets auf BitBucket. Es herrschte somit ein ziemliches Ungleichgewicht zwischen der Maven- und der Gradle-Welt.

Da ich das JavaFX-Maven-Plugin jedoch jetzt knapp ein Jahr lang weiterentwickle, haben mindestens die Maven-Nutzer einen strategischen Vorteil gehabt und konnten hier auf eine einfache Konfiguration zur Generierung von Native-Bundles setzen. Dies ist jedoch vorbei, denn ich habe mit den Erfahrungen durch das Maven-Plugin ein eigenes Plugin für Gradle entwickelt.

Eins vorweg: ich bin kein Gradle-Nutzer, ich mag meine Lifecycles in Maven und die festen Strukturen und Abläufe. Wer lieber was eigenes haben will, darf ruhig Gradle verwenden ;) ich zwinge hier niemanden zu wählen! Das war auch der Grund wieso ich die Konfigurationsparamter nahezu identisch gehalten habe: bessere Migration von Maven nach Gradle und natürlich auch von Gradle nach Maven (ob es sowas wirklich gibt?!). Wer jetzt mit Gradle sein Buildscript um JavaFX-Fähigkeiten erweitern will, der kann dies ganz einfach durch mein JavaFX-Gradle-Plugin erreichen.

buildscript {
    dependencies {
        classpath "de.dynamicfiles.projects.gradle.plugins:javafx-gradle-plugin:1.0"
    }

    repositories {
        mavenCentral()
    }
}
apply plugin: "javafx-gradle-plugin"

Mehr dazu kann man auf Github finden.

Gulp und Co für statische Website-Generierung mit Sicherheit

Aber nicht nur da hat sich seit letztem Jahr etwas geändert, doch hier zuvor ein kleiner historischer Rückblick:
Zu Beginn meiner Website habe ich statisches HTML händisch getippt, damals waren Tabellen-Layouts gerade der Renner schlechthin, jeder im Web hat damit gearbeitet, weil die bisherigen Boxmodelle nicht vernünftig waren. Der große Nachteil daran: abgesehen davon, dass es kein semantisches HTML war, sollte auch heute offensichtlich sein, dass man zu viele Fehler macht, da man Dateien dupliziert. Eine Änderung an der HTML-Struktur und schon müssen auf einmal alle vorhandenen Seiten händisch neu angefasst werden (und wehe dem, dass man was vergisst oder sich vertippt).

Danach der erste Berühungspunkt mit PHP, sehr viel habe ich da über die Materie der dynamischen Websites gelernt und mir auch erarbeitet. Später dann der Versuch mittels Java ein eigenes CMS zu entwickeln, der jedoch eher in ganz viel KnowHow-Aufbau geendet ist anstatt dass etwas wirklich produktives dabei herausgekommen war.

Meine Website wird vollständig mit Gulp generiert! Angefangen hat dies mit einem Experiment, um mal mit "state-of-the-art" Technologie meine Website zu generieren. Das ganze läuft nun schon seit einigen Monaten und wurde von mir nach und nach ausgebaut. Aktuelles neue Feature: automatische Prüfsummen-Generierung für Subresource Integrity, und das ganz mit den Mitteln von NodeJS!

Hier ein kleiner Auszug aus meinem gulpfile:

function getSubressourceIntegrity(entry, printAsAttributeValue){
    var foundResourceHash = allChecksums[entry];
    printAsAttributeValue = printAsAttributeValue === true;
    if(foundResourceHash !== "" && typeof foundResourceHash !== "undefined"){
        if(!printAsAttributeValue){
            return "integrity=\"" + subresourceIntegrityHashMethod + "-" + foundResourceHash + "\" crossorigin=\"anonymous\"";
        }
        return subresourceIntegrityHashMethod + "-" + foundResourceHash;
    }
    return "";
}
// don't escape the output
getSubressourceIntegrity.safe = true;
swig.setFilter("getSubressourceIntegrity", getSubressourceIntegrity);

Für die Generierung der Prüfsumme läuft vorher ein Task, der alle generierten und kopierten Ressourcen filzt und sich in einem Javascript-Objekt merkt:

function calculateIntegrityHash(){
    return through.obj(function (file, encoding, callback) {
        if(file.isBuffer()) {
            var pathprefix = file.cwd + "/" + targetFolder;
            var fileName = file.base.substr(pathprefix.length) + file.relative;
            fileName = fileName.replace(/\\/g, "/");

            var someChecksum = crypto.createHash(subresourceIntegrityHashMethod).update(file.contents, "utf8").digest("base64");
            allChecksums[fileName] = someChecksum.substr(0,someChecksum.length - 1);
            console.log("generated checksum for", fileName, "with result: ", allChecksums[fileName]);
        }

        this.push(file);
        return callback();
    });
}

In meinen SWIG-Templates habe ich somit folgendes stehen:

<html>
<head>
<link rel="stylesheet" href="/style/mobile.css" data-enhanced-integrity="{{"/style/mobile.css"|getSubressourceIntegrity(true)}}" />
<!-- ... -->
</head>
<body>
<!-- ... -->
<script src="/script/jquery.min.js" defer {{"/script/jquery.min.js"|getSubressourceIntegrity}}></script>
</body>
</html>

Dadurch kann ich ohne nachträgliche Arbeit automatisch die entsprechenden Hashes generieren und einfügen. Diese Lösung hat zwar den Nachteil, dass ich hier meine Templates entsprechend anpassen muss, allerdings habe ich dann die volle Kontrolle, und muss nicht über einen nachträglich konstruierten DOM arbeiten.

Kleine Seitennotiz zur Sicherheit: ich habe aus meinen Social-Funktionen den REDDIT-Link entfernt, da diese seit diesem Jahr ihre AGB geändert haben. Auch wenn es darum geht, dass REDDIT Werbeeinnahmen generieren kann, so möchte ich alle Besucher nicht dem entsprechend bevormunden. Hierfür werde ich später noch eine Kleinigkeit in Richtung 2-Klick-Lösung bauen.

Die nächste Umstellung wird allerdings die Umsetzung der Blog-Einträge betreffen, damit diese auch einzelnd verlinkt werden können. Bisher sammeln sich alle Beiträge auf einer Jahres-Seite, allerdings ist das nicht so ganz sauber, wie es sich anfangs in meinem Kopf dargestellt hatte. Außerdem werde ich meine CSS-Dateien nochmal neu aufsetzen und mit SASS oder LESS bauen, bisher sind diese noch "Hand-gezupft".

Einige dieser Erfahrungen fließen direkt in meine alltäglich Arbeit ein, viele jedoch sind und bleiben mein eigenes Wissen, welches früher oder später dann doch seine Anwendung findet. Manches davon mag vielleicht unnützes Wissen sein, aber je mehr man sich davon aneignet (und es einen nicht belastet), desto vielfältiger kann man später über den Tellerrand blicken.

Und damit soll es dieses Mal auch belassen sein, viel Erfolg allen bei Ihrer Arbeit!

29. März 2016 Perspektiven und Ausblicke

Kennt ihr das nicht auch? Als Content erschaffende Instanz fällt einem einfach nicht ein, was man schreiben könnte? Oftmals versucht man dann wenigstens IRGENDWAS zu schreiben, ohne dass es einen Sinn macht und wandelt es später dann soweit ab, dass es wenigstens semantisch eine klare Linie gibt.
Ein Ausweg kann natürlich sein, dass man von dem aktuellen Geschehen und Neuerungen erzählt, also fangen wir doch einfach an ;)

Erfolgreiche Umstellung von Gulp v3 nach Gulp v4

Ich verwende für die Erstellung meiner Website ja den NodeJS-Bower-GulpJS Stack und gerade bei der Entwicklung immer wieder Arbeitsschritte, die parallel abgearbeitet werden können, und einige, die in einer konsequenten Reihenfolge abgearbeitet werden müssen, hauptsächlich aufgrund des Steaming-Models von Gulp bzw. dem dadrunter liegendem "Orchestrator"-Framework. In Version 3 hat man häufig das Gulp-Modul run-sequence verwendet, um diese vernünftig auszuführen und nicht für jedes Element direkt einen eigenen Gulp-Task einzuführen.
Mit Version 4 von Gulp ist dies nun out-of-the-box möglich, hauptsächlich weil das zugrunde liegende Framework für die Task-Verwaltung gewechselt worden ist, dies wird nun von "Undertaker" übernommen.

Änderungen an den Gulp-Tasks lassen sich sehr schnell nachjustieren:

Vorher:

gulp.task('renderAll', function(cb) {
    runSequence(
        "cleanAll",
        "copyStaticFiles",
        "generateDownloadStuff",
        "calculateRessourceIntegrity",
        "prepareContent",
        "processContent",
        cb
    );
});

Nachher:

gulp.task("renderAll",
    gulp.series(
        "cleanAll",
        "copyStaticFiles",
        "generateDownloadStuff",
        "calculateRessourceIntegrity",
        "prepareContent",
        "processContent"
    )
);

Da der dritte Parameter weggefallen ist, laufen viele Gulp-Tasks ohne Fehler durch, allerdings wird man hier oftmals getäuscht in dem Fall, dass von einander abhängige Tasks aufruft. Es gibt bisher leider keine Prüfung, ob etwas in einer alten Syntax formuliert ist, ein Upgrade von Gulp3 nach Gulp4 ist somit etwas holprig, bringt dafür aber erhebliche Verbesserung für die Formulierung der eigenen Pipeline und deren Tasks.

So richtig spannend und anspruchsvoll wird es aber erst, wenn man "Reihenfolge" und "Gleichzeitigkeit" mischt:

gulp.task("prepareContent",
    gulp.series(
        "readNavigationStructure",
        "readSortedNavigationStructure",
        gulp.parallel("renderHtaccess", "renderSitemap", "renderHumansTXT", "readBlogEntries")
    )
);

Umfangreiches Content-Update meines Portfolios

Mein bisherige Portfolio-Bereich war eher klein und eigentlich bisher auch ein großer Platzhalter, doch dies habe ich nun erfoglreich mit Inhalt befüllt. Anders als vielleicht erwartet, handelt es sich hierbei nicht um Beispiel-Code, sondern eher um sowas wie eine Auflistung meiner Kompetenzen und bisherigen Projekterfahrung. Ich bin mal gespannt, wie schnell Google (Webmasters Tools aka SearchConsole) mir entsprechende Hits für diese Seiten liefern wird.

Ausblicke

Google belohnt Rich-Snippet-Integrationen und fördert hierbei das Dateiformat JSON-LD (JavaScript Object Notation - Linked Data), deswegen möchte ich meine Blog-Postings bald einzeln anspringbar (ähnlich der Idee, wie es im fefe-Blog auch gemacht wird) und mit entsprechenden JSON-LD-Einträgen verfügbar machen. Hierfür muss ich ein paar Anpassungen an meinen Navigationsalgorithmen machen, sowie bei dem Rausschreiben der Blog-Posts. Bisher werden alle Blog-Posts nur auf einer Seite pro Jahr gesammelt, sind aber nicht einzeln anspringbar, dies soll sich nun bald ändern.

Sowohl für das JavaFX-Gradle-Plugin als auch für das JavaFX-Maven-Plugin werde ich ebenfalls bald einen eigenen Task bzw. eigenes Goal erstellen, mit dem man häufig benötigte Daten zusammenstellen lassen kann, wenn man ein Problem hat. Oftmals liegt es an einer alten JDK-Version, oder aber dass JAVA_HOME nicht vernüntig auf das JDK zeigt sondern auf die JRE.
Um die Qualität der zukünftigen Bug-Tickets zu steigern, werde ich einen Art "Diagnostik"-Task/-Goal einführen, welche diese Informationen alle zusammenstellt, sodass man diese per Copy-n-Paste in das Ticket packen kann. Dies wird mit Sicherheit nicht bedeuten, dass keine Tickets mehr angenommen werden, die diese Informationen NICHT enthalten, aber es soll die Chance erhöhen, dass viele Dinge direkt im Ticket zur Verfügung stehen um gerade bei den Features bei diversen Versionssprüngen genauer untersuchen zu können. Leider ist das "javapackager" von Oracle alles andere als konsequent und birgt immer wieder eine Überraschung ;) auch positive z.B. durch neue Features.

work in progress