Die To-do Liste Einträge sollen von einer Datenbank in eine Liste geladen werden. Da ein inchorus Gadget standartmäßig nicht auf eine Datenbank zugreifen kann, bietet das inchorus SDK mehrere Plug-Ins an. Um eine Datenbankverbindung auszubauen, wird nur das „inchorus-database-plugin” benötigt. Im nächsten Schritt wird gezeigt, wie das Plug-In in das MyApp-Gadget eingebunden wird, um eine Datenbank anzubinden.
Wir öffnen hierfür im Packages Explorer die Datei pom.xml in unserem Projekt und tragen folgende Zeilen ein:
<dependency>
<groupId>de.guh.plugin</groupId>
<artifactId>inchorus-database-plugin</artifactId>
<version>2.0.14</version>
</dependency>
Um die Installation abzuschließen, müssen wir noch folgende Befehle ausführen. Dazu wählen wir die pom.xml aus und klicken auf die rechte Maustaste 1.Run as → 4Maven clean 2. Run as → 6Maven install
Damit wir in diesem Tutorial keine Datenbank erstellen müssen, verwenden wir für das Beispiel eine SQLite-Datei. Die Datei „myApp.db” können wir hier inchorus-Downloadbereich herunterladen. Nach dem Herunterladen öffnen wir im Windows-Explorer den Pfad „C:\inchorus\inchorus-gadget-sdk-eclipse-64bit\inchorus-sdk-workspace\inchorus-myApp-Gadget\”, erstellen einen neuen Ordner mit dem Namen „database” und fügen die Datei „myApp.db” in den Ordner ein. Danach wechseln wir in Eclipse, wählen den Reiter Package Explorer und markieren den Ordner „inchorus-myapp-gadget” und drücken F5.
Jetzt müssen wir noch die „JDBC.SQlite” Erweitung in die pom.xml eintragen. Dazu nutzen wir folgenden Code und tragen ihn am Ende der Datei ein:
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.31.1</version>
</dependency>
Im nächsten Schritt wählen wir die pom.xml aus, klicken auf den rechten Mauszeiger. Run as → 4Maven clean und danach Run as → 6Maven install.
Als nächstes soll eine Verbindung mit der Datenbank hergestellt werden. Dies wird in den folgenden Schritten erklärt.
Dazu öffnen wir im Package Explorer den Pfad „inchorus-myapp-gadget/src/de.guh.gadget/MyApp.java” und fügen den folgenden Code in die Klasse „MyApp.java” unter „private static final long serialVersionUID = 1L;” ein:
private static Logger log = Gadget.log;
public static Database dbItems = null;
public static Table tb_Items = null;
Wir erstellen drei Variablen. Die erste Variable ist eine „Private Static“-Variable und die letzten beiden sind „Public Static“-Variablen. Die erste Variable gibt uns die Information über den Programmablauf der Klasse zurück. In der zweiten Variable wird die Datenbank hinterlegt und in der dritten die Tabelle, in der sich die auszuwertenden Daten befinden. Die beiden letzten Variablen werden bei den „Custom Global“-Variablen erstellt, weil wir auch in anderen JAVA-Klassen darauf zugreifen wollen. Nachdem wir die Zeilen hinzugefügt haben, werden die Objekttypen rot unterstrichen und somit als Fehler dargestellt. Um den Fehler zu beheben, müssen wir die folgenden Import-Statements unter der Zeile „import de.guh.gadget.Authorization;” hinzufügen (wenn wir den Import „import de.guh.gadget.Authorization;” nicht finden können, klappen wir die Import-Liste mit einem Klick auf das kleine Plussymbol aus).
import org.apache.logging.log4j.Logger;
import de.guh.plugin.Database;
import de.guh.plugin.Table;
Jetzt bauen wir die Datenbank Verbindung auf. Dafür benötigen wir den Pfad zur SQLite-Datei „myApp.db”. Wir fügen den folgenden Code in die Methode „public void initialize() throws Exception” ein:
dbItems = new Database(
Database.type_SQLLITE,
"jdbc:sqlite:C:/inchorus/inchorus-gadget-sdk-eclipse-64bit/inchorus-sdk-workspace/inchorus-myapp-gadget/database/myApp.db"
);
tb_Items = new Table("items");
tb_Items.addField("itemid");
tb_Items.addField("name");
Mit diesem Code können wir die SQLite-Datei erreichen und eine Verbindung herstellen. Die Variable „dbItems” enthält den Typ der Datenbank und den korrekten Pfad zu der Datei „myApp.db”. Der Variable „tb_Items” übergeben wir die Struktur der Datenbanktabelle. Diese enthält den Namen der Tabelle und die Namen der Spalten.
Damit ist das Herstellen der Datenbankverbindung abgeschlossen.
Wenn wir den Code der JAVA-Dateien im „src/”-Verzeichnis ändern, ist es notwendig die Laufzeitumgebung neu zu starten.
Die Datenbankverbindung wurde in das Gadget integriert und kann nun getestet werden. Wir benötigen aber noch einen Weg, die Daten innerhalb einer XML verwenden zu können. Dies geschieht nach dem Frage-Antwort-Prinzip. Im folgenden Schritt wird gezeigt, wie der JAVA-Code (Backend) Daten aus der Datenbank abruft und diese an eine XML-Struktur zurückgibt. Auf diese XML-Struktur wird dann innerhalb der XSL-Datei zugegriffen.
Beim Laden der Liste, wird das Kommando „getItems” an das Backend gesendet. Dies geschieht in der Klasse „Command.java”, in welcher auf das jeweilige Kommando geprüft und entsprechend reagiert wird. Schließlich wollen wir bei einem „deleteItem” Kommando eine andere Funktion ausführen, als bei dem Kommando „getItems”. Wir benötigen eine Funktion „isValidRequest”, die überprüft, ob ein Wert gefüllt und valide ist. Zudem werden zwei weitere Funktionen benötigt: die Funktion „DatabaseAction” in der die Datenbankabfrage definiert ist und die Funktion „appendXML()”, die die Werte aus der Datenbank in die XML-Knoten schreibt. Wechseln wir dazu in den Pfad im Package Explorer: „inchorus-myapp-gadget/src/de.guh.gadget.pages/Command.java”
import de.guh.gadget.Gadget;
import de.guh.gadget.GadgetPage;
import de.guh.gadget.GadgetRequest;
import de.guh.gadget.GadgetResponse;
import de.guh.gadget.GadgetSession;
import de.guh.gadget.Validation;
import de.guh.gadget.myApp;
import de.guh.plugin.database.DatabaseAction;
import de.guh.plugin.database.Filter;
import de.guh.plugin.database.Record;
import de.guh.plugin.xml.XML;
Fügen wir die obenstehenden JAVA-Bibliotheken für die Web-Komponenten hinzu. Im nächsten Schritt verbinden wir die Command Klasse mit der GadgetPage Klasse wie folgt: public class Command implements GadgetPage. Danach schreiben wir eine Methode, die wir getItems nennen, um die Daten abzurufen.
public void getItems(GadgetRequest gdRequest, GadgetSession gdSession, GadgetResponse gdResponse) throws Exception {
gdRequest.log.info("...[running].");
}
Dieses Kommando wird von der inchorus-list beim Aufruf des Gadgets gesendet und ist für die Anzeige der Daten in der Liste notwendig. Mit dem Kommando „getItems” wird eine neue „DatabaseAction” initialsiert. Die „DatabaseAction” bekommt die vorhin erstellte Database Definition übergeben („MyApp.dbItems”) und speichert darüber den Pfad zur SQLite-Datei und den Namen der Datenbank ab. Der nächste Ausdruck fügt der „DatabaseAction” den Namen der Datenbanktabelle und die angeforderten Spalten hinzu. Dazu kopieren wir die folgende Zeile unter den Ausdruck: „DatabaseAction search = new DatabaseAction(MyAPP.dbItems);”.
search.addTable(MyApp.tbItems);
Der nächste Code-Abschnitt gibt die SQL-Query aus und die von der Datenbank angeforderten Daten in einer XML-Struktur zurück. Fügen wir den Code unter der obigen Zeile ein.
XML xmlItems = search.getSearchRecordsXML("items","item");
gdResponse.appendXML(xmlItems);
Über die Abfrage „XML xmlItems = search.getSearchRecordsXML("items", "item");” erhalten wir alle Einträge (item) aus der Datenbanktabelle ”items” in einer XML-Struktur. Der Ausdruck „gdResponse.appendXML(xmlItems);” fügt alle in der XML-Struktur gespeicherten „items” an die „gdResponse” an, welche dann an das Frontend (XSL-Datei) zurückgegeben wird.
public void getItems(GadgetRequest gdRequest, GadgetSession gdSession, GadgetResponse gdResponse) throws Exception {
gdRequest.log.info("...[running].");
DatabaseAction search = new DatabaseAction(MyApp.dbItems);
search.addTable(MyApp.tb_Items);
XML xmlItems = search.getSearchRecordsXML("items","item");
gdResponse.appendXML(xmlItems);
}
Hier noch einmal der komplette Code für das Kommando „getItems”, das damit abgeschlossen ist. Wir speichern nun alle Änderungen. Im nächsten Kapitel erstellen wir das Frontend des Gadgets.
In diesem Kapitel passen wir die Darstellung (Frontend) des Gadgets für das im vorherigen Kapitel erstellte Kommando (Backend) an. Zuerst erstellen wir uns das Grundgerüst des Gadgets und erweitern dieses in den nächsten Kapiteln.
Zur Erstellung eines Frontends, werden die inchorus Web-Komponenten benötigt, die ineinander verschachtelt sind und miteinander interagieren. In diesem Kapitel wird beschrieben wie das funktioniert und bauen Schritt für Schritt die Frontend Struktur auf. Wir öffnen dazu die Datei „index.xsl”, die wir im Package Explorer unter dem Pfad „inchorus-myapp-gadget/xsl/default_/standalone/default” finden. Zwischen den beiden Tags „<body></body>” finden wir folgenden Code:
<inchorus-gadget>
<xsl:attribute name="id">-1</xsl:attribute>
<xsl:attribute name="version">1.0.1</xsl:attribute>
<xsl:attribute name="path">/<xsl:value-of select="$gadgetpath"/></xsl:attribute>
<xsl:attribute name="displaymode"><xsl:value-of select="$displaymode"/></xsl:attribute>
<xsl:attribute name="integrationmode">integrated</xsl:attribute>
<xsl:attribute name="parameters"><xsl:value-of select="$parametersjson"/></xsl:attribute>
</inchorus-gadget>
Der „<inchorus-gadget>”-Tag bindet ein Gadget mit den entsprechenden Parametern in eine Webseite oder eine andere Anwendung ein. Die Attribute „id="-1"” und „path="/<xsl:value-of select="$gadgetpath"/>"” greifen auf Werte der „gadget_variables.xsl” zu. Diese Datei beinhaltet standardmäßig mitgelieferte Variablen, die über ein Kürzel leicht abrufbar sind. Das Attribut „version=”1.0.1”” ist zwingend notwendig, damit die Webseite im aktuellen Style angezeigt wird. Durch die ID, werden Aktionen und Styles dem richtigen Gadget zugeordnet. Die ID hat auch den Vorteil, dass wir so mehre Gadgets in eine Seite einbinden können und sie so durch ihre IDs voneinander unterscheiden können.
In dem Attribute-Path wird der Teilpfad des zu integrierenden Gadgets eingetragen. In unserem Beispiel „/myapp”.
Als nächstes ändern wir das Attribute integrationmode von integrated in standalone, da unsere index.xsl sonst nicht aufgerufen werden kann.
<xsl:attribute name="integrationmode">integrated</xsl:attribute>
Der nächste Schritt im Template ist der „<inchorus-content>” Tag. Dieser wird zwischen den „<inchorus-gadget>” Tags eingefügt.
</head>
<body>
<inchorus-gadget>
<xsl:attribute name="id">-1</xsl:attribute>
<xsl:attribute name="version">1.0.1</xsl:attribute>
<xsl:attribute name="path">/<xsl:value-of select="$gadgetpath"/></xsl:attribute>
<xsl:attribute name="integrationmode">standalone</xsl:attribute>
<xsl:attribute name="parameters"><xsl:value-of select="$parametersjson"/></xsl:attribute>
<inchorus-content>
<xsl:attribute name="id">page-1</xsl:attribute>
<xsl:attribute name="active">true</xsl:attribute>
<xsl:attribute name="hascontentfile">true</xsl:attribute>
<xsl:attribute name="loglevel">debug</xsl:attribute>
<xsl:attribute name="alternativetargetid">page-1</xsl:attribute>
</inchorus-content>
</inchorus-gadget>
</body>
Mithilfe des „<inchorus-content>” Tags können Inhalte in eine Webseite dynamisch geladen werden, ohne dass die eigentliche Webseite neu geladen werden muss. Das Attribut „id=page-1” stellt eine eindeutige Referenz auf das Content-Element dar, damit der Zugriff von außerhalb möglich ist. Das Attribut „loglevel=”debug”” ist gesetzt, um wichtige Debug-Informationen auf der Konsole des Entwicklermodus auszugeben und so die Fehlersuche zu vereinfachen. Da der Inhalt des Content-Elements zur besseren Übersicht in eine eigene Datei ausgelagert wurde, muss dem Attribut „hascontentfile” der Wert „”true”” zugewiesen werden. Die Datei muss den Namen der ID des Content-Elements tragen, da sie sonst nicht gefunden wird.
<inchorus-content>
<xsl:attribute name="id">page-1</xsl:attribute>
<xsl:attribute name="active">true</xsl:attribute>
<xsl:attribute name="hascontentfile">true</xsl:attribute>
<xsl:attribute name="loglevel">debug</xsl:attribute>
<xsl:attribute name="alternativetargetid">page-1</xsl:attribute>
</inchorus-content>
Um das Template weiter auszubauen, erstellen wir eine neue XSL-Datei auf Basis der „index.xsl”. Deshalb duplizieren wir die „index.xsl” im „Package Explorer” und benenn diese um. Dazu klicken wir mit der rechten Maustaste auf die „index.xsl” → Copy → Paste → und tragen in das nun angezeigte Textfeld „page-1.xsl” ein → OK. Der Name „page-1” der neuen Datei muss mit der ID des „<inchorus-content>” Tags übereinstimmen, damit die neue Datei dem „<inchorus-content>” Element eindeutig zugeordnet wird. Im Anschluss wird der Code in der Datei „page-1.xsl” zwischen den „<xsl:template>” Tags entfernt.
Im nächsten Schritt werden wir ein Text und ein Button im Gadget darstellen. Die Elemente werden innerhalb eines „<div>” platziert, um so eine geordnete Struktur zu erhalten. Wir fügen dafür zwischen den „<xsl:template>” Tags ein öffnendes „<div>” und ein schließendes „</div>”-Tag ein. Den nachfolgenden Code fügen wir zwischen den beiden „<xsl:template>” Tags ein:
<div>
<h3>Meine To-do Liste</h3>
</div>
Der „<h3>”-Tag stellt eine simple Überschrift dar.
Nachdem wir die Änderungen gespeichert und die Webseite im Browser neugeladen haben, sollte die Webseite wie folgt aussehen:
In diesem Schritt fügen wir das „<inchorus-list>”-Tag ein, in dem später die „To-dos” angezeigt werden. Mit der „inchorus-list” Web-Komponente lassen sich verschiedene Daten, z.B. aus einer Datenbank oder einer XML-Struktur, in einer vorkonfigurierten Liste darstellen. Editieren wir die Datei „page-1.xsl” und fügen wir unter dem „<h3>”-Tag folgenden Code ein:
<inchorus-list>
<xsl:attribute name="id">page-1-list</xsl:attribute>
<xsl:attribute name="command">getItems</xsl:attribute>
<xsl:attribute name="hascontentfile">true</xsl:attribute>
<xsl:attribute name="showloader">true</xsl:attribute>
</inchorus-list>
id="page-1-list":
Übergibt eine eindeutige ID ”page-1-list”, diese baut auf der XSL-Struktur auf.
showloader="true":
Bei einer längeren Ladezeit der Liste erscheint ein Ladesymbol.
hascontentfile="true":
Gibt an, dass der Code der Liste in eine eigene XSL-Datei ausgelagert wurde.
command="getItems":
Durch diesen Parameter wird das Kommando „getItems” an das Backend gesendet.
Sobald die Web-Komponente im Browser geladen wurde, wird das Kommando „getItems” an das Backend des Gadgets gesendet. Das Kommando wird in der Klasse „Command.java” verarbeitet und bei Bedarf werden Daten aus der Datenbank angefordert.
Wir erstellen eine neue Datei für die Liste, da wir zur besseren Übersicht den Code auslagern wollen. Dafür duplizieren wir die Datei „page-1.xsl” und benennen diese in „page-1-list.xsl” um, da wir diesen Wert dem Attribut ID in dem „<inchorus-list>”-Tag zugewiesen haben. Als nächstes löschen wir den Code zwischen dem „<xsl:template>”-Tag in der „page-1-list.xsl” Datei heraus. Damit haben wir die Liste erstellt und werden diese im nächsten Schritt mit Inhalt versehen.
Jetzt bearbeiten wir die Liste des Gadgets. Dafür erstellen wir einen Header-Bereich und füllen die Liste mit einem vorerst statischem Text, um zu sehen, wie die Liste dargestellt werden würde.
<xsl:template match="data">
<inchorus-list-header-row>
<inchorus-list-header id="page-1-list-header-1">
<xsl:attribute name="text"><xsl:value-of select="$id-list"/></xsl:attribute>
<xsl:attribute name="sortable">false</xsl:attribute>
</inchorus-list-header>
<inchorus-list-header id="page-1-list-header-2">
<xsl:attribute name="text"><xsl:value-of select="$name-list"/></xsl:attribute>
<xsl:attribute name="sortable">false</xsl:attribute>
</inchorus-list-header>
</inchorus-list-header-row>
<inchorus-list-content id="page-1-list-content" style="min-height:240px;">
<inchorus-list-content-row>
<div>1</div>
<div>Name1</div>
</inchorus-list-content-row>
<inchorus-list-content-row>
<div>2</div>
<div>Name2</div>
</inchorus-list-content-row>
</inchorus-list-content>
</xsl:template>
Mit dem „<inchorus-list-header-row>”-Tag erstellen wir einen Header-Bereich für die Liste. In dem „<inchorus-list-header>”-Tag werden die Überschriften der Spalten einer Liste angezeigt. In dem Wert für das Attribut name werden die Überschriften übergeben. Wir tragen hierfür Variablen ein, die in der Language-Datei festgehalten sind. Die Language-Datei language.xsl finden wir in dem Verzeichnis „xsl/_default/de”. Hier tragen wir die beiden Variablen $id-list und $name-list wie folgt ein:
<xsl:variable name="id-list">ID</xsl:variable> <xsl:variable name="name-list">Name</xsl:variable>
Das Speichern in eine Variable bietet uns zwei entscheidende Vorteile:
Wir haben eine Trennung von Code und Inhalt, was unseren Code übersichtlicher erscheinen lässt.
Wir können so den Inhalt in eine andere Sprache übersetzen und sparen uns damit zusätzliche XSL-Dateien
In dem Attribut sortable=”false” wird festgehalten, dass diese Spalten nicht sortierbar sind. Durch den „<inchorus-list-content>”-Tag wird ein Content-Bereich erstellt, in dem der Inhalt der Tabelle in einzelnen Zeilen darstellt wird. Eine Zeile wird mit dem Tag „<inchorus-list-content-row>” erstellt und innerhalb eines „<div></div>” mit Werten gefüllt. Die einzelnen Zeilen können beim Anklicken einen oder mehrere Events auslösen. Im Moment beinhaltet die Liste noch einen statischen Text, der uns als Platzhalter für die nächsten Schritte dient. Wir werden später den statischen Text durch die Werte aus der Datenbank ersetzen. Wenn wir den Code korrekt eingebunden haben und alle Dateien gespeichert haben, sollte das Gadget wie folgt aussehen.
Die Liste soll nicht nur statischen Text, sondern auch Werte aus einer Datenbank dynamisch anzeigen können. In diesem Kapitel wird erklärt, wie das Frontend des Gadgets in der Lage ist, Werte aus einer Datenbank auszugeben. Wir löschen zunächst den vorhandenen Code in der „page-1-list.xsl” Datei, innerhalb der „<inchorus-list-content>” Tags und fügen dort den folgenden Code ein:
<xsl:for-each select="//items/item">
<xsl:variable name="name" select="name"></xsl:variable>
<xsl:variable name="itemid" select="itemid"></xsl:variable>
<xsl:variable name="position" select="position()"></xsl:variable>
Durch „<xsl:for-each select="//items/item">” holen wir uns die Werte, die dann als Variablen abgespeichert werden. Der folgende Code muss zwischen den Zeilen „<xsl:variable name="position" select="position()"></xsl:variable>” und „</inchorus-list-content>” eingefügt werden.
<inchorus-list-content-row position="{$position}">
<div>
<xsl:value-of select="$itemid"/>
</div>
<div>
<xsl:value-of select="$name"/>
</div>
</inchorus-list-content-row>
</xsl:for-each>
Durch das Attribut „position="{$position}"” wird einer Zeile die Information über die jeweilige Position angehängt, die zur weiteren Verarbeitung oder für Styling-Zwecke (z.B.: Schraffierung) genutzt werden kann. Innerhalb der beiden „<div>” Elemente, werden die Werte der Variablen „itemid” und „name” ausgegeben. Ihre Liste ist jetzt in der Lage, Daten aus dem Backend zu holen und anzuzeigen. Später werden wir mit Hilfe eines „onclick” Events eine Lightbox öffnen. Dabei wird die „itemid” des Listeneintrags als Parameter übergeben. Wir können so eine Detail-Ansicht zu einem To-do anzeigen.
Das abgeschickte Kommando „getItems” kann mit einem Entwicklertool für einen Browser (F12) eingesehen werden.
Alle übertragenen Werte werden in der Log-Datei als XML-Struktur dargestellt und können so überprüft werden.