25. Oktober 2018

JPG with OpenJDK

Some articles in the web (e.g. on stack overflow) claim that OpenJDK does not have support to write JPG images.

Looking into it, I foudn that there is a JPEGImageWriter and a com.sun.imageio.plugins.jpeg.JPEG included with OpenJDK 11 (looking at version 11.0.1).

But this code does not produce an JPG as expeced:

BufferedImage bufferedImage = generateImage(new Date());

String fileName = "SampleFile";

if(!ImageIO.write(bufferedImage, "jpeg", new File(fileName + ".jpg"))){
    System.out.println("No writer for JPG found!");

It rather claims „No writer for JPG found!“ :(

Debugging a bit shows, that the JPEG ImageWriter ist available but not loaded due to the test image data I create in the generateImage() method above.

There, BufferedImage is created using

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)

But,  the type TYPE_INT_ARGB is not supported with JEPG and thus, the JPEGWriter not selected as a valid writer.

Changing the type to


fixes this and I’m able to write JPG with OpenJDK – hooray! ;-)

Thus, the claim that OpenJDK is not able to write JPG is not true (anymore), one just need to be aware to the implications the various ImageTypes have.

That also mean that I’ve been wrong last night when I repeated what I read about OpenJDK being incapable of writing JPG in Binärgewitter Podcast, Episode 214 (yet to be released, will update the link as soon as possible). Sorry for that!

Have fun and keep coding! ;-)

24. August 2018

Kubernetes on a RaspberryPi cluster

Recently, I decided to revive the raspberry pi cluster I used for Kubernetes-Experiments a while ago.

The re-install based on the Hypriot images and installation manual was pretty much straight forward.
Even though I encountered two strange things:

  1. Two of my RaspberryPi don’t want to connect via wifi. They have the very same config set as all others. Seems like they have brokern wifi chips.
  2. The sample configuration for the Ingress object that uses Traefik a a load balancer didn’t work as described – it just says „404 page not found“ instead of showing the acual sample page.
    Reason here is the Error

    ERROR: logging before flag.Parse: E0824 11:36:50.295344 1 reflector.go:199] Failed to list *v1beta1.Ingress: ingresses.extensions is forbidden: User „system:serviceaccount:kube-system:default“ cannot list ingresses.extensions at the cluster scope

    which I couldn’t fix right away and decided to learn on that at a later stage.

Before really starting to use the cluster, the first bullet point to me was to set up a registry that is used to pull the images from. First thing, to set up a registry, is faily easy with the registry docker image. On top of that, QNAP provides an „app“ (which is, in their context, a docker-compose to wire a set of containers together) that bundles the registry with an nginx and an redis cache.

Now, the actually point was how to tell the nodes to pull from that registry. First I thought I need to tell kubernetes. But as kubernetes delegates the docker commands to the docker instance running on each node, it’s a docker config setting.

By the way: To execute commands on all nodes at the same time, tmux-cssh has become a good friend of mine ;-)
Now, to configure my NAS as a trusted registry, I have to install the ca of the self-signed certificate on my nodes:

sudo -i
mkdir -p /etc/docker/certs.d/
ln -s /etc/docker/certs.d/ /etc/docker/certs.d/NAShostname:6088
scp admin@ /etc/docker/certs.d/

The link set using the „NAShostname“ is so that I can also use the name instead of the IP.

After that I’m able to push and pull images from & to my local private registry.

Let’s say I’d build a little application and pushed an image for that application based on a arm32v7 base image to my registry at „NAShostname:6088/armhf/application“. (Remember: CPU architecture matters! So you can’t use images build and running on your x86 or amd64 machine an a ARM based RaspberryPi!)
To run that application on my kubernetes cluster I have to:

Create a deployment

kubectl run demo --image=NAShostname:6088/armhf/application:latest --replicas=3 --port 8080

Expose that deployment to the outside world

kubectl expose deployment demo --type=LoadBalancer

The thing now is that the service created to expose the deployment never gets an IP address assigned. Status reads like:

$ kubectl get services demo
NAME         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
demo         LoadBalancer   <pending>     8080:32390/TCP   26m

To solve this, we need to define an external IP manually. THe tricky part is to know what valid external IPs are. It turns out that only thos from node that are running one of the deployments pods are working.

Lets find out waht these are:

$ kubectl get pods -o=wide
NAME                          READY     STATUS    RESTARTS   AGE       IP           NODE      NOMINATED NODE
demo                          1/1       Running   0          1h   node04    none
demo                          1/1       Running   0          1h   node05    none
demo                          1/1       Running   0          1h   node02    none
$ kubectl get nodes --output=wide
node02    Ready     none    11d  v1.11.2   none       Raspbian GNU/Linux 9 (stretch)  4.14.34-hypriotos-v7+  docker://18.6.0
node03    Ready     none    11d  v1.11.2   none       Raspbian GNU/Linux 9 (stretch)  4.14.34-hypriotos-v7+  docker://18.6.0
node04    Ready     none    11d  v1.11.2   none       Raspbian GNU/Linux 9 (stretch)  4.14.34-hypriotos-v7+  docker://18.6.0
node05    Ready     none    11d  v1.11.2   none       Raspbian GNU/Linux 9 (stretch)  4.14.34-hypriotos-v7+  docker://18.6.0
node06    Ready     master    11d  v1.11.2   none       Raspbian GNU/Linux 9 (stretch)  4.14.34-hypriotos-v7+  docker://18.6.0

Thus, we can use .105, .101 and .100 to expose our service:

$ kubectl edit services demo

Add the list „externalIPs:“:

apiVersion: v1 
kind: Service 
  creationTimestamp: 2018-08-19T08:20:03Z 
    run: demo 
  name: demo 
  namespace: default 
  resourceVersion: "1585558" 
  selfLink: /api/v1/namespaces/default/services/jetty-demo 
  uid: 804d3b3a-a776-11e8-a44f-b827eb388bbf 
  externalTrafficPolicy: Cluster 
  - nodePort: 31285 
    port: 8080 
    protocol: TCP 
    targetPort: 8080 
    run: demo 
  sessionAffinity: None 
  type: LoadBalancer 
  loadBalancer: {}

After saving, we can finally access the application via one of the IPs on port 8080.

For me, that feels somewhat unstatifying as by the binding of the pod ip to access the application the flexibility promised by kubernetes is vanished. Thus I suspect the cluster is not working as expected at this point and there is a lot of stuff to learn – if you actually want to setup your own kubernetes.
Most of the times, I’ve been working with it as a hosted solution or in context of OpenShift – and thats probably also the reason why setting up and running k8s ist not so well documented that acutally using it afterwards.

If someone comes along these lines and has some suggestions or questions – I’d be very happy to see your comment ;-)

More interesting stuff:
* Build containers faster with Jib, a Google image build tool for Java applications
* Setup k8s on pi using Ansible

21. Juni 2018

RegExp in Aktion: Suffix als Filterkriterium

Immer mal wieder bin ich froh, das es RegularExpressions gibt. Sie helfen sehr dabei, schnell Änderungen in umfangreichen, strukturierten Texten (z.B. Quellcode ;-) ) vorzunehmen.

Ab und zu passiert es mir, das ich mir einen regulären Ausdruck erarbeite und 2 Wochen später einen ähnlichen Fall habe, den RegExp aber nicht dokumentiert habe – und mir nochmal erarbeite. Das hilft zwar, das Schreiben regulärer Ausdrückezu üben, ist aber nicht unbedingt effizient ;-)

Daher fange ich mal an den Ausdruck, der mir heute geholfen hat festzuhalten:

Es geht darum, alle vorkommen von „document“ mit „documents“ zu ersetzen. Natürlich sollen dabei die Vorkommen, bei denen das „s“ bereits angehängt ist, nicht ersetzt werden um nicht mit einem „documentss“ zu enden. Zum Testen als die Varianten:


Des Rätsels Lösung ist der Ausdruck


Den man z.B. im Sublime Editor oder in IntelliJ IDEA problemlos verwenden kann, wie im Screenshot zu sehen.

Bei dem ?! handelt es sich um ein sogenanntes „negative lookahead“, mehr dazu unter

Have fun! :)

13. Juni 2018 Size Limit for FileUploads

Recently, I’ve been tinkering with a new application framework which looks quite promising so far.
A good introduction is provided in the documentation, by the examples on GitHub and some nice articles on the web like „Getting Started with Micronaut“ by Jonas Havers.

I had to dig a little bit to find out some things when implementing a file upload. So here are some notes about it, maybe it help ssomeone else ;)

The basic documentation on file uploads provided by the main doc is a good starting point.

Then one might stuble quickly on a fairly well known exception like:

{"_links":{"self":{"href":"/upload","templated":false}},"message":"The received length [1049482] exceeds the maximum content length [1048576]"}

Not straight-forward to find is that the section „body annotations“ provides an answer on what the config setting to adjust this is. Also, it hints for the annotation @Size to provide a value per endpoint which is useful to set different limits in differnt contexts.

For an example how the config is done via an application.yml file can be found in the serverConfiguration paragraph of the documentation.

An important thing to note is when dealing with form based file uploads, you might use enctype="multipart/form-data" and thus need another attribute to set the upload limit. That would be micronaut.server.multipart.maxFileSize. Thus, I ended up with with the config:

        name: sample-application
        maxRequestSize: 100MB
          maxFileSize: 100MB

Also, a a final note for this post, let me remind you that as Micronaut is fairly young, it helps to keep an eye on the FAQ and Problems section. I had the problem regarding the startup time, for example, for which the solution is provided there. So easy to solve if you know what to do ;-)

27. April 2018

Von Autofriedhöfen und Zukunftstechnologien

Ich finde es spannend, den sich gerade vollziehenden Wandel in Sachen Transport und Fortbewegung mitzuverfolgen, der nicht nur durch rapide Umwälzungen im Kontext von Automatisierung und moderner Sensortechnik (für autonomes Fahren), sondern auch durch bisweilen grotesk anmutende Verhaltensweisen der kroßen und kleinen Aktuere auf dieser Bühne geprägt wird. Der Existenzkampf um den Verbrennungmotor ist da nur ein Beispiel. Der Dieselskandel hat das Thema vielleicht mehr ins Zentrum der Aufmerksamkeit gerückt, ist aber auch eher ein Nebenschauplatz. Dennoch gab es aus dem Kontext in den vergangenen Tagen ein paar bemerkenswerte Schlagzeilen, die ich gerne in Kombination festhalten möchte:

1. VW-Friedhöfe
Dieser Tage bin ich auf ein beeindruckendes Video von BBC gestoßen:

Die volle Meldung dazu, inkl. längerem Video, findet sich bei Reuters:
Reuters: VW storing around 300,000 diesels at 37 facilities around U.S.

2. Der Umsatzrekord

Diese Bilder stehen für mich in krassem Kontrast zu den gemeldeten Umsatzrekord von VW – wird vermutlich daran liegen das sie diese „Aufarbeitung des Dieselskandels“ nicht unmittelbar und vollständig in der aktuellen Bilanz niederschlägt. Ist ja auch mehr ein Prozess als ein Einmaleffekt ;-)

3. Die rettende Erfindung von Bosch

Doch es gibt Hoffnung für die vielen Autos – denn Bosch scheint ein Heilmittel gefunden zu haben, wie heise berichtet: Licht am Diesel-Horizont: Bosch senkt Abgaswerte dramatisch unter 1/10 des geforderten Wertes.

und nu?

Es bleibt Spannend, ob die Bosch-Technologie tatsächlich noch für höhere Wellen sorgen wird oder VW es gelingt damit den Kopf aus der Schlinge zu ziehen und vielleicht wieder Richtung Technologie- und damit Markführerschaft zu drängen – oder ist die E-Welle doch schon so groß, das man Diskussionen um Verbrennungsantriebe nurnoch Unterhaltungswert oder ein Nieschendasein zurechnen sollte? – Nachrichten u.a. aus China als riesigem Absatzmarkt lassen es vermuten und die Technologieforschritte scheinen Skeptikern („die Reichweite wie niw ausreichen!“) immer weiter den Wind aus den Segeln zu nehmen.

9. April 2018

Action required: Reform des EU Urheberrechts

Die EU plant eine Urheberrechtsreform, die durch den Streit einiger Großkonzerne (Google/YouTube gegen Content-Industrie (Verlage, Plattenlabels, Filmindustire)) ins Rollen gebracht wurde.

Diese Reform ist durch die Interessen eben dieser Aktuere geprägt, insbesondere derer die sich durch aktuelle technische Entwicklungen überrollt fühlen und selbst keine bessere Anwort finden als mit Verboten und Gesetzesänderungen ihr mit-überrollten Geschäftsmodelle sichern lassen zu wollen. Also der Content-Industrie.
Durch diese Prägung bzw. das Lobbying dieser Aktuere sind viele Aspekte, insbesondere die nicht-kommerziellen und künstlerischen, bei der Konzeption der Reform unberücksichtigt geblieben. (Und durch die Tatsache das der CDUler Axel Voss in einem unverantwortlichen Zug den Input der beteiligten Parlamentarier ignoriert und die Vorlage der Komission 1:1 übernommen hat. CDU/CSU wiedersprechen damit schon wenige Stunden nach Vereidigung der GroKo Regierung aus dem Koalitionsvertrag. Ein Böses Omen für die nächsten 4 Jahre…)

Folge ist, dass die Reform, sollte sie wie derzeit geplant in Kraft treten, viele Seiteneffekte hat, die der Zivielgesellschft und auch vielen Teilen der zunehmend digitalisierten Geschäftswelt schaden würden.

Ein Teil der geplanten Reform ist das in Kraft treten der Pflicht für Uploadfilter. Diese würde dazu führen, das Plattformen wie GitHub, auf denen unzählige Menschen zusammenarbeiten um Open-Source-Software zu erstellen, lange nichtmehr so gut funktionieren würden wie bisher. Der Grund dafür liegt darin, das automatische Filtern nach Mustern arbeiten und viele Aspekte nicht berücktigen können. So würde auf einmal Teile der Uploads blockiert (z.B. weil sie Inhalte falsch zuordnen und für illegal halten) und damit die effektive Zusammenarbeit torpediert.

Die Open-Source-Software Szene ist also in ihrer Existenz bedroht und damit alle die darauf aufbauen – und das sind Status-Quo (dank Digitalisierung) praktisch alle.

Also, es ist Zeit, was zu tun.


1. Unterschreibe direkt den offenen Brief unter
2. Nimm dir 15 Minuten Zeit und rufe einen Abgeordneten an – das ist laut der EU Parlamentarierin Julia Reda die effektivste Methode, die Notwendige Aufmerksamkeit zu bekommen.
3. Schick einen Tweet an die Europaabgeordneten:


* Süddeutsche: Das Netz der schwarzen Listen
* Twitter Hashtag „#WhatTheVoss“
* Comic: Die Diskussion in einer EU-Arbeitsgruppe
* Article 13 can kill my Startup

26. Februar 2018

Das Microsoft Dilemma – Die Gefahr für Europa, zur Kolonie zu werden

In der ARD Mediathek findet sich zur Zeit mal wieder eine sehr interessante Doku zu einem Thema, um das in den letzten Jahren sehr leise geworden ist: Die Monopolstellung von Microsoft in vielen IT Bereichen und die daraus resultierenden politischen, wirtschaftlichen und gesellschaftlichen Gefahren.

Zur Doku: Das Microsoft Dilemma (Mediathek WebView)

Wichtiger Punkt dabei ist, das Mircosoft nicht der alleinige Player ist, den man im Auge haben und kritisch beobachten muss. Die anderen Konzerne, die versuchen Monopole zu etablieren sind es genauso. Und auch wenn Google, Facebook und co. in der Reportage als die Konzerne benannt werden, die OpenSource Software intensiv nutzen, darf man nicht dem Irrglauben verfallen sie würden sich auch nur einen Deut besser gebaren.

mehr dazu:

Artikel bei Heise zur Dokuund noch einer.

RBB Radio Interview zur Dokumentation

Sueddeutsche Zeitung: Der Staat in Microsofts Hand

29. November 2017

Bose Quiet Comfort 35: Aktuell ist nicht gleich aktuell

Wenn man schauen will, ob seine Bose Hardware – in meinem Fall die Quiet Comfort 35 Kopfhörer (Amazon Link) – mit ihrer Firmware auf dem aktuellen Stand ist, kann man sich meiner Erfahrung nach nicht auf die Bose Connect App verlassen.

Die hat nämlich eben fröhlich behauptet „Ihr Produkt ist auf dem aktuellen Stand.“. Als ich dann doch noch über die Updater Website in Kombination mit des dort zum Download angebotenen „Updater“ geprüft habe, bekam ich ein Update angeboten – sogar mit einem sehr deutlichen Versionssprung von 1.1.2 auf 1.3.4 . Da hat die App wohl ihren Zweck verfehlt :(

Ich bin jetzt mal gespannt, ob sich mit diesem Update, was ich durch die regelmäßige überprüfung mit iPad erst viel später als möglich mitbekommen habe, auch die wenigen Unschönheiten (Störgeräusche beim Aufbau von Sprachverbindungen) der Kopfhörer bereinigt haben, die mich noch stören…ansonsten sind es wirklich gute, zuverlässige Kopfhörer mit Noise Canceling :)

21. November 2017

Plastikmüll in Weltmeeren

Kürzlich bin ich durch ein Tweet von ZDF heute auf einen Clip aufmerksam geworden, der zeigt wieviel Plastikmüll sich in den Gewässern des Planeten sammelt.

Dabei musste ich mal wieder an das Projekt The Ocean Cleanup denken, das wir von einiger Zeit unterstützt haben. Und da meine Hoffnung, das die Menschheit sich kurz- oder mittelfristig besinnt und Plastikproduzenten und -verbrauchern auch konsequent die vollständige Entsorgung/Aufbereitung anlastet (und das weltweit 🙄), begrenzt ist, sehe ich dieses Projekt fast als die einzige Möglichkeit zumindest etwas gegenzusteuern.

Woher der ganze Müll kommt? Eine Studie sagt hauptsächlich aus Flüssen Asiens stammen soll. Doch werd sich in Europa jetzt entspannt zurücklehen will, sollte vorsichtig sein, denn „denn wir exportieren jede Menge Plastikmüll ins Ausland und China ist der weltgrößte Müll-Importeur.“. Wir sammeln in den Gelben Säcken also Müll für den Export.
Die Süddeutsche Online berichtete kürzlich übrigens über den Jangtse und betont das man der Konzentration auf die großen Flüsse vielleicht das Positive abgewinnen kann, das erste Gegenmaßnahmen direkt sehr effizient sein könnten, da an nur wenigen Stellen viel bewirken kann.

Doch noch weiss man nicht viel von diesen Gegenmaßnahmen, daher mein Aufruf: Unterstützt The Ocean Cleanup!

Nachtrag: hat das Thema auch aufgegriffen und berichtet das Deutsche im EU-Vergleich viel Plastikmüll produzieren

20. November 2017

JCE ab Java 8u151 per Property aktivieren

Gute Neuigkeiten: Mit Java 8 Update 151 kann man die Java Cryptography Extension (JCE) per property aktivieren, da Oracle den Mechanismus zum handling desselben, der in Java 9 etabliert wurde, auf Java8 zurückportiert hat.
Auf macOS wird so das Homebrew Cask jce-unlimited-strength-policy8 überflüssig.

Um JCE in Java 8 Update 151 oder neuer zu aktivieren, braucht man nur noch das folgende Property zu setzen:


Z.b. in $JAVA_HOME/jre/lib/security/, es gibt wie in den Kommentaren in jener Datei auch nachzulesen ist, aber auch andere Stellen an denen man diese Einstellungen vornehmen kann.

Das Homebrew Cask wurde auch bereits entfernt, also nicht wundern wenn ein Reinstall nach einem JavaUpgrade fehlschlägt. ;-) wird erstellt mit WordPress
Beiträge (RSS) und Kommentare (RSS)

(c) 2005 - 2015 Markus Schlichting