Bibliothek zum Einlesen von MediaWiki-Dump-Dateien

Für ein Projekt war ich auf der Suche nach einer Java-Bibliothek um die Dumps einer MediaWiki-Installation auszuwerten. Fündig geworden bin ich bei der Bibliothek WikiXMLJ, welche allerdings mittlerweile einige Jahre auf dem Buckel hat. Auf Basis dieser Bibliothek habe ich die Bibliothek mediawikixml erstellt. Um die Bibliothek zu nutzen, muss im ersten Schritt eine neue Paketquelle in der pom.xml definiert werden.

<repositories>
 <repository>
 	<id>github</id>
 	<url>https://maven.pkg.github.com/seeseekey/mediawikixml</url>
 </repository>
</repositories>

Anschließend kann die Abhängigkeit eingebunden werden:

<dependency>
    <groupId>net.seeseekey</groupId>
    <artifactId>mediawikixml</artifactId>
    <version>1.0.1</version>
</dependency>

Damit kann die Bibliothek zur Auswertung von MediaWiki-Dumps genutzt werden:

WikiXMLParser wikiXMLParser = WikiXMLParserFactory.getParser("dump-current.xml");

try {

    wikiXMLParser.setPageCallback(new PageCallbackHandler() {
        public void process(WikiPage page) {
            System.out.println(page.getId());
            System.out.println(page.getRevisionId());
            System.out.println(page.getTimestamp());
            System.out.println(page.getTitle());
            System.out.println(page.getWikiText());
        }
    });

    wikiXMLParser.parse();
} catch (Exception e) {
    e.printStackTrace();
}

Für jede MediaWiki-Seite wird unter anderem die ID, die Revision, der Timestamp, der Titel und der eigentliche Inhalt der Seite geparst. Die Bibliothek setzt mindestens Java 8 voraus. Zu finden ist das Repository mit der Bibliothek auf GitHub. Die Bibliothek ist unter der Apache License in Version 2 lizenziert und damit freie Software.

A.I. DUET

Google veröffentlicht von Zeit zu Zeit ein paar seiner Experimente im Zusammenhang mit künstlicher Intelligenz. Eines dieser Experimente ist A.I. DUET. In der Webapp wird dem Nutzer ein virtuelles Klavier angeboten, auf welchem dieser ein paar Noten spielen kann. Alternativ kann ein Keyboard mittels MIDI-Interface angeschlossen werden. Nachdem der Nutzer einige Noten gespielt hat, antworte das trainierte neuronale Netz mit eigenen Noten; so kann der Nutzer in einer Art Duett mit dem neuronalen Netzwerk interagieren.

A.I. DUET in Aktion

Zu finden ist das Experiment unter experiments.withgoogle.com. Der Quelltext kann über GitHub bezogen werden. Lizenziert ist A.I. DUET unter der Apache License in Version 2 und damit freie Software.

MQTT-Broker in Java einbinden

Zur Nutzung des MQTT-Protokolls wird ein MQTT-Broker benötigt. Dieser kann separat betrieben oder aber in eine Anwendung eingebettet werden. Ein MQTT-Broker, welcher sich für die Einbettung unter Java eignet, ist Moquette. Zur Einbindung von Moquette muss es den Abhängigkeiten des Projektes hinzugefügt werden:

<dependency>
	<groupId>io.moquette</groupId>
	<artifactId>moquette-broker</artifactId>
	<version>0.12.1</version>
</dependency>

Die Funktionalitäten zum Start und Stop des MQTT-Brokers werden in diesem Beispiel in der Klasse Broker gekapselt. In der Klasse wird eine Instanz vom Typ Server angelegt und über die Methode startServer kann der MQTT-Broker gestartet werden. Beim Start wird in diesem Beispiel das Topic /exit angelegt. Weitere Topics können über die Methode pushTopic angelegt werden. Mittels der Methode stopServer kann der Broker wieder gestoppt werden.

public final class Broker {

    private static Logger log = LoggerFactory.getLogger(new Exception().fillInStackTrace().getStackTrace()[0].getClassName());

    final Server mqttBroker = new Server();

    public void startServer() {

        // Load class path for configuration
        IResourceLoader classpathLoader = new ClasspathResourceLoader();
        final IConfig classPathConfig = new ResourceLoaderConfig(classpathLoader);

        // Start MQTT broker
        log.info("Start MQTT broker...");
        List userHandlers = Collections.singletonList(new PublisherListener());

        try {
            mqttBroker.startServer(classPathConfig, userHandlers);
        } catch (IOException e) {
            log.error("MQTT broker start failed...");
        }

        // Wait before publish topics
        log.info("Wait before topics are pushed...");

        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            log.warn("Pause for publishing topics interupted.");
        }

        // Publishing topics
        log.info("Pushing topics...");

        pushTopic("/exit");

        log.info("Topics pushed...");
    }

    public void stopServer() {
        mqttBroker.stopServer();
    }

    public void pushTopic(String topic) {

        MqttPublishMessage message = MqttMessageBuilders.publish()
                .topicName(topic)
                .retained(true)
                .qos(MqttQoS.EXACTLY_ONCE)
                .payload(Unpooled.copiedBuffer("{}".getBytes(UTF_8)))
                .build();

        mqttBroker.internalPublish(message, "INTRLPUB");
    }
}

Beim Start des Servers wird eine Konfigurationsdatei mit dem Namen moquette.conf aus dem Ordner resources/config geladen. Diese könnte beispielhaft wie folgt aussehen:

##############################################
#  Moquette configuration file. 
#
#  The syntax is equals to mosquitto.conf
# 
##############################################

port 1883

#websocket_port 8080

host 0.0.0.0

#Password file
#password_file password_file.conf

#ssl_port 8883
#jks_path serverkeystore.jks
#key_store_password passw0rdsrv
#key_manager_password passw0rdsrv

allow_anonymous true

Beim Start des MQTT-Brokers wird ein Handler vom Typ PublisherListener registriert. Diese Handler muss natürlich vorher definiert werden:

public class PublisherListener extends AbstractInterceptHandler {

    private static Logger log = LoggerFactory.getLogger(new Exception().fillInStackTrace().getStackTrace()[0].getClassName());

    @Override
    public String getID() {
        return "PublishListener";
    }

    @Override
    public void onPublish(InterceptPublishMessage msg) {

        // Create array for payload
        int readableBytes = msg.getPayload().readableBytes();
        byte[] payload = new byte[readableBytes];

        // Read bytes from payload
        for (int i = 0; i < readableBytes; i++) {
            payload[i] = msg.getPayload().readByte();
        }

        // Create string from payload
        String decodedPayload = new String(payload, UTF_8);
        log.debug("Received on topic: " + msg.getTopicName() + " content: " + decodedPayload);
    }
}

Der Handler wertet alle Publish-Nachrichten aus und loggt diese mittels des Loggers. Nun kann der Broker gestartet werden:

// Start broker
Broker broker = new Broker();
broker.startServer();

// Bind a shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> {

	log.info("Stopping MQTT broker...");
	broker.stopServer();
}));

Über den registrierten Shutdown-Hook kann der Server anschließend wieder beendet werden. Damit ist die beispielhafte Einbindung von Moquette in eine Java-Applikation abgeschlossen. Der Quelltext von Moquette kann über GitHub bezogen werden. Lizenziert ist das Projekt unter der Apache License in Version 2 und damit freie Software.

Deeplearning4j

Bibliotheken für die Entwicklung von Deep Learning-Anwendungen bzw. zur Nutzung von maschinellem Lernen, sind meistens für Python verfügbar. Entsprechende Bibliotheken für Java sind dagegen spärlich gesät. Eine dieser Bibliotheken für Java ist Deeplearning4j. Neben der klassischen Kost, wie der Unterstützung unterschiedlicher neuronaler Netze, verfügt Deeplearning4j über eine Schnittstelle zu Python, mit deren Hilfe die entsprechenden Bibliotheken aus der Python-Welt angebunden werden können.

deeplearning4j.org

Der Quelltext der Bibliothek ist auf GitHub zu finden. Lizenziert ist die Bibliothek unter der Apache License in der Version 2 und damit freie Software. Die offizielle Projektseite kann unter deeplearning4j.org besucht werden.

Code-Formatierung unter IntelliJ IDEA selektiv deaktivieren

IntelliJ IDEA bietet, wie wahrscheinlich jede brauchbare IDE, eine Funktionalität um den Quelltext automatisch zu formatieren. Manchmal kann es allerdings notwendig sein die Funktionalität für bestimmte Dateien oder Abschnitte zu deaktivieren. IntelliJ IDEA bietet dem Nutzer eine Möglichkeit dies zu tun. Dazu muss in den Einstellungen unter Code Style im Tab Formatter Control das entsprechende Feature aktiviert werden. Im Beispiel sieht das Ganze wie folgt aus:

// @formatter:off
try {
  // Do something wrong
} catch(Exception e) {
  // Gotta Catch 'Em All
}
// @formatter:on

Durch den einleitenden Kommentar @formatter:off wird die Code-Formatierung deaktiviert; am Ende des Blockes wird er mittels @formatter:on wieder aktiviert. Damit ist es mögliche Abschnitte und Dateien von der Code-Formatierung auszunehmen.