01/2014

Webanwendungen in ++ mit Tntnet Programmieren Programmieren Web plus plus Tntnet

90 Angeregt durch die „Reifeprüfung fürs Web“ im -Magazin 11/13​ stellt dieser Artikel das Webframework

Tntnet vor. Mit ihm lassen sich in C++ Webanwendungen mit MVC-Architektur programmieren. Olaf Radicke, Tommi Mäkitalo www.linux-magazin.de

Tntnet-Applikationen lassen sich grund- sätzlich auf zwei Arten umsetzen. Entwe- der kommt ein Tntnet-Application-Server zum Einsatz, um Shared Libraries und Objektdateien zu laden und auszuführen, oder man erzeugt ein einziges lauffähiges Binary. Im ersten Fall besteht die Ap- plikation aus einer Shared Library und dem Tntnet-Application-Server. Im zwei- ten Fall lässt sich alles zu einer einzigen ausführbaren Datei zusammenfassen, was das Ausrollen vereinfacht, etwa auf Embedded-Geräten. Dieser Artikel ver- wendet die zweite Variante.

Zur Ansicht

© nomadsoul1, 123RF.com © nomadsoul1, Das Tntnet-Framework nutzt die ver- breitete Anwendungsarchitektur Model Im Magazin-Schwerpunkt 11/13​ [1] durf- sourcen-schonend. So lassen sich damit View Controller (MVC). Für die View- ten Contao, Rails, Django und Magnolia auch Weboberflächen für die schwäche- Komponente, die für Ansichten zuständig CMS zeigen, wie sie eine Programmier- ren CPUs von Embedded-Geräten ver- ist, sieht es die projekteigene Auszeich- aufgabe lösen. Das inspirierte die Auto- wirklichen. Am anderen Ende des Spek- nungssprache ECPP vor, die C++ über ren, die Beispielanwendung für diesen trums ist es für hohe Lasten skalierbar spezielle Tags in HTML einbettet. Beim Artikel in C++ umzusetzen. Der Online- und unterstützt Multithreading. Zudem Übersetzen wandelt ein Präprozessor sie Veranstaltungskalender (Abbildung 1) ist C++ seit etwa drei Jahrzehnten ein in C++-Code um, den ein herkömmlicher zapft eine Open-Data-Schnittstelle an, fester Bestandteil der IT-Welt und inter- C++-Compiler zu einer ausführbaren Da- um Straßenfeste anzuzeigen, die in ei- national standardisiert. Das macht Tntnet tei kompilieren kann. Es wäre möglich, nem vom Anwender gewählten Zeitraum zukunftssicher: Anwender können darauf die gesamte Logik als C++-Code in HTML stattfinden. vertrauen, dass der Code wartbar bleibt. einzubetten. Bei kleineren Aufgaben Als Grundlage dient nun Tntnet [2], führt das rasch zu einem Resultat, schon Tommi Mäkitalos C++-Framework für Flexibel bei etwas umfangreicheren Projekten ist Webanwendungen, das unter LGPLv2.1 es aber nicht ratsam. steht. Im Jahr 2003 veröffentlichte er die Tntnet unterscheidet sich in einem Punkt Getreu dem MVC-Prinzip ist in der Such- erste Version, derzeit ist die Release 2.2 wesentlich von verbreiteten Webframe- seite (Listing 1) kaum Logik zu finden, aktuell. Tntnet-Anwendungen laufen works wie Rails oder Django: Es pro- denn sie dient ausschließlich der Ansicht. etwa bei der Deutschen Börse AG, Tom- pagiert nicht das Prinzip „Konvention Die Datei »strassenfeste.ecpp« deklariert mis Arbeitgeber. Dieser Artikel verwendet vor Konfiguration“. Es möchte dem An- zu Beginn mit »<%args>« die Anfrage- die jüngste Version aus dem Entwickler- wender nicht vorschreiben, wie er sein Repository, die der Kasten „Tntnet ins- Projekt zu organisieren und seine Dateien DELUG-DVD tallieren“ einrichtet. zu benennen hat, sondern versucht über Auf der DELUG-DVD zu dieser DELUG-DVD C++ als Technologie für Webanwendun- dokumentierte Best Practice und Howtos Ausgabe finden Sie die Aufgabenstellung sowie gen ist im Vergleich zu Ruby on Rails einen Leitfaden für die Realisierung guter die Auswertung aus dem Schwerpunkt „Reife- und anderen Skriptsprachen sehr Res- Software zu geben [3]. prüfung fürs Web“ im Magazin 11/​13. 01/2014 Programmieren Die Anwendung benutzt ein Formular, um Werte entgegenzunehmen und zu übergeben. Sie sind im Parameter des Typs »tnt::QueryParams« repräsentiert. Ein einzelnes Feld wie »bezirk« lässt sich Tntnet wie folgt auslesen:

sessionShared.bezirk =U 91 qparam.arg("bezirk");

Unerlässlich für interaktive Websites ist das Session-Handling. Tntnet-Controller

bilden es mit Makros ab, beispielsweise www.linux-magazin.de in Zeile 28:

TNT_SESSION_SHARED_VAR(SucheSession,U suche, ());

Es handelt sich hierbei um die Daten, die der Controller gemeinsam mit der View nutzt. Das Makro gibt der Instanz von Abbildung 1: Dank Tntnet lässt sich die Website für die Veranstaltungssuche auch in C++ programmieren. »SucheSession« eine Lebenszeit über den einzelnen Request hinaus für die Dauer Parameter der Veranstaltungssuche. Die Headerdatei, sodass der Anwendungsent- der Session. Jeder User erhält eine eigene unterschiedlichen »scope«-Tags klären wickler die Instanzierung indirekt durch Session, um deren Verwaltung sich Tnt- die Geltungsbereiche von Variablen in- eine Tntnet-Factory-Klasse erledigt (Zeile net automatisch kümmert. nerhalb der Anwendung, einer Session 21). Der Controller erbt von der Klasse Für Werte, die nur die Lebensdauer eines und eines HTTP-Requests. Daneben be- »tnt::Component«, die grundlegende Requests benötigen, gibt es das Makro füllt die Datei das Suchformular mit den Funktionen eines Controllers bereitstellt. »TNT_REQUEST_SHARED_VAR()«. Diese Bezirken und gibt Ergebnisse aus, sofern Variante genügt, um die Kooperation ver- die Suche welche ergab. Controller schiedener Komponenten während eines Im Session-Scope referenziert die ECPP- Requests zu erlauben. Das MVC-Konzept Datei zudem den Header »sucheses­ Die eigentliche Arbeit des Controllers von Tntnet basiert darauf, dass mehrere sion.h«, der die Klassen der Anwendung findet dann in der Methode »operator()« Komponenten oder Controller in Serie bekannt macht. Daneben deklariert sie statt, die HTTP-Request und ‑Reply so- geschaltet eine Anfrage verarbeiten. die gemeinsame Variable »suche«, die die wie die Parameter der Anfrage entgegen- Such-Session für alle Komponenten spei- nimmt (Zeile 23). Die Methode ist ein Fertig! chert. Damit verknüpft sie auch die View Erbstück der Klasse »Component« und mit dem Controller, der die eigentliche wird bei jedem eingehenden Request Das letzte Element in der Operator-Me- Arbeit macht. ausgeführt, egal ob es sich um eine GET- thode heißt »return DECLINED;«. Dieser Die Funktion des Controllers übernimmt oder POST-Anfrage handelt. Darüber hi- Return-Wert teilt dem Tntnet-Applica- der Code in »controller/suche.cpp«, ge- naus lässt sich noch eine ganze Reihe tion-Server mit: Ich bin fertig, ich konnte wöhnlicher C++-Code ohne besondere anderer Informationen über die Klasse meine Arbeit erfolgreich erledigen. Sollte Tags (Listing 2). Es gibt allerdings keine »HttpRequest« abfragen. noch eine weitere Komponente den Re-

Tntnet installieren Das Webframework Tntnet [2] setzt die Bi- lation klont man deren Code von einem Github- Ob Tntnet funktioniert, lässt sich mit einer bliothek Cxx-Tools voraus, die ebenfalls vom Repository [4]. Im entstandenen Verzeichnis einfachen Beispielanwendung testen. In ei- Entwickler Tommi Mäkitalo stammt. Zur Instal- konfigurieren und übersetzen die folgenden nem beliebigen Verzeichnis erzeugt folgender Kommandos den Code: Befehl die Grundlage für die Webanwendung »myfirstproject«: autoreconf ‑i ./configure tntnet‑config ‑‑project=myfirstproject make Im Verzeichnis »myfirstproject/« stößt »make« Das Kommando »su ‑c 'make die Übersetzung an. Anschließend startet das install'« installiert die Tools. Kommando »tntnet« die Anwendung samt Ebenso lässt sich Tntnet von eingebautem Webserver, der sich mit Logmel- [5] klonen und mit den glei- dungen bemerkbar macht (Abbildung 2). Im Abbildung 2: Installation geglückt: Tntnet schreibt sein HTTP-Access- chen Kommandos einsatzbe- Browser ist das Projekt unter »http://local- und das Error-Protokoll auf das Terminal. reit machen. host:8000/myfirstproject« zu erreichen. Listing 1: »strassenfeste.ecpp« (gekürzt)

01 <%args> 15 [...] 29 

02  q; 16 

Suche

><$

03  bezirk; 17  30 bezirke[n] $>

04 [...] 18 

31 % } 05  19  32  06 <%application scope="shared"> 20  33  07  std::vector bezirke; 21  34  08  22  36 
Stichwortsuche:
include="strassenfestresult.h"> 23  37  10  StrassenfestResult strassenfestResult; 24  38 % if (strassenfeste.empty()) { 11  25  Bezirk: 12 <%session scope="shared" 26  39 Keine Ergebnisse include="suchesession.h"> 27