Java-Bibliotheken und -Anwendungen aus PHP heraus nutzen

Gegensätze ziehen sich an
Kommentare

Im Bereich Unternehmensanwendungen besitzt Java einen beachtlichen Marktanteil. Aus diesem Grund existieren in der Java-Welt viele sehr nützliche Bibliotheken, Frameworks und Schnittstellen, für die es in PHP keine oder bisher nur weniger ausgereifte Entsprechungen gibt. Mit der PHP/Java-Bridge existiert eine Lösung, um aus PHP heraus auf Java-Quellcode und Bibliotheken zuzugreifen.

Der Zugriff auf Java aus PHP-Skripten heraus war lange Zeit ein sehr stiefmütterlich behandeltes Thema. Zwar existierte eine PHP-Erweiterung dazu, die aber aufgrund ihrer Fehleranfälligkeit und langsamen Geschwindigkeit mehr Fluch als Segen war. Mit dem Open-Source-Projekt PHP/Java-Bridge [1] liegt dagegen eine ausgereifte, schnelle und mächtige Lösung vor, um existierende Java-Klassen und -Bibliotheken nutzen zu können.

Zwar steht Entwicklern mit PHP bereits ein System zur Verfügung, dass sehr viele Features mit an Bord hat und sich auch mit Extensions recht einfach um zusätzliche Funktionen erweitern lässt, allerdings mangelt es oftmals an Funktionalität und Bibliotheken, die in der Java-Welt vorhanden sind. Gerade im Bereich von Unternehmensanwendungen existieren doch noch einige Lücken in der PHP-Funktionalität. Für Zugriffe auf ERP-Systeme wie SAP oder die Anbindung anderer Backend-Anwendungen führt oftmals kein Weg an der Verwendung von Java vorbei. Natürlich steht mit der Nutzung von Web Services eine Möglichkeit zur Verfügung, solche Systeme aus PHP heraus anzusprechen, was aber aufgrund der vergleichsweise langsamen Geschwindigkeit nicht immer praktikabel ist. Zudem existieren für Java einige Bibliotheken und Frameworks, für die es in der PHP-Welt keine oder nur unzureichende Entsprechungen gibt. Durch die Verwendung von PHP/Java-Bridge lassen sich beispielsweise auch Systeme und Bibliotheken wie Lucene ([4]), PDFBox ([5]), iText ([6]), FOP ([7]), POI ([8]) oder andere ausgereifte Java-Lösungen nutzen. Auch Umsteiger, die ihre bisherigen Java-Systeme durch PHP ersetzen möchten, haben dadurch den Vorteil, dass sie nicht alles auf einen Schlag austauschen müssen, sondern einzelne Applikationsteile nach und nach anpassen können.

Architektur

Streng genommen ist PHP/Java-Bridge ein Datenaustauschprotokoll auf XML-Basis. Mit diesem Protokoll ist es möglich, eine Brücke zwischen PHP und Java zu schlagen und beide miteinander kommunizieren zu lassen. Die Richtung der Kommunikation ist bidirektional. Aus PHP kann Java-Quellcode verwendet werden, der umgekehrte Weg ist aber ebenso möglich. Entwickler müssen sich mit dem Protokoll nicht auseinandersetzen. Um die ganze Sache so einfach wie möglich zu machen, existiert eine PHP-Erweiterung, mit der die Verwendung von Java-Klassen unkompliziert ist und die alle Aufrufe in das darunterliegende Protokoll umsetzt. Da die Bridge den JSR-223-Standard [10] implementiert, erfolgt das Zusammenspiel zwischen Java und PHP nahtlos. Sogar Sessions können zwischen beiden ausgetauscht werden. Die Lösung ist so flexibel, dass es sogar möglich ist, eine PHP-Anwendung innerhalb des Webcontainers eines J2EE-Servers zu installieren und ablaufen zu lassen, ohne dass PHP auf der Maschine zur Verfügung steht. Die Entwicklungsziele umfassen daher, neben der problemlosen Verwendung von Java-Klassen aus PHP heraus, auch die Integration von PHP in J2EE-Umgebungen. .

Anders als SOAP oder andere Web-Service-Protokolle ist PHP/Java-Bridge speziell auf die Verbindung zwischen Java und PHP zugeschnitten und dementsprechend optimiert. Die daraus resultierenden Geschwindigkeitsvorteile sind enorm. Abbildung 1 zeigt die Architektur der Bridge.

Abb. 1: Architektur der PHP/Java-Bridge
Installation

PHP/Java-Bridge ist bislang nur für Linux verfügbar. Eine installierte Java Virtual Machine ist nicht immer erforderlich. Die Extension bietet einen Modus, in dem nur die Erweiterung auf dem Webserver installiert werden muss. Wir werden diesen Modus später in diesem Artikel noch genauer unter die Lupe nehmen (siehe Abschnitt „Java ohne Java“). Für die folgenden Beispiele werden aber sowohl ein installiertes JDK als auch JRE vorausgesetzt. Für Benutzer von Fedora-Linux stehen auf der Projektseite der Bridge fertig kompilierte Binaries zum Download bereit. Für alle anderen gilt im Folgenden beschriebenes Vorgehen. .

Nach dem Download und Entpacken der kompletten Sourcecodes [9] verläuft die weitere Installation nahezu identisch zu anderen PHP-Erweiterungen. Mit einigen Befehlen auf Kommandozeilenebene ist die Einrichtung schnell erledigt. Für den letzten Schritt sind root-Rechte zwingend notwendig. Einzig die Pfade zu der jeweils verwendeten JDK- und JRE-Installation müssen an die Pfade ihres Systems angepasst werden.

> phpize
> ./configure -with-java=/usr/bin/java-1.5.0,/usr/bin/jre-1.5.0
> make
> su -c 'install.sh'

Nach dem Neustart des Webservers (z.B. mit apachectl restart) steht die Erweiterung unter PHP zur Verfügung. Ist die Installation korrekt verlaufen, so liefert ein Aufruf des Befehls phpinfo() eine Ausgabe der java-Erweiterung. Als Java-Status sollte hier running stehen.

PHP ruft Java

Nachdem die Hürde der Installation genommen ist, steht der Verwendung der Bridge nichts mehr im Wege. Die Extension erweitert den Befehlssatz von PHP um einige Befehle, die für die Arbeit mit Java-Klassen notwenige sind. Das folgende Listing zeigt, wie mit einem dieser Befehle Java-Objekte aus PHP heraus erzeugt werden können.

append('Das PHP Magazin ');
  $objString->append('ist spitze');

  echo (string)$objString;
?>

Dieser Quellcodeausschnitt zeigt die Verwendung des Befehls java, mit dem ein Objekt einer Java-Klasse erzeugt wird. Benötigt man statt eines Objekts eine Klasse, beispielsweise für den Aufruf statischer Methoden, so kann dies mit JavaClass erreicht werden:

getProperty("user.name")." ";
  echo (string)$system->getProperty("os.name")." ";
  echo (string)$system->getProperty("os.arch")." ";
?>

Die Bridge kümmert sich auch um die korrekte Umwandlung der Datentypen. Aus assoziativen PHP-Arrays werden so bei einer Übergabe an eine Java-Methode HashMap-Objekte. Dies funktioniert weitgehend automatisch. Zur Ausgabe der Werte mit PHP ist allerdings noch ein wenig Handarbeit angesagt. In den beiden vorangegangenen Beispielen wurde der Wert eines Java-String-Objekts vor der Ausgabe mit echo explizit in den PHP-Typ string gecastet. Dies funktioniert hervorragend, allerdings setzt es auch voraus, dass der entsprechende Typ der Variable bekannt ist. Wird der Wert eines Objekts benötigt, bietet PHP/Java-Bridge daher die Hilfsfunktion java_values an. Das folgende Beispiel zeigt die Verwendung dieser Funktion. Abbildung 2 zeigt einen Ausschnitt der Ausgabe.

<?php echo "Ohne Mapping:
"; $str = new java("java.lang.String", "PHP Magazin"); echo $str; echo " "; echo "Mit Mapping: "; // PHP String aus Java String echo (java_values($str)); echo " "; // Java String als Array echo "Als Array: "; echo "
";
print_r (java_values($str->toCharArray()));
echo "

";

echo " ";

// Kein Mapping möglich! echo "Objekt ohne Java-Entsprechung: "; echo (java_values(new java("java.lang.System")));

echo " "; ?>

Abb. 2: Automatisches Type-Mapping von Java zu PHP
Externe Bibliotheken

Per Default bietet die Bridge damit Zugriff auf alle Klassen der Java-Klassenbibliothek. Diese liefert bereits einen breiten Funktionsumfang. Selbstverständlich könne nicht alle Klassen verwendet werden. Subsysteme wie beispielsweise AWT und Swing, die für grafische Benutzeroberflächen zuständig sind, lassen sich in Webumgebungen nicht nutzen.

Ähnlich wie PHP lebt auch Java von der Möglichkeit, externe Bibliotheken einzubinden und zu nutzen. Meist stehen für ein Problem gleich mehrere gute Lösungen zur Verfügung. Java-Anwendungen binden diese externen Bibliotheken normalerweise automatisch über den Class-Loader ein, wenn die Bibliothek im CLASSPATH verfügbar ist. PHP/Java-Bridge steht dieser Mechanismus prinzipbedingt nicht zur Verfügung. Alle für die Ausführung notwendigen Bibliotheken müssen explizit eingebunden werden. Die Bridge-Extension bietet dazu den Befehl java_require, mit dem das Einbinden solcher JAR-Dateien problemlos möglich ist. Das folgende Listing zeigt die Verwendung der Java-Bibliothek FOP [7] zur Erstellung von PDF-Dateien aus XML-Daten via XSLT.

render($xmldata, $stylesheet);
?>

Wird kein Pfad für die JAR-Datei angegeben, so wird die Bibliothek im Default-Classpath der Bridge-Extension gesucht. Dieser kann über die php.ini-Datei konfiguriert werden. Da diese Möglichkeit nicht auf allen Servern zur Verfügung steht, kann stattdessen auch ein absoluter Pfad genutzt werden (beispielsweise /srv/www/htdocs/libs/fop.jar). Sogar HTTP- oder FTP-URLs sind problemlos möglich. Damit lassen sich Bibliotheken auch von entfernten Rechnern aus dem Netz laden. Allerdings sollte man in diesem Fall beachten, dass dies nur für selten genutzte Bibliotheken eine sinnvolle Lösung ist, da der Zugriff über dass Netz um Faktoren langsamer ist, als der Zugriff auf lokale Bibliotheken.

Fehlerbehandlung

Sowohl Java als auch PHP verwenden zu Fehlerbehandlung Exceptions. Die Integration zwischen Java und PHP geht hier soweit, dass Exceptions in Java-Klassen durch PHP aufgefangen werden können. So ist eine nahtlose Fehlerbehandlung auch dann möglich, wenn der Fehler in einer externen Bibliothek auftritt. Das folgende Listing zeigt, wie Java-Exceptions auf PHP-Seite aufgefangen werden können.

<?php try {
    new java("java.lang.String", null);
  } catch(JavaException $exception) {
    echo 'Ein Fehler ist aufgetreten
'; echo (string) $exception->getMessage(); } ?>

Java liefert mit jeder Exception einen so genannten Stack-Trace mit, anhand dessen der genaue Verlauf des aufgetretenen Fehlers ersichtlich wird. Um an die Stack-Ausgaben der Java-Exception zu gelangen, sind leider einige Winkelzüge notwendig, wie im catch-Zweig des folgenden Beispiels zu sehen ist. Dies ist notwendig, da die hierfür verantwortliche Java-Funktion printStackTrace normalerweise die Ausgabe direkt auf der Konsole ausgibt. Abbildung 3 zeigt die Ausgabe der Stack-Trace Informationen.

<?php try {
    new java("java.lang.String", null);
  } catch(JavaException $exception) {
    echo 'Ein Fehler ist aufgetreten
'; echo "
";
    $stack = new java("java.io.ByteArrayOutputStream");
    $exception->printStackTrace(new java("java.io.PrintStream", $stack));
    echo "$trace";
    echo "

"; } ?>

Java ohne Java

Eine der herausragenden Funktionen von PHP/Java-Bridge ist die Möglichkeit, Java-Bibliotheken in PHP zu konvertieren. Die so erzeugten Quellcodes können auf einem Rechner ausgeführt werden, auf dem kein Java installiert ist. Die Bridge-Erweiterung ist aber weiterhin notwendig. Was sich auf den ersten Blick unsinnig anhört, hat seine Existenzberechtigung. Das Original-Java von Sun ist nicht auf jeder Linux-Distribution verfügbar. Gerade auf Debian-Linux und dessen Derivate lässt die Java-Unterstützung teilweise zu wünschen übrig. Auch verspricht der Entwickler von PHP/Java-Bridge, dass der Ressourcenverbrauch in diesem Modus geringer ist, als dies mit einer Java-VM der Fall ist.

Die Konvertierung der Bibliotheken muss allerdings zwingend auf einem Rechner durchgeführt werden, auf dem Java installiert ist. Zur Konvertierung muss lediglich die Bibliothek und ein Zielpfad angegeben werden.

> java -jar JavaBridge.jar -convert /usr/share/php5/pear fop.jar

Das war’s! Die Benennung der so generierten PHP Sourcecodes folgt einer einfachen Logik und bildet die Java-Paket-Struktur über den Dateinamen nach. Aus einer Klasse org.apache.fop.PDFRenderer wird so die PHP-Datei org_apache_fop_PDFRenderer.php. Die Verwendung der Bibliothek unterscheidet sich von der zu Beginn des Artikels gezeigten Verwendung lediglich in der Art, wie sie in das PHP-Skript eingebunden und die Objekte erzeugt werden.

render($xmldata, $stylesheet);
?>

Dieses Skript funktioniert dank der Konvertierung auch auf Rechnern ohne Java. Lediglich die so generierten PHP-Klassen und die Bridge-Extension müssen auf dem Server installiert sein.

Altenativen Für PHP 4 existierte lange Zeit eine Extension, die den Sprung nach PHP 5 nicht geschafft hat. Da diese Erweiterung oft mehr Sorgen als Nutzen brachte, wurde sie nicht weiterentwickelt. Zwar gibt es einige unabhängige Projekte, welche diese Erweiterung in fehlerbereinigter Form in Eigenregie weiterführen, dem Funktionsumfang und Performance der PHP/Java-Bridge können sie aber nicht das Wasser reichen. Zend bietet im Rahmen seines Produkts Zend Platform [2] ebenfalls die Möglichkeit, auf Java-Klassen zuzugreifen. Die Verwendung von PHP/Java Integration [3] aus der Zend-Plattform ist ähnlich der in diesem Artikel beschriebenen Vorgehensweise mit PHP/Java-Bridge. Auch hier ist die nahtlose Verwendung von Java-Klassen aus PHP heraus möglich. Den Vorteil des professionellen Supports erkauft man sich allerdings mit einem relativ hohen Grundpreis. Dafür erhält man allerdings dann auch alle anderen Features der Zend-Plattform, Entwicklern steht seit kurzem eine kostenlose Version zur Verfügung.
Fazit

Mit PHP/Java-Bridge existiert eine ausgereifte, mächtige und performante Lösung, um auf bestehenden Java-Quellcode zuzugreifen. Mit den in diesem Artikel beschriebenen Funktionen sind die Möglichkeiten noch lange nicht ausgeschöpft. Durch seine Flexibilität bietet PHP/Java-Bridge noch unzählige andere Möglichkeiten, die eines genaueren Blickes würdig sind.

Der Aufwand erscheint zu Beginn hoch zu sein und lohnt sich auch bestimmt nicht für jede Anwendungen. Doch gerade im Bereich von Enterprise-Anwendungen hat die PHP/Java-Bridge ihre Daseinsberechtigung. Auch wer eine Lösung für spezielle Probleme benötigt, der findet im Java-Bereich meist deutlich ausgereiftere Lösungen, als dies für PHP der Fall ist. Gerade für den Bereich PDF-Bearbeitung und -Erzeugung, Suchmaschine-Anbindung, XSLT und andere Aufgaben existieren für Java sehr gute Bibliotheken.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -