Messagebus

Andre Schemschat

Wie in jeder komplexen Architektur müssen die einzelnen Komponenten untereinander verbunden sein, um Daten und Nachrichten auszutauschen. Je fester diese Koppelung ist, um so schneller können untereinander Daten ausgetauscht werden, die Entwicklung ist also schneller und einfacher. Dieser vermeintliche Vorteil wandelt sich jedoch mit steigender Komplexität zum Nachteil, da es schwerer wird den Code sauber zu trennen und die Übersicht zu behalten. Eines der Ziele der gewählten Architektur ist es, neue Erweiterungen so einfach wie möglich zu erlauben, ohne dabei etwas an dem Grundsystem zu ändern. Zu diesem Zweck wurde ein Messagebus integriert. Während der Initialisierung können sich alle Teile an diesem Bus registrieren und mitteilen, auf welche Nachrichten sie reagieren wollen. Während der Laufzeit können dann Nachrichten verschickt werden, die der oder die Empfänger verarbeiten. Die Empfänger sind dabei in ihrer Anzahl nicht eingeschränkt, es können also mehrere Quellen auf die gleiche Nachricht reagieren, so dass gerade Statusmeldungen sehr einfach zu verwenden sind. Das Versenden der Nachrichten läuft dabei synchron ab, dass heißt eine Nachricht wurde erst vollständig von allen Emfpfängern verarbeitet, bevor der Aufruf zurück zu dem Urheber springt. Exceptions, die während der Ausführung auftreten, werden ebenfalls an den Urheber weitergeleitet, so dass dieser auf etwaige Fehler reagieren kann.

@Receive public void getGame(MGetGame m) {
    Session s = Database.session();     
    Game game = (Game)s.get(Game.class, m.getID());
 
    if(game == null)
        throw new ControllerException("game_not_found");
    m.setGame(game);
}
Empfangen einer Nachricht
MGetGame getgame = new MGetGame(gameId);
send(getgame);
Game game = getgame.getGame();
Senden einer Nachricht

Wie im obigen Beispiel gesehen werden bestimmte Typen von Objekten über den Messagebus geschickt, so genannte Messages. Die Nachrichten fungieren als eine Art Umschlag für die Informationen, die benötigt werden um die Anfrage auszuführen. Sie bestehen meistens aus einem Konstruktor, der die erwarteten Parameter entgegennimmt und aus Settern und Gettern, um die Parameter zu lesen und die Antwort zu setzen.

Neben dieser allgemeinen Art von Nachricht gibt es noch zwei spezielle Subtypen, die sich in einigen Punkten unterscheiden. Zum einen die PassiveMessage, zum anderen die SingleResponseMessage. Ersteres markiert eine Nachricht, die lediglich für passive Zwecke eingesetzt wird. Passive Nachrichten werden immer dann verschickt, wenn sich etwas geändert hat, was andere interessieren könnte, wie z.B. das ein Spieler ein Spiel verlassen hat. Letztere sind Anfragen, die nur ein einziges Ergebnis zurückliefern und dadurch vereinfacht gehandhabt werden können. Für beides ist im folgenden ein Beispiel gelistet.

public class MGameCreated extends PassiveMessage {
	private Game game;
 
	public MGameCreated(Game g) {
		this.game = g;
	}
 
	public Game getGame() {
		return this.game;
	}
}
Beispiel einer passiven Nachricht
public class MGetGame extends SingleResponseMessage<Game> {
	private Game game;
	private int id;
 
	public MGetGame(int id) {
		if(id < 1)
			throw new IllegalArgumentException();
		this.id = id;
		this.game = null;
	}
 
	public int getID() {
		return this.id;
	}
 
        @Override
	public Game getResponse() {
		return game;
	}
 
        @Override
	public void setResponse(Game game) {
		if(game == null)
			throw new IllegalArgumentException();
		this.game = game;
	}
}
 
// das vereinfachte senden der Nachricht
Game g = (new MGetGame(5)).send(this);
Beispiel einer SingleResponseMessage


Page last modified on March 21, 2011, at 10:15 AM