Samstag, 11. Februar 2012


Artikel

Juli 2008 | Artikel

Google Protocol Buffers: Mark-Set-Go! Fortsetzung, Teil 2

Teil 1   Teil 2   

Protocol Buffer und Java

Der generierte Java-Code besteht im Falle von Listing 2 aus einer einzigen Quelldatei (AddressbookProtos.java). Diese enthält für jedes message-Element je eine Klasse, außerdem fällt auf, dass jede Klasse einen eigenen Builder mitbringt. Die Enums werden korrekt abgebildet und die mit repeated markierten Attribute werden auf Java-Seite folgerichtig mit einer List umgesetzt. Der generierte Java-Code ist außerdem abhängig von Klassen, die vom Protocol Buffer-Framework zur Verfügung gestellt werden. Diese stellen unter anderem auch sicher, dass Setter, die in der original .proto-Datei als required markiert wurden, auch tatsächlich gefüllt sind. Für den Fall, dass Muss-Felder also nicht bestückt werden, bekommt man eine nette Exception als Quittung. Bei Feldern, wo der Parameter optional, anstelle required gesetzt wurde, sorgt das Framework darüber hinaus dafür, dass sie im Bedarfsfall mit gültigen Standardwerten gefüllt werden. Bei numerischen Feldern ist dies eine Null, bei Strings ein Leerstring und bei boolschen Feldern der Wert false sofern nicht anders festgelegt.

Wie bereits erwähnt wurde, handelt es sich bei dem von protoc generierten Java-Codes letztlich um POJOs. Neben den üblichen Gettern und Settern steht außerdem für jedes Feld eine has-Methode zur Verfügung, mit der geprüft werden kann, ob das entsprechende Feld gefüllt ist oder nicht. Für Listen steht zusätzlich noch eine Hilfsmethode bereit, um festzustellen, wie viele Elemente sich in derselbigen befinden. Erzeugt wird ein mit Protocol Buffer generierter Datencontainer stets über einen Builder. Über die Methode newBuilder erhält man einen solchen Builder, auf dem nun die einzelnen Setter zum Befüllen mit Daten aufgerufen werden können. Erzeugt wird das Objekt schließlich durch einen finalen Aufruf der Methode build() auf dem Builder. Listing 3 zeigt, wie man mithilfe von Buildern ein Person-Objekt erzeugt, das aus der Proto-Datei (Listing 2) hervorgeht.

  1. Listing 3 : Erzeugen von Entitäten mit Hilfe von Buildern
  2. Person.newBuilder()
  3. .setId(1234)
  4. .setName("John Doe")
  5. .setEmail("jdoe@example.com")
  6. .addPhone(Person.PhoneNumber.newBuilder()
  7. .setNumber("555-4321")
  8. .setType(Person.PhoneType.HOME))
  9. .build();

Direkt auf dem Datenobjekt selbst existieren selbstverständlich auch eine Reihe mehr oder weniger wichtiger Methoden wie etwa toString() mit der man die Daten in Textform ausgeben kann. Die Methode writeTo bietet die Möglichkeit, die Daten in einen Stream zu schreiben. Analog zu writeTo existiert mit der Methode parseFrom natürlich auch eine Möglichkeit, aus einem Stream zu lesen. Der Datenaustausch über verschiedene Programmiersprachen hinweg wäre dann in der Form denkbar, dass man sich über protoc entsprechende Quellen für die jeweilige Programmiersprache erzeugt und über dessen Methoden zum Laden und Speichern vom entsprechenden Stream auf die Daten zugreift. In Tabelle 1 sind alle wichtigen Methoden mit einer kurzen Beschreibung zusammengefasst.

Tabelle 1: Wichtige Methoden aus dem Protocol Buffer-Framework
Methode Beschreibung
isInitialized() Prüft ob alle mit required markierten Felder gefüllt sind.
toString() Gibt den Inhalt in Textform aus, interessant vor allem für Debuggingzwecke.
mergeFrom (Message other) Verknüpft zwei Datenstrukturen. Die Felder werden mit denen aus other überschrieben, in repeated markierte Felder wird angehängt. Die Methode ist nur auf Buildern verfügbar.
clear() Setzt alle Felder zurück. Die Methode ist nur auf Buildern verfügbar.
toByteArray() Konvertiert die Daten (den Protocol Buffer) in ein Byte Array
parseFrom(byte[] data) Liest einen Protocol Buffer aus einem Byte Array ein
writeTo(OutputStream out) Schreibt die Daten in einen OutputStream
parseFrom(InputStream in) Liest Daten aus einem InputStream
 
 
Performanceboost

Das Kommandozeilenwerkzeug protoc erzeugt aus den .proto-Dateien Quellen für die jeweilige Zielprogrammiersprache. Beim Erzeugen von Code versucht protoc in der Defaulteinstellung die Quelldateien so klein wie möglich zu halten. In dieser Einstellung wird das Protocol Buffer-Framework dann mithilfe von Reflection die Datenstruktur verwalten. Sollte sich ergeben, dass der Reflection-basierte Ansatz in irgendeiner Weise zu langsam ist, so besteht die Möglichkeit, mit einem speziellen Parameter in der .proto-Datei den Code auf Geschwindigkeit zu optimieren. Durch Einfügen des Parameters

  1. option optimize_for = SPEED;

wird beim erneuten Kompilieren nun Code erzeugt, der ohne Reflection auskommt und laut Google extrem schnell sein soll ("Re-run the protocol compiler, and it will generate extremely fast parsing, serialization, and other code"). Das Ganze hat natürlich auch einen kleinen Haken: Der entstandene Code ist deutlich größer.

Fazit

Google Protocol Buffer sind ein gewagter Schritt zurück. Weg von XML und wieder hin zu  proprietären Formaten, damit einhergehend natürlich einen beachtlichen Performanceschub gewinnend. Bedingt durch die einfache Strukturierungssprache und der Tatsache, dass Code zum einfachen Zugriff auf eben diese Strukturen generiert wird, stellen die Protocol Buffer eine echte Innvotation dar. Eine bewährte Innovation noch dazu, denn Google-intern ist das Protokoll bereits in zahlreichen Projekten beim Datenaustausch im Einsatz. Die Protocol Buffer integrieren sich erstaunlich gut in Java und stellen eine echte Alternative zu XML dar.

Das Projekt, das auf code.google.com gehostet wird, bringt viele Beispiele, Tutorials und eine gute Dokumentation für die Programmiersprachen C++, Python und natürlich Java mit. Aktuell liegt das Projekt in der Version 2.0 noch als Beta-Version vor und kann zumindest für Windows bereits als Binary heruntergeladen werden. Für unixartige Betriebssysteme bleibt derzeit nur der Weg, das Projekt aus den Sourcen zu kompilieren.

Um die Java-Unterstützung zu kompilieren, ist zusätzlich ein installiertes Maven 2 auf dem System erforderlich. Zum finalen Release wird es sicherlich auch für Unix entsprechende Binaries zum Download geben. Dieser Artikel wurde auf einem Mac erstellt, hier ergaben sich absolut keine Probleme beim Kompilieren der Protocol Buffer. Mit den Protocol Buffern zeigt Google eindrucksvoll, dass es auch noch Wege abseits von XML gibt. Ob sich dieser Weg allerdings zu einer Autobahn entwickeln wird, sprich ob sich die Technologie auf breiter Ebene durchsetzen wird, das bleibt sicherlich noch abzuwarten. Auf einem guten Weg ist Google mit seinen Protocol Buffern dennoch allemal.

Marc Teufel arbeitet als Software-Entwickler bei der hama GmbH & Co und ist dort für die Entwicklung großer Java-Anwendungen im Logistikzentrum zuständig. Er ist Autor zahlreicher Fachartikel zu Java und .NET, hat zwei Bücher zu Web Services publiziert und spricht regelmäßig auf Fachkonferenzen. Unter www.teufel.net ist er im Web zu erreichen.
  1. Meldung auf JAXenter
  2. Google Protocol Buffers
  3. Java Tutorial

Teil 1   Teil 2   

Kommentare