Seit einiger Zeit verwenden meine Teamkollegen und ich den Twitter-Account
@oraclebudb, um interessante
Neuerungen, die keine langen Texte erfordern, bekanntzumachen. Wenn Ihr also stets über
Neuigkeiten zur Oracle-Datenbank wie
neue Releases, Patchsets, deutschsprachige Veranstaltungen oder ähnliches informiert sein wollt,
einfach an diesen Account dranhängen ("Folgen").
Nun ist man ab und zu unterwegs und kann einen Tweet nicht immer von seinem iPhone oder
PC absetzen - man möchte einen Tweet "planen" und dann zu einem festgelegten Zeitpunkt,
bspw. "Montag 10:00 Uhr" automatisch absetzen. Sowas kann übrigens auch sehr interessant
sein, wenn man Twitter für regelmäßige Statusmeldungen über etwas nutzen möchte - ich
könnte mir sehr gut vorstellen, zum Beispiel die Pegelstände von Flüssen (vor allem bei
Hochwasser) regelmäßig über Twitter zu posten. Auch hier braucht es einen Automatismus, von
Hand geht nix mehr.
Der Nutzen ist klar - die Frage ist also: Wie setzt man es um? Und ich möchte es natürlich
mit der Oracle-Datenbank, also mit SQL und PL/SQL machen. Eine erste Google-Suche führte
mich denn auch zu zahlreichen Blogs und Webseiten mit PL/SQL-Codefragmenten, die
alle eines gemein hatten: Ich brachte es nicht zum Laufen (wobei das wohl eher an mir lag)
Allein das von Twitter
verwendete OAuth-Verfahren, welches von einer Anwendung genutzt werden muss, implementiert
man nicht mal eben in 5 Minuten in PL/SQL.
Im Java-Bereich gibt es allerdings eine sehr populäre Bibliothek für Twitter:
twitter4j. Und da
man in einer Oracle-Datenbank auch Java laufen lassen kann, habe ich mich entschlossen,
das Rad nicht neu in PL/SQL zu erfinden, sondern das zu nutzen, was da ist ...
Im folgenden findet Ihr also eine Anleitung, wie man eine PL/SQL-Prozedur in die
Datenbank legt, die unter einem bestimmten Account twittert. Mit dieser Variante
kann nur der Account-Eigentümer per PL/SQL twittern - die Autorisierung durch andere
Nutzer ist prinzipiell möglich, hier aber nicht beschrieben.
Schritt 1: Applikation auf "dev.twitter.com" registrieren:
Loggt euch mit eurem Twitter-Account auf dev.twitter.com
ein. Navigiert im Menü oben rechts (dort, wo Ihr euren Accountnamen seht) zum Bereich
My Applications und klickt dann die Schaltfläche Create a new Application. Füllt dann den
Dialog aus. Ihr braucht einen Namen, eine Beschreibung und eine Webseite (die muss es für den
Anfang aber nicht wirklich geben). Die Callback-URL wird für heute nicht benötigt (Abbildung 1). Dann
müsst Ihr mit dem CAPTCHA fertig werden und eure Anwendung ist erstellt.
Abbildung 1: Anwendung erstellen
Wenn die Anwendung erstellt wurde, seht Ihr bereits einige wichtige URLs und das
Schlüsselpaar für die Anwendung selbst (Consumer Key und Consumer Secret).
Abbildung 2: Die Anwendung wurde erstellt
Nun navigiert Ihr zu den Settings eurer neuen Anwendung und stellt die
Berechtigungen auf Read and Write. Das ist wichtig, denn das Absenden eines
Tweets ist ein "Write.
Abbildung 3: Vergeben der Berechtigung "Read and Write"
Nun zurück zur ersten Reiterkarte Details. Unten seht Ihr eine Schaltfläche
Create My Access Token - damit generiert Ihr die
nötigen Accountschlüssel für den eigenen Account (Access Token und Access Token Secret).
Diese, den Consumer Key und das Consumer Secret bitte merken - das
brauchen wir in der Stored Procedure.
Abbildung 4: Access Token und Access Token Secret
Nun seid Ihr mit dem Registrieren der Anwendung fertig. Jetzt geht es zur Oracle-Datenbank.
Schritt 2: Twitter4j in die Datenbank laden.
Ladet twitter4j von der Webseite twitter4j.org
herunter. Twitter4j ist Open Source unter der Apache Lizenz - kann also für alle Anwendungsfälle, sei
es kommerziell oder nicht, verwendet werden. Das ZIP-Archiv muss in ein Verzeichnis eurer Wahl
ausgepackt werden - am besten legt Ihr es gleich auf den Datenbankserver.
Abbildung 5: ZIP Archiv "twitter4j"
Die Java-Bibliotheken befinden sich im Unterverzeichnis lib. Für einfache Status-Updates
braucht Ihr nur das Archiv twitter4j-core-2.2.4.jar. Das wird nun wie folgt in die Datenbank geladen.
$ loadjava -user {dbuser}/{dbpassword} -o -r -v twitter4j-core-2.2.4.jar
Ihr sehr nun einige Meldungen und zum Schluß kommen einige Fehlermeldungen, die Ihr
aber ignorieren könnt.
skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.xml skipping : resource META-INF/maven/org.twitter4j/twitter4j-core/pom.properties The following operations failed class twitter4j/internal/logging/SLF4JLogger: resolution class twitter4j/internal/logging/SLF4JLoggerFactory: resolution exiting : Failures occurred during processing
Schritt 3: Java-Klasse für ein Status-Update erstellen
Es wäre sehr aufwändig, die Methoden der Twitter4j-Bibliothek direkt auf PL/SQL abzubilden. Dafür
sind es zu viele und vielfach werden Java-Objekte übergeben, deren Mapping auf Datenbanktypen nicht
einfach ist. Der beste Weg ist es, die Operationen, die man haben möchte, in Java zu implementieren,
dabei einfache Funktionssignaturen zu verwenden und diese "Top-Level"-Methoden dann nach
PL/SQL abzubilden. Zuerst also die Java-Klasse, die auf Basis der Twitter4j-Beispiele gebaut wurde. Achtet darauf,
in der Methode setOAuthAccessToken die Schlüssel von dev.twitter.com einzutragen. Weiter
vorne in den Calls zu System.setProperty müsst Ihr euren Proxy-Server eintragen, wenn die Datenbank hinter einer
Firewall steht. Wenn nicht, entfernt die Zeilen einfach.
create or replace and compile java source named TwitterStatusUpdate as import twitter4j.*; import twitter4j.conf.*; import twitter4j.auth.*; import java.io.*; import java.util.*; import oracle.jdbc.*; import oracle.sql.*; import java.sql.*; public class UpdateStatus { static Twitter twitter = null; static { System.setProperty("http.proxyHost", "{Proxy-Server, falls nötig}"); System.setProperty("http.proxyPort", "{Proxy-Server-Port, falls nötig}"); ConfigurationBuilder confbuilder = new ConfigurationBuilder(); confbuilder.setOAuthAccessToken("{Access-Token aus dev.twitter.com}") .setOAuthAccessTokenSecret("{Access-Token-Secret aus dev.twitter.com}") .setOAuthConsumerKey("{Consumer-Key aus dev.twitter.com}") .setOAuthConsumerSecret("{Consumer-Secret aus dev.twitter.com}"); twitter = new TwitterFactory(confbuilder.build()).getInstance(); } public static String updateStatus(String newStatus) throws Exception { Status status = twitter.updateStatus(newStatus); return status.getText(); } } / sho err
Schritt 4: PL/SQL Wrapper für die Java-Methode erstellen
Für diese statische Java-Metjode updateStatus, die einen String entgegennimmt und zurückgibt, lässt
sich nun sehr einfach ein PL/SQL-Mapping erstellen.
create or replace function set_twitter_status(p_new_status in varchar2) return varchar2 is language java name 'UpdateStatus.updateStatus(java.lang.String) return java.lang.String'; / sho err
Schritt 5: Privilegienvergabe
Ein Twitter-Posting wird über das Netzwerk abgesetzt - das darf ein "normaler" Datenbankuser mit
Java erstmal nicht. Damit die obige Java-Klasse auch tatsächlich funktioniert, muss der Datenbankuser
Privilegien zum Netzwerkzugriff und zum Einstellen des Proxy-Servers (falls nötig) erhalten. Das
erledigt man wie folgt - das Skript muss als DBA gestartet werden.
begin dbms_java.grant_permission( '{DB-SCHEMA}', 'SYS:java.util.PropertyPermission', 'http.proxyHost', 'read,write' ); dbms_java.grant_permission( '{DB-SCHEMA}', 'SYS:java.util.PropertyPermission', 'http.proxyPort', 'read,write' ); dbms_java.grant_permission( '{DB-SCHEMA}', 'SYS:java.net.SocketPermission', 'api.twitter.com:80', 'connect, resolve' ); end; /
Abschluß
Dann ist es fertig. Nun könnt Ihr testen ...
SQL> select set_twitter_status('another test at friday') from dual; SET_TWITTER_STATUS('ANOTHERTESTATFRIDAY') ------------------------------------------------------------------------ another test at friday 1 Zeile wurde ausgewählt.
Wenn Ihr euch die Twitter-Seite eures Accounts anseht, solltet Ihr das Posting nun
sehen ... und von hier aus ist eine Automatisierung kein Thema mehr - ob man nun
per Scheduler-Job regelmäßig etwas twittert, eine APEX-Anwendung zum Planen der Tweets
erstellt oder andere Dinge tut - mit den Mitteln der Datenbank kann dies nun beliebig
genutzt werden. Eine einfaches Beispiel ist demnach eine APEX-Anwendung mit einem Formular
auf eine Tabelle. Im Formular kann man Tweets und eine Zeitpunkt eintragen, zu dem der
Tweet gepostet werden soll. Ein DBMS_SCHEDULER-Job läuft dann regelmäßig los und postet
automatisch alle "fälligen" Tweets. Und natürlich kann man mit twitter4j noch mehr tun als nur Status-Updates
abzusetzen, aber wie man bspw. die Home-Timeline abruft, dazu mache ich am besten
ein eigenes Blog Posting. Viel Spaß auf jeden Fall beim Ausprobieren ...