Archiv für den Autor: Christoph Giesche

Über Christoph Giesche

Christoph Giesche war seit 2007 in verschiedenen Bereichen als Java Softwareentwickler tätig und ist seit 2012 freiberuflicher Java Consultant mit dem Schwerpunkt Backendentwicklung (JEE, Spring). Pofil

JavaFx – Using FilteredList in ListViews

filteredlistI just came across the problem, that I wanted to show parts of a single “huge” List in different JavaFx ListViews divided by their type. Additionally I wanted the ListViews to be updated after I added or removed items from the initial List, without the need of manually adding and removing items from sublists.

The solution is quite simple: For the complete list of Items you should use an ObservableList. To retrieve a subset of this list, you can use the filtered() method. This method takes a Predicate as parameter. The Predicate’s test() method will be called for each item in the initial list. Only if this method returns true, the item will be part of the filtered list. The best thing is: If you change items in the main list, the filteres lists will be updated automatically.

Now, you can simply set the FilteredLists as the ListView’s model.

Take a look at the following simple example. It requires Java8 to run because of the lambda expressions, but they can be easily replaced by anonymous implementations of the Predicate interface.

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
 
public class Labor extends Application {
 
  public static void main(String[] args) {
    launch(args);
  }
 
  @Override
  public void start(final Stage primaryStage) throws Exception {
 
    final ObservableList<String> stringList = FXCollections.observableArrayList("Hans", "Peter");
    final VBox rootPane = new VBox();
    final HBox listHbox = new HBox();
    final Button addButton = new Button("Add name");
    final ListView<String> listViewOnlyH = new ListView<>();
    final ListView<String> listViewOthers = new ListView<>();
    final TextField textField = new TextField();
 
    addButton.setOnAction(event -> stringList.add(textField.getText()));
    listHbox.getChildren().addAll(listViewOnlyH, listViewOthers);
    rootPane.getChildren().add(listHbox);
    rootPane.getChildren().add(textField);
    rootPane.getChildren().add(addButton);
 
    listViewOnlyH.setItems(stringList.filtered(string -> string.startsWith("H")));
    listViewOthers.setItems(stringList.filtered(string -> !string.startsWith("H")));
    primaryStage.setScene(new Scene(rootPane));
    primaryStage.show();
  }
 
}

HP Microserver N40L NAS Projekt (Teil 2)

Hardware

Der N40L hat mich positiv überrascht. Die Verarbeitungsqualität ist wirklich hervorragend. Für die gesamte Einrichtung habe ich keinen Schraubenzieher benötigt. Auf der Innenseite der Tür des Servers sind sowohl alle benötigten Schrauben, als auch das einzig wichtige Werkzeug zu finden.

Natürlich ist der Server von innen dicht mit Hardware und den Festplattenschächten befüllt. Viel Platz zum Basteln kann man nicht erwarten. Die Installation der Tv-Karte in einem der beiden PCIe-Steckplätze war anspruchsvoll und ist eher nichts für Grobmotoriker. Glücklicherweise kann man das Gerät ohne Probleme direkt vor sich auf den Tisch stellen um (relativ) bequem darin zu arbeiten.

Hardwareseitig haben sich durch die unverhoffte Existenz eines DVD-Laufwerks bei Auslieferung des Servers ein paar kleinere Änderungen ergeben:

  • Das eingebaute DVD-Laufwerk habe ich durch ein Blu-Ray Laufwerk ausgetauscht (Da keine Frontblende für den Laufwerksschacht mitgeliefert wurde, war “kein optisches Laufwerk” keine Option.
  • Die System-SSD habe ich auf dem Blu-Ray Laufwerk platziert und über ein Adapterkabel an den eSATA-Port des Servers angeschlossen, da alle internen SATA-Ports belegt sind.

Im Betrieb macht der Server zwar Lüftergeräusche, solange man ihn nicht im Schlafzimmer stehen hat, fallen diese aber nicht besonders auf.

Software

Entgegen meiner ursprünglichen Planung dient jetzt ein “normaler” Ubuntu Server als Betriebssystem. OpenMediaVault ist zwar als reine NAS-Lösung durchaus zu empfehlen, allerdings reagiert die Weboberfläche sehr sensibel auf manuelle Änderungen der Konfiguration, die ich z.B. für die TV-Karte und TvHeadend vornehmen musste.

Die drei Datenplatten sind als RAID5-Array konfiguriert und über NFS und Samba erreichbar. Teile der Daten (die wichtigen) werden täglich mit rsync auf einen externen Server gesichert.

So eingerichtet läuft das NAS jetzt rund um die Uhr und leistet treue Dienste – so problemlos, dass es schon fast langweilig wird. :)

HP Microserver N40L NAS Projekt (Teil 1)

HP ProLiant N40lDa es auf meinem Synology-NAS (211j) mit seinen zwei 1TB-Festplatten langsam eng wird, und ein Upgrade auf größere Platten nur kurzfristig Linderung bringen würde, habe ich mich entschlossen auf ein Eigenbau NAS umzusteigen. Als Basis wird ein HP ProLiant Microserver N40l dienen. Ein Nachfolgemodell ist zwar schon auf dem Markt, bringt aber trotz des nahezu doppelten Preises nur wenig mehr Leistung, so dass ich an dieser Stelle bewusst gespart habe.

Als Systemfestplatte kommt eine günstige Kingston 60GB SSD zum Einsatz. Genau wie bei meinem HTPC wird darauf nur das OS laufen – die Geschwindigkeit und Kapazität sind bei dem geplanten (nahezu) 24/7 Betrieb eher nebensächlich. Um keinen der vier HDD-Schächte zu blockieren, wird sie wahrscheinlich “irgendwo” im Gehäuse ihren Platz finden um den Schacht für das optische Laufwerk nicht zu blockieren.

WD NAS 3000Das wichtigste am NAS sind natürlich die Festplatten. Ich habe mich nach reichlicher Recherche für 3TB-Patten von Western Digital (WD30EFRX) entschieden, die für 24/7 Betrieb zertifiziert sind. Die sparsamen und günstigeren “Green”-Varianten haben die Angewohnheit, die Leseköpfe nach zehn Sekunden Inaktivität in die Halteposition zu fahren, was für die Lebensdauer äußerst nachteilig ist. Zuerst werde ich drei dieser Platten im RAID-5 betreiben, somit stehen mir anfangs 6TB an Speicherplatz zur Verfügung. Bei Bedarf kann ich den Platz durch eine weitere Platte auf 9TB erhöhen, was mir angesichts meines noch nicht ganz gefüllten 1TB-NAS für den Anfang etwas übertrieben erscheint.

Neben seiner Haupaufgabe als NAS zu dienen soll der Server zusätzlich als TV-Backend dienen. Hier wird HTS TvHeadend in Verbindung mit einer DigitalDevices Cine CT V6 Twin Tuner zum Einsatz kommen. Zusammen mit XBMC ein unschlagbares Team :).

Als Betriebssystem wird OpenMediaVault, eine auf Debian basierende, für NAS optimierte Linux Distribution installiert. Anpassungen bezüglich der TV-Funktionalität lassen sich dank APT recht komfortabel bewerkstelligen.

In den nächsten Tagen wird die Hardware bei mir eintreffen. Ich werde berichten :)

Synology DownloadStation with JDownloader click’n'load

UPDATE:
Since Sep. 28, you can find the Download of the newest Version of JdAdapter here!

Since a few months, I am a proud owner of a Synology NAS (211j). It has many useful features and works like a charme. One important feature is the DownloadStation which supports downloading from many different hosters even with using premium accounts.
Although synology provides software to redirect downloads from your browser to the DownloadStation, I was missing a special feature: Many sites offer support for JDownloader’s click’n'load feature which adds a list of URLs to be downloaded to the JDownloader application. Because I was not able to find a plugin or application capable of decrypting and adding download URLs to the Synology DownloadStation, I decided to create it on my own.

First, I created a library (synolib) that encapsulates all the HTTP communication to the DownloadRedirector API (CGI) and provides a nice Java interface for use in application. It currently supports login, adding a download URL and retrieving a list of all current downloads.
The main program is called JdAdapter – a webapp that implements the click’n'load functionality of JDownloader. When clicking on a click’n'load button, it decrypts the URLs and adds them to the DownloadStation via synolib.

The software is written in plain Java and thus runs on nearly every operating system.

Download

Please find the newest Version of JdAdapter here.

Sources (SVN)

Weiterlesen

Simple edge detection invented “from scratch”.

As I am mostly working on middlewares and webapplications at work, I decided to try out something different this weekend. A long time ago I had the idea of writing a software that is able to recognize license plates. Today I know that this is not a trivial task – but just to be sure, I tried something like that:

Before you can start to analyze the content of a picture, you often have to detect edges in it. So a simple edge detection was my main target for today. As you can see in the following pictures, it works quite well:

You can see four images in the application screenshot – the whole process of my edge detection:

  • Top left: Original image
  • Top right: Greyscale version of the image
  • Bottom left: Gaussian blur on greyscale image (reduces noise)
  • Bottom right: Edge detection applied

Another example picture:

As you can see, the edge detection currently is rather inaccurate but maybe I will find some time and motivation to improve it.

For now, the code looks like this:

Create greyscale copy of the image

BufferedImage src = (BufferedImage) srcImage;
BufferedImage targetImg = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
 
for (int x = 0; x < src.getWidth(); x++) {
    for (int y = 0; y < src.getHeight(); y++) {
        Color srcCol = new Color(src.getRGB(x, y));
        int greyVal = (int) (0.2989 * srcCol.getRed() + 0.5870 * srcCol.getGreen() + 0.1140 * srcCol.getBlue());
        targetImg.getRaster().setSample(x, y, 0, greyVal);
    }
}
 
return targetImg;

Applying gaussian blur

final BufferedImage src = (BufferedImage) srcImage;
final int srcWidth = src.getWidth();
final int srcHeight = src.getHeight();
long startAt = System.currentTimeMillis();
 
int[][] matrix = {{1,2,1},
                  {2,4,2},
                  {1,2,1}};
 
Raster raster = src.getRaster();
BufferedImage targetImg = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_BYTE_GRAY);
 
for (int x = 0; x < srcWidth; x++) {
    for (int y = 0; y < srcHeight; y++) {
 
        int factor = 0;
        int pixelSum = 0;
        for (int ix = 0; ix < matrix.length; ix++) {
            for (int iy = 0; iy < matrix.length; iy++) {
                int xRead = x - 2 + ix;
                int yRead = y - 2 + iy;
 
                if (xRead >= 0 && yRead >= 0 && xRead < srcWidth && yRead < srcHeight) {
                    int weight = matrix[ix][iy];
                    pixelSum = pixelSum + (weight * raster.getSample(xRead, yRead, 0));
                    factor += weight;
                }
            }
        }
        int pixelRgbVal = pixelSum / factor;
        targetImg.getRaster().setSample(x, y, 0, pixelRgbVal);
    }
}
 
long stopAt = System.currentTimeMillis();        
System.out.println("Duration for blur: " + (stopAt - startAt) + " ms");
 
return targetImg;

Detect edges (primitive way)

        final BufferedImage srcImg = (BufferedImage) src;
final int srcWidth = srcImg.getWidth();
final int srcHeight = srcImg.getHeight();
 
BufferedImage targetImg = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_RGB);
Raster srcRaster = srcImg.getRaster();
 
for (int x = 0; x < srcWidth; x++) {
    for (int y = 0; y < srcHeight; y++) {
        if (x + 1 < srcImg.getWidth()) {
            if (Math.abs(srcRaster.getSample(x, y, 0) - srcRaster.getSample(x +1, y, 0)) > schwelle) {
                targetImg.setRGB(x, y, Color.WHITE.getRGB());
            }
        }
        if (y + 1 < srcImg.getHeight()) {
            if (Math.abs(srcRaster.getSample(x, y, 0) - srcRaster.getSample(x, y + 1, 0)) > schwelle) {
                targetImg.setRGB(x, y, Color.WHITE.getRGB());
            }
        }
    }
}
 
return targetImg;

DynamicProxies – The magic behind OR-mappers and mocking frameworks

Did you ever wonder how mocking frameworks “create” instances of you interfaces? Or how OR-mappers like Hibernate give you entities with lazily loaded references to another of your entities that throw the well known LazyInitializationException when the session is already closed?

The answer is: Dynamic proxies.

As part of the reflection package in the JDK, the classes around java.lang.reflect.Proxy allow you to create instances of interfaces – even if there is no implementation of that interface present in the classpath. These instances are called “proxy-instances”.

Each proxy-instance has assigned an implementation of the interface java.lang.reflect.InvocationHandler. The handler gets informed about every method that is called on the proxy-instance (including arguments, return types etc.). This allows you to dynamically create “runtime implementations” of interfaces, giving them a custom behavior (testing frameworks like JUnit – record, replay, etc.) or just to intercept/modify calls to a “real” instance (AOP-like behavior).

Here is an example to get an idea of how (easy) it works:

Main class

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
/**
 * This class contains a main method that creates a dynamic proxy.
 * 
 * @author Christoph Giesche
 */
public class ProxySample {
 
    public static void main(String[] args) {
 
        //Create an instance of our InvocationHandler
        InvocationHandler handler = new UselessHandler();
 
        //Create a "dynamic proxy" of our useless interface
        Object proxy = Proxy.newProxyInstance(
                Useless.class.getClassLoader(), 
                new Class[] {Useless.class}, 
                handler);
 
        //Cast the proxy instance to our Useless interface
        Useless uselessProxy = (Useless) proxy;
 
        //Call some methods on our instance
        uselessProxy.getStatus();
        uselessProxy.setSomeValue("foobar");
        uselessProxy.toString();
    }
}

Interface that is used to create proxy-instance

package de.perdoctus.examples;
 
/**
 * Just a useless interface to demonstrate dynamic proxies.
 * 
 * @author Christoph Giesche
 */
public interface Useless {
    void getStatus();
    void setSomeValue(String value);
}

An invocation handler telling you what is going on

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
/**
 * UselessHandler will handle all method calls to our dynamic proxy. This
 * handler can be assigned to different proxy instances.
 * 
 * @author Christoph Giesche
 */
public class UselessHandler implements InvocationHandler {
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
        StringBuilder sb = new StringBuilder();
 
        sb.append("Method '")
          .append(method.getName())
          .append("' was called ");
 
        if (args != null) {
            sb.append("with arguments:");
            for (Object arg : args) {
                sb.append('\n');
                sb.append(arg.getClass().getSimpleName())
                  .append(" = ")
                  .append(arg.toString());
            }
        } else {
            sb.append("without arguments.");
        }
 
        sb.append("\nThe method has the return type '")
          .append(method.getReturnType())
          .append("'\n");
 
        System.out.println(sb.toString());
        return null;
    }
 
}

Result when running main class

Method 'getStatus' was called without arguments.
The method has the return type 'void'

Method 'setSomeValue' was called with arguments:
String = foobar
The method has the return type 'void'

Method 'toString' was called without arguments.
The method has the return type 'class java.lang.String'

How to REST – Useful articles

If you are planning to use REST in your projects, I strongly recommend you to get in touch with it’s principles. As REST makes excessive use of the standard HTTP protocol, aspects like caching can be delegated to one of the various HTTP caching products.

Below, you can find some very useful articles about the principles of REST including versioning and common mistakes when implementing a REStful service.

After having read all of those articles, you may have a more precise understanding of what RESTful interfaces should look like and what advantages you have due to the fact that it is based on HTTP.

Evaluating JavaScript from within your Java application

Sometimes you may wish to include JavaScript, Groovy or other scripting languages features within your Java application. The package javax.script offers an API for exactly that purpose.

The JRE provides a JavaScript engine (Mozilla’s Rhino) by default. Additional engines are listed here.

A simple example of how to evaluate a JavaScript in Java is shown below. If needed, you have access to the complete Java API from within your script.

package de.perdoctus.examples;
 
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
 
/**
 * @author Christoph Giesche
 */
public class ScriptManagerExample {
 
    public static void main(String[] args) {
        //create a ScriptEngineManager
        ScriptEngineManager sem = new ScriptEngineManager();
 
        //obtain a JavaScript engine from the manager
        ScriptEngine engine = sem.getEngineByName("JavaScript");
 
        //put some attributes to the engine's context
        ScriptContext context = engine.getContext();
        context.setAttribute("netPrice", 10.92, ScriptContext.ENGINE_SCOPE);
        context.setAttribute("vat", 19, ScriptContext.ENGINE_SCOPE);
 
        //Execute some JavaScript using our attributes.
        try {
            engine.eval("var price = netPrice + (netPrice * vat / 100)");
        } catch (ScriptException ex) {
            System.err.println(ex);
        }
 
        //retrieve attribute "price" from engine's context
        Double price = (Double) context.getAttribute("price");
 
        System.out.println("Price including vat: " + price);
    }
}