Java Code Qualität verbessern

Im Bereich der statischen Quellcodeanalyse gibt es einige Tools, welche auf unterschiedlichste Aufgaben spezialisiert sind. Ziele dieser Tools sind, Fehler zu finden, die Lesbarkeit des Codes zu verbessern und die Qualität des Quellcodes allgemein zu erhöhen. Heute werden wir uns einige dieser Tools ansehen.
Nachdem es im letzten Artikel um Findbugs und sinnvolle Alternativen dazu ging, geht es hier um Ergänzungen, welche die Qualität des Programmcodes weiter verbessern können. Dazu werden wir exemplarisch PMD und Checkstyle vorstellen.

Continue reading

Posted in Java and Quality | Tagged , , , , | Leave a comment

Findbugs ist tot, lang lebe Findbugs

Um potenzielle Fehler und Stolperfallen im Programmcode zu identifizieren, gibt es das Tool Findbugs. Es analysiert den Java-Bytecode und findet dabei Codestellen, an welchen potenziell Probleme auftreten können. Beispiele dafür sind inkonsistente equals()-hashCode()-Methoden, unsichere Casts, mögliche Stack Overflows, möglicherweise auftretende, aber nicht beachtete Exceptions, etc.

Continue reading

Posted in Java and Quality | Tagged , , , | 1 Comment

Aktorenmodell und Akka Teil 1/3

Heutzutage ist die Nachfrage nach äußerst skalierbaren, aber trotzdem zuverlässigen und fehlertoleranten Systemen so hoch wie nie.

Daher möchten wir im ersten Teil dieser dreiteiligen Serie eine Einführung in das Aktorenmodell geben. Im zweiten Teil der Serie wird es dann eine Einführung in das Aktorframework Akka geben. Akka ist im Übrigen eine Implementierung des Aktorenmodells auf Basis der JVM, welches mit begrenztem Aufwand das Verteilen einer Anwendung auf mehrere Systeme ermöglicht. Da es nur einen begrenzten Sinn hat, ein verteiltes System auf nur einer Maschine laufen zu lassen, wird der dritte Teil das Clustering mit Akka behandeln.
Continue reading

Posted in Java Runtimes - VM, Appserver & Cloud | Tagged , , , , , , | Leave a comment

Apache Spark – Success Story

Wie im ersten Artikel zu Apache Spark bereits angerissen, gibt es durch die immer weiter fortschreitende Digitalisierung (Industrie 4.0, Smart Grids, Connected Cars, Internet of Things, sowie große Onlinevertriebsplattformen und Soziale Netzwerke) immer mehr Geräte und Nutzer, welche kontinuierlich neue Daten generieren. Um diese stetig wachsende Datenmenge zu verwerten, gibt es große verteilte Systeme, welche die Daten zunächst strukturieren und aufbereiten, um sie anschließend auswerten.

Dieser Artikel ist ein Follow-Up zur zweiteiligen Serie zu Apache Spark. Nach der allgemeinen Einführung in Apache Spark im ersten Artikel der Serie und den Codebeispielen im zweiten Artikel, in welchen Wörter, beziehungsweise Zeichen gezählt und ausgewertet wurden, sowie ein Apache-Logfile analysiert wurde, werden in diesem Follow-Up Artikel einige Production Use Cases und Success Stories vorgestellt. Hier sieben Success Stories aus den Bereichen E-Health, E-Commerce, Social Networks, Streaming und Shared Economy.

Continue reading

Posted in Open Source BI | Tagged , , , | Leave a comment

JUnit 5: Die Neuerungen im Überblick

Vor etwa einem Jahr, im Sommer 2015, wurde auf der Crowdfunding-Plattform Indigogo eine Spendenkampagne für die Weiterentwicklung von JUnit gestartet. Ziel der JUnit Lambda getauften Aktion war es, das am weitesten verbreitete Unit-Testing-Framework für Java zu überarbeiten und fit für die Zukunft zu machen. Insbesondere sollte JUnit so erweitert werden, dass das Framework möglichst umfassend von den neuen Sprach-Features von Java 8 profitieren kann. Um das zu erreichen, war eine komplette Neukonzipierung des Kerns von JUnit notwendig.

Die Crowdfunding-Kampagne, an der sich auch die OIO GmbH beteiligt hat, war ein voller Erfolg, sodass die Entwicklungsarbeiten wie geplant beginnen konnten. Aus dem Projekt JUnit Lambda wurde JUnit 5. Heute, ein Jahr später, gibt es schon den zweiten Milestone Release, mit dem man die neuen Features ausprobieren kann. Es sind aber noch nicht alle geplanten Neuerungen vollständig umgesetzt. Dennoch hinterlässt dieses Release schon einen sehr guten Eindruck von der neuen Version des Testing-Frameworks. Weitere Milestones und ein erstes finales Release sind für Ende 2016/Anfang 2017 geplant.

Continue reading

Posted in Java and Quality | Tagged , , | Leave a comment

Apache ActiveMQ (Teil 2/2)

In dieser Artikelserie geht es um die Funktionsweise von Publish-Subscribe Systemen am Beispiel von Apache ActiveMQ. Anwendungsfälle hierfür könnten ein effizientes Load-Balancing oder eine einfache Replikation sein. Hier ist die Verwendung eines Systems, welches das Publish-Subscribe Pattern implementiert, essenziell. Die Verwendung eines RESTful Request-Response-System und einer Client-Server-Architektur wäre in derartigen Fällen äußerst aufwendig und dazu ineffizient.

Dies ist der zweite Teil der zweiteiligen Artikelserie zu Apache ActiveMQ. Während Apache ActiveMQ und die zugrundeliegenden Technologien im ersten Teil dieser Serie eingeführt wurden, wird es in diesem zweiten Teil um die praktische Anwendung von Apache ActiveMQ gehen. Es gibt mehrere Beispiele mit Java-Source Code, sowie eine Einführung in das von Apache ActiveMQ mitgelieferte Webinterface.

Praktische Anwendung

Zunächst benötigen wir den Apache ActiveMQ Message Broker. Dieser ist hier zu finden. Eine detaillierte Installationsanleitung ist hier zu finden. Nachdem der Message Broker installiert und gestartet ist, können wir mit unserer Anwendung Nachrichten über ihn verschicken. Alternativ kann unsere Anwendung auch einen lokalen virtuellen Message Broker direkt aus der Anwendung heraus starten und die Nachrichten darüber verschicken.
Außerdem wird natürlich die Apache ActiveMQ API, sowie das JMS benötigt. Diese Abhängigkeiten können wir über Maven einbinden:

<dependencies>
<dependency>
    <groupId>javax.jms</groupId>
    <artifactId>jms-api</artifactId>
    <version>1.1-rev-1</version>
</dependency>
	<dependency>
		<groupId>org.apache.activemq</groupId>
		<artifactId>activemq-core</artifactId>
		<version>5.7.0</version>
	</dependency>		
</dependencies>

Alternativ via Gradle:

compile group: 'javax.jms', name: 'jms-api', version: '1.1-rev-1'
compile group: 'org.apache.activemq', name: 'activemq-core', version: '5.7.0'

Nun können wir anfangen zu programmieren. Wir beginnen mit einem Publisher für ein Topic in Apache ActiveMQ. Der Java-Quellcode sieht wie folgt aus:

public void publish(String topic, String text, String uri) {
 try {
  // Connect to the Message Broker
  ActiveMQConnectionFactory connectionFactory = new 
    ActiveMQConnectionFactory(uri);
  Connection connection = connectionFactory.createConnection();
  connection.start();

   // specify QoS level -> does not matter here because of TCP
   Session session = connection.createSession(false,
      Session.AUTO_ACKNOWLEDGE);
   Destination destination = session.createTopic(topic);

   // Create a MessageProducer from the Session to the Topic
   MessageProducer producer = session.createProducer(destination);

   // specify message persistence
   producer.setDeliveryMode(DeliveryMode.PERSISTENT);

   // Create and send the messages
   TextMessage message = session.createTextMessage(text);
   producer.send(message);
   System.out.printf ("[%s - %s] Sent: '%s' with topic %s" + 
      " to server %s\n", Thread.currentThread().getName(), 
      this.hashCode(), text, topic, uri);

   // Clean up
   session.close();
   connection.close();
  } catch (JMSException jmse) {
     jmse.printStackTrace();
  }
}

Die implementierte Funktion heißt “publish” und erhält als Argumente das Topic, eine Nachricht und die URI des Message Broker als Strings. Ein beispielhafter Aufruf wäre etwa “publish(“t1”, “test message”, “tcp://127.0.0.1:61616″)”. Um einen lokalen Message Broker zu verwenden, wird als URI-String “vm://localhost” übergeben.

Zunächst verbinden wir uns mit dem Message Broker. Dazu erstellen wir ein Objekt vom Typ ActiveMQConnectionFactory (Zeilen 4 und 5), erstellen ein Connection-Objekt und öffnen diese Verbindung mit dem Aufruf der Funktion “start()” auf das Connection-Objekt (Zeilen 6 und 7).

Danach beginnen wir eine Session und stellen den QoS-Level auf automatische Acknowledges. Dies ist hier allerdings nicht so wichtig, da wir ja ohnehin über TCP kommunizieren (vgl. uri). Anschließend erstellen wir ein Objekt vom Typ MessageProducer (Zeile 15), speichern dieses in der Variable “producer” und setzten den DeliveryMode auf PERSISTENT. Somit werden alle unsere Nachrichten gespeichert, bis ein Subscriber sie abholt. Alternativ könnten wir den Modus auf NON_PERSISTENT stellen, woraufhin ausschließlich die Subscriber, welche im Moment des Sendens das Topic abonniert haben, diese Nachricht empfangen würden. Nun erstellen wir das TextMessage-Objekt, übergeben der entsprechenden Factory-Methode der “session” den “text” und speichern das Resultat in der Variable “message”. Anschließen versenden wir die “message” über unseren “producer” und geben die Nachricht über die Konsole aus. Schließlich schließen wir die Verbindung zum Message Broker.

Wenn wir nun unseren Beispielaufruf “publish(“t1”, “test message”, “tcp://127.0.0.1:61616″)” ausführen und es einen Message Broker unter 127.0.0.1 auf dem Standardport 61616 gibt, wird die Nachricht gepublisht und folgende Ausgabe erscheint in der Konsole:

[Thread-13 - 1037829921] Sent: 'test message' with topic t1 to server tcp://127.0.0.1:61616

Üblicherweise wird für jede Nachricht, die gepublisht wird, eine neue TCP-Verbindung zum Message Broker aufgebaut. Dies kommt daher, dass in großen Systemen der zusätzliche Overhead von tausenden offenen TCP-Verbindungen auf dem Message Broker, welche zu denen ohnehin offenen Verbindungen der Subscriber dazukommen, einen signifikanten Effekt auf die Gesamtperformance hat.

Nun eine erste Implementierung für einen Subscriber, welcher eine Nachricht empfangen soll und danach ebenfalls die Verbindung trennt.

public void receiveSync(String topic, String uri) {
 try {
   // Connect to the Message Broker
   ActiveMQConnectionFactory connectionFactory = new 
      ActiveMQConnectionFactory(ActiveMQ.getURI());
   Connection connection = connectionFactory.createConnection();
   connection.start();

   // Create a Session
   Session session = connection.createSession(false, 
      Session.AUTO_ACKNOWLEDGE);
   Destination destination = session.createTopic(topic);

   // Create a MessageConsumer from the Session to the Topic
   MessageConsumer consumer = session.createConsumer(destination);

   // Wait for a message
   Message message = consumer.receive();
   String received = "";
   if (message instanceof TextMessage) {
      TextMessage textMessage = (TextMessage) message;
      received = textMessage.getText();
   } else {
      received = message == null ? "-" : message.toString();
   }
   System.out.printf("[%s - %s] Received: '%s' via %s\n",
      Thread.currentThread().getName(), this.hashCode(), 
      received, topic);

   consumer.close();
   session.close();
   connection.close();
 } catch (Exception e) {
   e.printStackTrace();
 }
}

Diese “receiveSync” Funktion erhält als Argumente den Namen des Topics und die URI des Message Brokers. Beispielaufruf: “receiveSync(“t1”, “tcp://127.0.0.1:61616″)”.

Die ersten Zeilen sind identisch zu denen beim Publisher. Erst in Zeile 15 wird anstatt eines MessageProducers ein MessageConsumer erstellt und in die Variable “consumer” gespeichert. Mit dem Methodenaufruf “consumer.receive()” wird der aktuelle Thread blockiert, bis eine Nachricht eintrifft. Wenn es sich bei dieser Nachricht um eine Textnachricht handelt, wird der Text extrahiert und ausgegeben. Anschließend wird die Verbindung geschlossen.

Das Resultat des Testaufrufs und anschließende Senden einer Nachricht:

[Thread-24 - 1783224049] Received: 'test message' via t1

Die Erstellung eines Subscribers für eine Queue statt ein Topic ist vom Quellcode her fast identisch, bis auf den Fakt, dass in Zeile 12 anstatt “session.createTopic(name)” die Methode “session.createQueue(name)” verwendet wird. Bei der Verwendung von Queues kann anstatt dem allgemeinen MessageConsumer auch ein QueueBrowser erstellt werden. Mit diesem können die verfügbaren Elemente dann über die Methode “getEnumeration()” erhalten werden.

Natürlich hilft es begrenzt, wenn nur eine Nachricht empfangen werden kann. Anstatt die Zeilen 18 bis 28 jetzt jedoch in eine while (true)-Schleife zu verschieben, kann auch ein MessageListener auf für den “consumer” hinzugefügt werden. Dazu hier ein Codebeispiel, in welchem gleichzeitig auch die Funktionalität der Durable Suppliers veranschaulicht wird.

public class DurableTestConsumer {
  private Connection connection;

  public DurableTestConsumer(String topic, String uri, String clientID,     
    String subscriptionName) {
      try {
	// Connect to the Message Broker
        ActiveMQConnectionFactory connectionFactory = new
        ActiveMQConnectionFactory(ActiveMQ.getURI());
	connection = connectionFactory.createConnection();
	connection.setClientID(clientID);
	connection.start();

	// Create a Session
        Session session = connection.createSession(false,
          Session.AUTO_ACKNOWLEDGE);
	Topic t = session.createTopic(topic);

        // Create a durable subscriber from the Session to the Topic
        MessageConsumer consumer = session.createDurableSubscriber(t, 
          subscriptionName);

	consumer.setMessageListener(message -> {
	try {
	  String received = "";
	  if (message instanceof TextMessage) {
	    TextMessage textMessage = (TextMessage) message;
	    received = textMessage.getText();
	  } else {
            received = message == null ? "-" :
            message.toString();
	  }
          System.out.printf("[%s - %s] Received: '%s'\n",
          Thread.currentThread().getName(),
	  Thread.currentThread().hashCode(), received);
        } catch (JMSException jmse) {
	jmse.printStackTrace();
      }
    });
    } catch (JMSException e) {
      e.printStackTrace();
    }
  }

  public void disconnect() {
    try {
      connection.close();
    } catch (JMSException e) {
      e.printStackTrace();
    }
  }
} 

Wie zu sehen ist, wird die “connection” hier als Attribut in der Klasse gespeichert. Im Kontruktor wird es wie gehabt initialisiert. Dieses Mal wird allerdings zusätzlich eine “clientID”, welche über den Konstruktor übergeben wird, verwendet. Diese “clientID” wird später den DurableSubsciber eindeutig identifizieren. Außerdem können niemals zwei Subscriber mit der gleichen “clientID” mit dem Message Broker verbunden sein und auf die gleiche Subscription horchen.

Um dies zu realisieren, wird in Zeile 20 anstatt einem Aufruf der Methode “createConsumer(…)” die Methode “createDurableSubscriber(…)” aufgerufen. Anschließend wird ein MessageListener auf den “consumer” hinzugefügt. Dieser enthält im Lambda-Ausdruck die Implementierung des zugehörigen Interfaces. Als Übergabeparameter erhält die Implementierung das empfangene Message-Objekt message, welches daraufhin ausgeben wird.

Dieser Subsciber ist so lange aktiv, bis er durch einen Aufruf der “disconnect()”-Methode beendet wird.

Web Inteface

Nachdem wir nun einige Publisher, Subscriber und DurableSubscriber erstellt haben, öffnen wir das Webinterface (127.0.0.1:8161/admin) vom Apache ActiveMQ Message Broker. Nach Eingabe der Zugangsdaten (default: admin, admin), erscheint diese Übersichtsseite:
Home

Hier sind einige Grunddaten, wie Name, Version, ID und Uptime, sowie eine Navigationsleiste oben zu sehen. Rechts haben wir Quicklinks, mit denen beispielsweise eine Auflistung der Topics, Queues oder Subscribers im XML-Format angezeigt werden kann. Die dafür verwendete URL können wir dann auch von unseren Anwendungen aus aufrufen.

Wenn wir nun auf “Topics” klicken, erhalten wir diese Übersicht:
Topics

Neben einigen Topics, die für interne Managementvorgänge verwendet werden, sehen wir hier auch die von uns erstellten Topics t1, t2, c1 und c2.Wir sehen, dass alle 25 Nachrichten von t1 abgeholt wurden, und es gerade 2 Consumer gibt. Detaillierte Informationen zu diesen Consumern können mit einem Klick auf “active subscribers” rechts angezeigt werden. Alternativ kann eine Nachricht an das Topic über “Send To” oder einen Klick direkt auf das Topic geschickt werden. Das Topic kann über einen Klick auf “Delete” entfernt werden. All diese Funktionen funktionieren natürlich auch für alle anderen Topics. Im Übrigen werden die eventuell noch nicht ausgelieferten Nachrichten beim Löschen eines Topics mitgelöscht. Noch verbundene Subscriber werden allerdings nicht beeinträchtigt. Außerdem wird das Topic neu erstellt, sobald ein Publisher eine neue Nachricht darüber verschickt.

Die Ansicht für die Queues ist analog zu der Übersicht über die Topics, nur bei den Queues wird die Anzahl der noch nicht abgeholten Pakete noch einmal explizit angegeben.

Der nächste Menüpunkt “Subscribers” enthält eine Übersicht über die unterschiedlichen gerade verbundenen Subscribers.
Subscribers

Hier sind sowohl die aktiven, als auch die nicht aktiven DurableSubscriber angezeigt. Außerdem gibt es eine Übersicht über die aktuell verbundenen temporären Subscriber, die keine DurableSubscriber sind. Jeder Subscriber wird mit der zugehörigen ClientID, dem Subscription Namen, sowie der Destination (beispielsweise Topic t1), sowie einigen anderen Informationen angezeigt. Wir sehen im Screenshot beispielsweise, dass für den nicht verbundenen Subscriber s1 mit der ClientID c2 und Destination t1 aktuell 25 Nachrichten im Puffer vorgehalten werden, die noch nicht abgeholt wurden. Wenn wir diesen Subscriber jetzt über die “Delete”-Operation rechts löschen würden, würde der Puffer geleert. Der DurableSubscriber wird allerdings wieder neu hinzugefügt, sobald wir ihn über unser Java-Programm wieder verbinden.

Connections
Anschließend gibt es noch eine Verbindungsübersicht unter “Connections” in der Navigationsleiste. Hier sehen wir die verbundenen Subscriber aufgeschlüsselt nach den unterstützten Protokollen, sowie eine Übersicht der Network Connectors.

Im letzten Tab können wir Nachrichten versenden. Dies ist derselbe Tab, der mit einem Klick auf den “Send-To”-Link in der Übersicht über die Topics oder Queues geöffnet wird.

Hier können wir eine JMS-Message an ein beliebiges Topic oder eine Queue verschicken, sowie einen Timer über einen cronjob aufsetzen, der regelmäßig eine feste Nachricht an die ausgewählte Destination schickt.

Posted in Java Runtimes - VM, Appserver & Cloud | Tagged , , , , | 1 Comment

Apache ActiveMQ (Teil 1/2)

In dieser Artikelserie geht es um die Funktionsweise von Publish-Subscribe Systemen am Beispiel von Apache ActiveMQ. Anwendungsfälle hierfür könnten ein effizientes Load-Balancing oder eine einfache Replikation sein. Hier ist die Verwendung eines Systems, welches das Publish-Subscribe Pattern implementiert, essenziell. Die Verwendung eines RESTful Request-Response-System und einer Client-Server-Architektur wäre in derartigen Fällen äußerst aufwendig und dazu ineffizient.

Zu ActiveMQ wird es eine zweiteilige Artikelserie auf diesem Blog geben. Sie beginnt in diesem ersten Teil mit einer Einführung in Apache ActiveMQ und die unterstützen Features, gefolgt von einer Einführung in die verwendeten Publish-Subscribe Systeme, sowie der Definitionen einiger Quality Of Service Levels. Abschließend werden die Systeme Apache ActiveMQ und Apache ActiveMQ Artemis erläutert und verglichen.

Der zweite Teil der Artikelserie wird neben einigen Java-Code-Beispielen auch eine Einführung in das mitgelieferte Webinterface von Apache ActiveMQ enthalten.
Continue reading

Posted in Java Runtimes - VM, Appserver & Cloud | Tagged , , , , | 2 Comments