Programmierung


Just released a beta of my tiny little project java.orklz.com. java.orklz.com centralizes the latest news from significant Java websites.

Es haben sich doch vermehrt neue Beiträge von mir im Naxos Software & Technology Blog angesammelt:

  1. Know your enemy - Negative CAPTCHA
  2. SOA I: Serviceorientierte Architektur - The Buzzword strikes again
  3. Installation von Bea Weblogic Server 9.2 unter MacOS X 10.5 (Leopard)
  4. SOA II: Automatisierte Erstellung eines Web Service mit Apache Axis2 und Ant

An einem müßigem Wochenende habe ich die J2ME Anwendung “TrafficJammer” entwickelt. Wie es dazu kam und was sonst noch dabei rum kam, könnt man hier nachlesen: TÜR AUF ZUM LABOR: KOORDINATEN, VERKEHRSMELDUNGEN, GOOGLE MAPS UND EINE MOBILE APP.

ZEIT online - Wissen - it-technik : Gemeinsam auf die Spitze treiben

Das Wichtigste wird so quasi zwangsläufig zuerst erledigt und alles Nachrangige nach hinten geschoben. Sollte gegen Ende des Projekts die Zeit knapp werden, dann bleiben lediglich die unbedeutenderen Funktionen auf der Strecke. Der Kunde bekommt dann immer noch ein lauffähiges Programm, das zwar nicht alles hat, was er sich wünschte, mit dem er aber immerhin arbeiten kann.

Ich finde so schlecht Gegenargumente zum XP? Entweder ist mein Google kaputt oder ich weiß auch net?! Also, ich brauch mal Links, Anregungen um das Bild differenzierter zu sehen

Mit diesem Tutorial wollen wir uns mal sozusagen dem Internet hinter dem Internet zuwenden, den Bereich, den man nicht zu sehen bekommt, der aber für den Bereich e-commerce mittlerweile von fundamentaler Bedeutung ist: Webservices.

Was ist das? Ein Webservice stellt Informationen, einen Service, zur Verfügung. Dies ist nicht unbedingt so spannend aber dieser Service agiert nicht direkt mit einem Menschen sondern wird normalerweise von einer Software angesprochen. Die Maschinen sprechen sozusagen automatisiert untereinander. Das hört sich auf jeden Fall schon einmal viel spannender an!

Zur weiteren Vertiefung der Theorie, sei unbedingt auf den Wikipedia-Artikel verwiesen. Insbesondere das Schaubild zur Funktionsweise sollte man sich vor Augen halten.

Wir wollen beispielhaft jetzt einen Beitrag für eine serviceorientierte Architektur (SOA) leisten.


Dazu nehmen wir PHP und XML-RPC. PHP sticht in dem Bereich der SOA nicht unbedingt als die Sprache der 1. Wahl hervor. Meist wird hier Java oder C# verwendet, die Mechanismen sind aber auch in PHP vorhanden. Zur Kommunikation benutzen wir XML-RPC.

XML-RPC bedeutet "XML-Remote-Procedure-Call" und erlaubt die Kommunikation, bzw. den Methodenaufruf, über Software auf verschiedenen Systemen, unter verschiedenen Umgebungen zu kommunizieren. Der gemeinsame Nenner ist ein TCP/IP-basiertes Netzwerk. Die Methodik ist in vielen Programmiersprachen implementiert. Das bedeutet, dass der Anbieter eines Service nicht in der gleichen Sprache erstellt sein muss wie der Konsument.
Den gemeinsamen Nenner des TCP/IP-basierten Netzwerk, muss man noch etwas einschränken: Der Aufruf der entfernten Methoden erfolgt über HTTP. Die Rückgabe der Methode ist dann in intern XML verpackt, wobei dort folgenden Datentypen vorhanden sein können:

  • int, double, boolean, String, DateTime-iso8601, Base64-String (ByteStrom)

Wenn man genauere Ergebnisse benötigt, kann man die Resultate auch in eine Struktur (struct) packen. Ein Struct ist ähnlich einem Hash. Er besitzt einen Key (Typ String) und ein Value (beliebiger oben genannter Datentyp).

Soweit zur Theorie… Bevor die Praxis folgt, sollte man sich folgendes Bild am besten ausdrucken und neben die Tastatur legen. Das Schaubild verdeutlicht die generelle Funktionsweise von XML-RPC (spezialisiert) unter PHP und es wird immer wieder auf das Schaubild zur Erklärung des Code verwiesen.
Bild: xmlRPC.png

Zur Funktionsweise müssen wir noch sicherstellen, dass wir das PEAR-Package XML_RPC benutzen können.

 

Beispiel: Wir implementieren eine Suchfunktion für Mitarbeiter.

Um das Beispiel nicht zu komplex werden zu lassen, kann nur nach dem Ort eines Mitarbeiters gesucht werden.

1. Schritt: Eine Mitarbeiter-Datenbank aufbauen.
Wir implementieren eine rudimentäre Mitarbeiter-Datenbank in MySQL.
Datenbank-Skript mitarbeiter.sql.txt

2. Schritt: Aufbau einer Abfragemaske
Die Abfragemaske wird sehr minimal aufgebaut. Sie stellt nur eine einfache Eingabemöglichkeit dar, einen Ortsnamen einzugeben. Dieser Ortsname wird an den XML-RPC Client übergeben (siehe Bild).
Datei: gui.php

3. Entgegenname der Suchanfrage durch den XML-RPC Client
Zuallerst müssen wir im Client durch einen include sicherstellen, dass wir das PEAR-Package eingebunden haben. Danach packen wir den empfangenen Wert in die Variable $ort.
Jetzt sollten wir uns das Bild wieder zu Hilfe nehmen. Die Variable $ort wird in ein XML_RPC_Value verpackt ($para1) mit der entsprechenden Typ-Angabe (string).
Anschließend muss dieses XML_RPC_Value in ein PHP-Array gepackt werden ($parameterArray) , welches in eine XML_RPC_Message gepackt wird ($nachricht). Der erste Parameter für XML_RPC_Message ist hierbei der Name, der externen Funktion. D.h. der Name der nach außen vom Service her sichtbar ist. Intern kann dieser Name komplett anders heißen. Dazu aber später…
Wir benötigen jetzt eine Instanz vom Typ XML_RPC_Client ($xmlrpc) und übergeben hier den URL-Pfad unter
der der Service erreichbar ist, den Host und den Port. Über diese Instanz, können wir jetzt unsere Nachricht ($nachricht) an den Service verschicken und erhalten das Ergebnis in der Variable $response. In der folgenden If-Bedingung wird das Ergebnis dann entpackt und kann genutzt werden. Wir entpacken hier in die Variable $ergebnis und übergeben das Ergebnis als Get-Parameter an die gui.php zurück.
Datei: client.php

4. Der Service antwortet
Der Service muss als Erstes das PEAR Server Package für XML-RPC inkludieren. Im nächsten Schritt wird eine Instanz vom Typ XML_RPC_Server gebildet. Dieser Instanz wird ein mehrdimensionales Array übergeben. In diesem Array ist ein Array pro Funktion enthalten welches folgende Angaben hat:
Name der Servicefunktion für extern (holeMitarbeiter) als Key, dann bis zu drei Werte in einem Array und zwar der interne Funktionsname und optional docstring und signature. docstring enthält eine Beschreibung, signature gibt den Rückgabewert an und den Typ der zu übergebenden Parameter.
Hier ist also extern der Funktionsname "holeMitarbeiter" sichtbar, der intern auf die Funktion "ichHole" weiterverweist.
In ichHole wird der Übergabeparameter weiterverarbeitet. Die Variable heißt hier $hasen, der Name spielt absolut keine Rolle. in $hasen ist der vom Client verpackte XML_RPC_Value, der in ein PHP-Array gesteckt wurde. Dieser wird hier wieder entpackt und steht uns dann als Variable $ort für die SQL-Abfrage zur Verfügung.
Nachdem die SQL-Abfrage durchgeführt wurde, packen wir die einzelnen Werte in XML_RPC_Values, diese wiederum in ein PHP-Array, welches ebenfalls in ein XML_RPC_Value vom Typ "Struct" gepackt wird ($RPC_ergebnis). $RPC_Ergebnis wird in eine XML_RPC_Response gepackt und ist der Rückgabewert der Funktion.
Datei: server.php

Das wars soweit! Ich hoffe, das Ganze war soweit einigermaßen verständlich und noch nachvollziehbar. Verwiesen werden sollte noch auf die XML_RPC Dokumentation auf der PEAR-Seite: http://pear.php.net/package/XML_RPC/docs/latest/

Zur Vorbereitung meiner Abschlußprüfung, war ich gerade dabei, mich der Thematik AJAX zuzuwenden. Die Erstellung der notwendigen XML-Daten geschah im Unterricht in PHP. Warum auch nicht, das Prinzip soll in erster Linie erklärt werden und PHP-Code ist doch recht schnell zu erstellen.
Habe mich dann aber doch irgendwie in den Gedanken vertieft, mein XML mit Perl zu fabrizieren… Und es hat mich überrascht wie schnell es mir von der Hand ging ohne eine besonders große Einarbeitungszeit. Benutzt habe ich dazu das Modul XML::Writer.
Im nächsten Schritt habe ich versucht eine mehr oder wenig sinnige Aufgabenstellung im AJAX-Kontext umzusetzen: Alle 10 Sekunden erscheint auf einer Website an einer definierten Stelle ein neuer Banner. Die Bannerdaten sollten natürlich von meinem Perl-Skript in wohlgeformten XML geliefert werden. Das Resultat in Perl:


#!/usr/bin/perl
use strict;
use warnings;
# use DBI; # DB-Connectivity wäre hier wohl das eigentliche Einsatzgebiet
use XML::Writer;

my @banner = ("http://192.168.0.2/test/js1/banner/eins.jpg",
   "http://192.168.0.2/test/js1/banner/zwei.jpg",
   "http://192.168.0.2/test/js1/banner/drei.jpg");
my @url = ("http://www.heise.de", "http://www.golem.de", "http://blog.wilkening.info");

# Wir machen eine Browserausgabe also den
# Content-Type und vor allem den doppelten
# Zeilenumbruch nicht vergessen
print "Content-Type: text/xml\n\n";

my $output = "";

# XML geht in die Variable $output.
my $writer = new XML::Writer(OUTPUT => $output);
$writer->setDataIndent(3);

$writer->startTag('Banner');
# Abarbeiten des Array
for (my $i=0; $i< @banner;$i++)
{
   $writer->startTag(’EinBanner’, ID=>$i); # Attribute werden einfach “angehängt”
      $writer->startTag(’bild’);
      $writer->characters($banner[$i]);
      $writer->endTag(’bild’);
      $writer->startTag(’uri’);
      $writer->characters($url[$i]);
      $writer->endTag(’uri’);
   $writer->endTag(’EinBanner’);
}
$writer->endTag(’Banner’);

$writer->end();

Ich finde den Code wirklich simpel aber erkläre noch einmal kurz wichtige Dinge:

  1. use XML::Writer; -> Einbindung des Modul
  2. Die Arrays @banner und @url enthalten die eigentlichen Daten. So etwas kommt normalerweise meist aus einer DB…
  3. print “Content-Type: text/xml\n\n”; -> Auf den konnte ich bei meinen Versuchen nicht verzichten…
  4. my $writer = new XML::Writer(OUTPUT => $output); -> Instanz eines Objekt vom Typ XML:Writer
  5. $writer->startTag(’Banner’); -> Setzen eines Elements, eines Tags. Hier das Root-Element
  6. $writer->endTag(’Banner’); -> Schließen eines Knotens
  7. “Banner” ist das Root-Element. Dazwischen folgen die weiteren Knoten, die in der For-Schleife gebildet werden. Hierbei sollte man noch einmal ein Augenmerk darauf werfen, wie Attribute gebildet werden:
    $writer->startTag(’EinBanner’, ID=>$i); # Attribute werden einfach “angehängt”.
    Der Inhalt der Elemente wird mit $writer->characters($banner[$i]); geschrieben
  8. $writer->end(); -> FERTIG

Die Ausgabe der XML-Datei sieht wie folgt aus:

<Banner>
   <EinBanner ID="0">
      <bild>http://192.168.0.2/test/js1/banner/eins.jpg</bild>
      <uri>http://www.heise.de</uri>
   </EinBanner>
   <EinBanner ID="1">
      <bild>http://192.168.0.2/test/js1/banner/zwei.jpg</bild>
      <uri>http://www.golem.de</uri>
   </EinBanner>
   <EinBanner ID="2">
      <bild>http://192.168.0.2/test/js1/banner/drei.jpg</bild>
      <uri>http://blog.wilkening.info</uri>
   </EinBanner>
</Banner>

Nachdem ich durch externe Hilfe noch auf ein paar Fehler aufmerksam gemacht wurde, den Code mit “use strict” verbessert habe und nun auch noch die Punkte Unterprogramme und “Here-Document” mit aufgeführt habe, sollte “Perl in einer Stunde” soweit erst einmal fertig sein.

Download: “Perl in einer Stunde”

Wenn man mal mit etwas anfängt… Jetzt werde ich mittlerweile gedrängt, Tutorials rauszuhauen. Was auf jeden Fall die Tage folgen wird, ist eine Kurzeinführung zum Thema AJAX sowie XML / DTD / XSLT und vielleicht auch noch XML-RPC mit PHP.

Es gibt in dieser Welt so einige Dinge, um die man am liebsten einen großen Bogen machen möchte: den Gang zur Zulassungsstelle, den fälligen Zahnarztbesuch oder aber auch um ”reguläre Ausdrücke“.  Das Dumme ist nur, man macht sich als Programmierer das Leben unnötig schwer, wenn man darauf verzichtet!

Anhand einiger kleiner Beispiele, versuche ich mal die Arbeitserleichterung “reguläre Ausdrücke” näher zu bringen. Und wenn schon denn schon, sind alle Beispiele in Perl, sollten aber auch in PHP oder einer Hochsprache wie Java nachvollziehbar sein.

 

Situation 1: Ich brauche Ortsnamen die mit “M” beginnen

Die Lösung sieht in Perl wie folgt aus:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ m/^M/)
   {
      print $einOrt.”\n”
   }
}

Der Mustervergleich findet in der IF-Bedingung mit “$einOrt =~ m/^M/” statt. Die Erläuterung ist ziemlich simpel:

  • =~ leitet den Vergelich ein (Beachte: =~ vs. ==) 
  • m bedeutet, dass wir einen Mustervergleich vornehmen wollen
  • ^heißt soviel wie “am Anfang” und
  • M heißt “M” ;-)

Um die minimalen Unterschiede zu anderen Programmiersprachen aufzuzeigen, hier das obige Beispiel in PHP:

<?php
$orte = array(”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);

foreach ($orte as $einOrt)
{
   if (preg_match(’/^M/’, $einOrt))
   {
      echo “$einOrt<br/>”
   }
}
?>

Es wird die Funktion preg_match verwendet. Dadurch können wir auf eine Einleitung des Vergleich mit “m” verzichten.

 

Situation 2: Suchen und Ersetzen

Dummerweise müssen wir alle Ortsnamen die ein “burg” im Namen haben, mit einem “schloss” ersetzen:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ s/burg/schloss/)
   {
      print $einOrt.”\n”
   }
}

Die IF-Bedingung sollte sich hier von selber erklären. “s” bedeutet “substitute” und leitet den Vorgang ein mit dem Suchbegriff “burg” und nachfolgend die Ersetzung “schloss”.
Dieser Vorgang wird nur beim ersten Vorkommen des gesuchten Begriff “burg” vorgenommen. Wenn in einer Zeile alle Vorkommen eines Suchbegriffs ersetzt werden sollen, benötigen wir am Ende des Ausdrucks noch den Modifier “g” (für global). Beispielsweise wollen wir alle “n’s” mit einem “m” ersetzen:

#!/usr/bin/perl
use strict;

my @orte = (”Hannover”, “Muenchen”, “Mainz”, “Hamburg”, “Marburg”);
my $einOrt;

foreach $einOrt (@orte)
{
   if ($einOrt =~ s/n/m/g)
   {
      print $einOrt.”\n”
   }
}

Hierbei wird immer zwischen Groß- und Kleinschreibung unterschieden. Falls diese Unterscheidung nicht stattfinden soll, müssen wir dem Modifier “g” noch den Modifier “i” (für “ignore case”) anhängen:

if ($einOrt =~ s/m/n/gi)

Falls wir jetzt mehrere Zeichen auf einmal ersetzen wollen, brauchen wir die eckigen Klammern []. Beispielsweise wollen wir alle Vokale in einem Satz streichen:

#!/usr/bin/perl
use strict;

my $zeile = “Hallo Leute es ist 09:15 Uhr. Ende”
# [aeiou] Alle Vokale werden mit “” ersetzt
if ($zeile =~ s/[aeiou]//gi)
{
   print $zeile.”\n”
}

Alles was in unserem Suchmuster innerhalb der eckigen Klammern steht, wird nun ersetzt und zwar mit nix ;-)

Das Ganze lässt sich sozusagen negieren. Heißt, alles wird gestrichen, außer die Vokale:

if ($zeile =~ s/[^aeiou]//gi)

Innerhalb der eckigen Klammern bedeutet ^nicht “am Anfang” sondern so viel wie NICHT.

Wir haben aber auch die Möglichkeit, in unserem Beispiel einen Bereich zu ersetzen. Wenn wir z.B. alle Zahlen von 0 bis 9 mit einem Unterstrich ersetzen wollen, müssen wir Folgendes schreiben:

if ($zeile =~ s/[0-9]/_/gi)

 

Situation 3: Komplizierte Mustererkennung

 

Als Situation sei gegeben, dass wir KFZ-Kennzeichen überprüfen müssen. Wir gehen davon aus, dass KFZ-Kennzeichen wie folgt aufgebaut sind:

  1. Zuerst kommen ein bis drei groß geschriebene Buchstaben von A bis Z
  2. Dann folgt ein Bindestrich
  3. Danach 0 bis 3 groß geschriebene Buchstaben von A bis Z und
  4. am Schluss ein bis 4 Zahlen von 0 bis 9

Die Kennzeichen sind beispielsweise in einer Textdatei kfz.txt:

H-GH456
F-MS2207
NOM-T242
H-ZU1
HH-ZU1
HH-ZU
HH-ZUZU1
HHHH-ZU1

Das Perl-Programm sieht wie folgt aus:

#!/usr/bin/perl
use strict;

open(DATEI, “<kfz.txt”);
my @zeilen = <DATEI>
close(DATEI);

my $zeile;

foreach $zeile (@zeilen)
{
   if ( $zeile =~ m/^[A-Z]{1,3}\-[A-Z]{0,3}[0-9]{1,4}/)
   {
      print “Gueltig: “.$zeile.”\n”
   }
   else
   {
      print “Ungueltig: “.$zeile.”\n”
   }
}

 

Situation 4: Komplizierte Mustererkennung und Speicherung in Variablen

 

Jetzt geht es ein wenig härter zur Sache, es wird kryptisch! Sollte uns aber nicht abhalten, diesen letzten Schritt der Einführung durchzustehen. Nehmen wir an, wir haben aus einer Datenbank diverse Links zu Webseiten und FTP-Ordnern bekommen. Es muss eine Möglichkeit geben, dieses für eine Website so aufzubereiten, daß die Verlinkung korrekt dargestellt wird. Wir benötigen also das Protokoll (http oder ftp), eine URL und einen Titel. Jeder Eintrag kommt wie folgt formatiert aus der Datenbank:

{link:http://de.selfhtml.org/{SELFHTML-Seiten}}

Die “Umwandlung” geschieht wie folgt:

#!/usr/bin/perl
use strict;

my $zeile = “{link:http://de.selfhtml.org/{SELFHTML-Seiten}}”

$zeile =~ m/^\{link:(.*):\/\/(.*)\{(.*)\}\}\s*$/;
print “\$1: $1\t\$2: $2\t\$3: $3\n”

Was geschieht hier?

  1. Es findet eine Mustererkennung statt : m
  2. Wir gehen an den Satzanfang und Suchen die Sequenz ab “{link:” die bis zum nächsten Vorkommen von “:/” geht. Die “\” sind die sogenannten Escape-Zeichen, die Sonderzeichen markieren! Die normalen Klammern “()” gruppieren alles was innerhalb von diesem Muster vorkommt “(.*)”. D.h. es steht uns später in der Variable “$1″ zur Verfügung
  3. Die nächste Sequenz geht ab dem Vorkommen von “://” -> “:\/\/” los. Beachte: Die “\” sind die sogenannten Escape-Zeichen, die Sonderzeichen markieren! Sie endet beim nächsten Vorkommen von “{”. Der Inhalt steht uns als “$2″ zur Verfügung
  4. Gleich direkt daran, wird alles bis zum Vorkommen von }} in die nächste Variable “$3″ gepackt -> “(.*)\}\}”
  5. “\s*$/” bedeutet, dass ab hier nur noch Leerzeichen (”\s*”) bis zum Zeilenende (”$”) folgen dürften oder halt sofort das Zeilenende.
    Leerzeichen bedeutet ‘ ‘, \n, \r oder \t

Die Ausgabe sieht wie folgt aus:

$1: http $2: de.selfhtml.org/ $3: SELFHTML-Seiten

 

Ich hoffe, dieser kleine Einstieg hat etwas geholfen. Freue mich wie immer über Kommentare, Kritik usw.. Zur Vertiefung sei das Buch Reguläre Ausdrücke. Praxislösungen für PHP, Perl, MySQL und JavaScript empfohlen!

Ach du schöne neue (Web)welt… Ich dränge, ich warte, ICH WILL:

W3C: Formulare für Web 2.0 in Vorbereitung

Hinzugekommen sind beispielsweise Attribute beziehungsweise Attributwerte für das input-Element. So kann type Werte wie email, url oder datetime annehmen, und Autoren können Felder als “Muss” kennzeichnen (required=”required”).

Gefunden auf heise.de

Next Page »