Sonntag, 27. Dezember 2009

Scala-Servlets

Ein schönes Beispiel dafür, wie sich gewohnte Java-Programmierung in Scala "anfühlt", sind Servlets:
package com.muchsoft.scala.servlets

import javax.servlet.http.HttpServlet
import javax.servlet.http.{HttpServletRequest => Request,
HttpServletResponse => Response}

class MeinErstesScalaServlet extends HttpServlet {

override def doGet(request: Request, response: Response) {

val ausgabe =
<html>
<head><title>Hallo Scala</title></head>
<body>
<h1>Hallo Scala-Welt!</h1>
</body>
</html>

response.getWriter().print(ausgabe)
}
}
Das sieht doch fast wie Java aus, oder? Nicht ganz: Beim Import können wir Umdefinitionen vornehmen, das override vor der Methodendefinition ist zwingend notwendig, zudem ein Schlüsselwort und keine Annotation. Der Rückgabetyp der Methode doGet() ist nicht angegeben und entspricht dadurch dem Java-void. Für Scala hätten wir vor die öffnende geschweifte Methodenklammer :Unit= schreiben können.

Innerhalb von doGet() legen wir das XML-Literal ausgabe an (als nicht änderbaren Wert mit val; mit var angelegte Variablen versucht man in funktionalen Sprachen zu vermeiden). Dieses XML-Literal schreiben wir ganz normal in den Ausgabestrom des Response-Objekts. Der Typ von ausgabe ist scala.xml.Elem.

Die Struktur der Web-Applikation entspricht dem JavaEE-Standard:


Der vom Scala-Compiler erzeugte Java-Bytecode landet in WEB-INF/classes. Die Scala-Standardbibliothek scala-library.jar (aus dem Scala-Installationsverzeichnis) muss in WEB-INF/lib mit ausgeliefert werden. In WEB-INF/web.xml mappen wir die Klasse com.muchsoft.scala.servlets.MeinErstesScalaServlet auf die URL "hallo.scala". Nach dem Bereitstellen (Deployment) z.B. in Tomcat oder GlassFish kann das Servlet im Web-Browser dann mit der URL http://localhost:8080/halloscala/hallo.scala aufgerufen werden.

Zum Übersetzen der Servlet-Klasse muss sich noch die Servlet-API auf dem Build-Path (Classpath) befinden. Dazu kann man z.B. aus dem Tomcat-Installationsverzeichnis servlet-api.jar oder aus dem GlassFish-Verzeichnis javaee.jar als externe Bibliothek einbinden.

Nun verbessern wir das erste Scala-Servlet und trennen Darstellung und Steuerung etwas besser voneinander:
class MeinZweitesScalaServlet extends HttpServlet {

def ausgabe =
<html>
<head><title>Hallo Scala</title></head>
<body>
<h1>Hallo Scala-Welt!</h1>
<p>Zeit auf dem Server: {jetzt} </p>
</body>
</html>

def jetzt = new java.util.Date

override def doGet(request: Request, response: Response) {
response.getWriter().print(ausgabe)
}
}
ausgabe ist nun eine Funktion außerhalb von doGet(), die auf die Funktion jetzt zurückgreift, um einen aktuellen Zeitstempel auszugeben. Beide Funktionen sind ohne Parameterklammern definiert und müssen daher ohne Klammern aufgerufen werden. Hätten wir die Funktionen mit leeren Parameterklammern definiert, hätten wir es uns beim Aufruf aussuchen können, ob wir die Klammern hinschreiben oder nicht. Es hat sich die Konvention herausgebildet, die Klammern bei der Definition wegzulassen, wenn eine Funktion keine Nebenwirkungen (Seiteneffekte) hat.

Für eine "vollständige" Web-Applikation fehlt noch ein Formular. Bitteschön:
class MeinDrittesScalaServlet extends HttpServlet {

def ausgabe(benutzername: String) =
<html>
<head><title>Hallo Scala-Welt</title></head>
<body>
<h1>Hallo {benutzername}</h1>
<p>Zeit auf dem Server: {jetzt}</p>
<form method="GET" action="hallo3.scala">
<p>Wie heißt Du?
<input name="benutzer" />
<input type="submit" value="Abschicken" />
</p>
</form>
</body>
</html>

def jetzt = new java.util.Date

override def doGet(request: Request, response: Response) {

val param = request getParameter "benutzer"

val benutzername =
if ((param == null) || (param.isEmpty))
"Scala"
else
param capitalize

val antwort = ausgabe(benutzername)

response.getWriter().print(antwort)
}
}
ausgabe() bekommt nun einen String-Parameter übergeben, der in doGet() anhand des Request-Parameters "benutzer" ermittelt wird. Statt des ?:-Operators von Java, den es in Scala nicht gibt, verwenden wir ein besser lesbares if-else, das in Scala ein Ausdruck ist und entsprechend ein Ergebnis liefert.

Wenn diese dritte Servlet-Klasse in web.xml auf die URL "hallo3.scala" gemappt wird, kann der Aufruf im lokalen Applikations-Server mit http://localhost:8080/halloscala/hallo3.scala?benutzer=Thomas erfolgen.

In der Praxis wird man Servlets wohl eher nicht direkt programmieren, sondern ein Framework wie Struts, JSF, Wicket o.ä. einsetzen. Man sieht hier aber gut, wie problemlos man Scala in bestehende Java-(Web-)Anwendungen integrieren kann. Und wenn man Web-Applikationen so richtig funktional entwickeln möchte, kann man das Scala-Lift-Framework nutzen.

Samstag, 12. Dezember 2009

ECMAScript 5

Bis vor ein paar Jahren musste man regelmäßig darauf hinweisen, dass Java nicht JavaScript ist, und JavaScript wurde als Programmiersprache – trotz Objektbasierung und funktionaler Aspekte – nicht ernst genommen. Mit Web 2.0 und Ajax ist dies seit einiger Zeit definitiv anders. JavaScript ist im Frontend akzeptiert, und es gibt keine ernsthaften Diskussionen mehr, ob man es im Browser deaktivieren soll. RIA kommt ohne JavaScript nicht aus.

Vor einer Woche wurde nun die Spezifikation von ECMAScript 5, dem offiziellen Standard für JavaScript, freigegeben. Die neue ECMAScript-Version wurde ziemlich genau zehn Jahre nach der letzten Version, ECMAScript 3, veröffentlicht (Version 4 wurde ausgelassen). Neben vielen kleinen Verbesserungen und einem "strict"-Modus ist nun auch JSON im Standard enthalten. Mit diesem Datenformat können JavaScript-Objekte kompakt durch das Netz übertragen werden.

Für mich ist ECMAScript insofern interessant, als es nun über zehn Jahre her ist, dass ich für den Web-Browser iCab eine JavaScript-Engine (Interpreter) zunächst auf Basis von ECMAScript 2, nach 1999 dann aufbauend auf ECMAScript 3 entwickelt hatte. iCab hat seine Rendering Engine (und damit auch die JavaScript-Laufzeitumgebung) zwar mittlerweile auf Apples WebKit umgestellt, aber die Implementierung einer so zentralen Browser-Komponente gab einen tollen Einblick hinter die technischen Kulissen auf das, wie das Web bis (und gerade) heute funktioniert.

Wie die Zeit vergeht...

Donnerstag, 10. Dezember 2009

Hallo Java EE 6!

Dreieinhalb Jahre nach Java EE 5 hat Sun heute die endgültige Spezifikation von Java EE 6 freigegeben. Bestandteil davon sind u.a. die Spezifikationen von EJB 3.1, JPA 2.0 und JSF 2.0.

Der Download des Java EE 6 SDK enthält den Application Server GlassFish v3 als Referenzimplementation (neben Beispielen samt Dokumentation).

Ebenfalls verfügbar ist die an JEE 6 und GlassFish v3 angepasste Entwicklungsumgebung NetBeans 6.8. Eclipse-Anwender finden hier das entsprechende Plugin.

Wer bereits jetzt Java-Enterprise-Projekte auf Basis von JEE 5 entwickelt, dem dürfte die Umstellung auf die neue Version nicht allzu schwer fallen – sofern der eingesetzte Application Server kompatibel zur neuen Spezifikation ist.

Eine dreiteilige Einführung in Java EE 6 hat Sun hier veröffentlicht.

Dienstag, 8. Dezember 2009

Eclipse 3.5 Galileo, Software-Updates und Proxy-Verbindungen

Je nach Netzwerkumgebung gibt es mit Eclipse immer wieder Probleme beim Installieren von Plugins (über das Menü Help > Install New Software...) bzw. beim automatischen Aktualisieren bereits installierter Erweiterungen (über Help > Check for Updates). Grund sind meistens Proxies, die von Eclipse nicht unterstützte Protokolle verwenden, sowie Firewalls, die eigene Zertifikate für https-Verbindungen ausgeben.

Sofern man das Zertifikat der Firewall besitzt (eine Datei üblicherweise mit der Endung *.cer), kann man dieses in den Keystore der Java-Installation importieren. Welche Java-Installation von Eclipse verwendet wird, kann man unter About Eclipse > Installation Details > Configuration herausfinden. Unter Windows lautet der Aufruf des keytool-Kommandozeilenbefehls beispielsweise
C:\Programme\Java\jre6\bin\keytool -import -v
-file PfadZumZertifikat
-keystore C:\Programme\Java\jre6\lib\security\cacerts
Geben Sie das Keystore-Passwort ein: changeit
"changeit" ist das Standard-Passwort des KeyStores, sofern Sie es nicht geändert haben.


Ein anderes Problem stellen NTLMv2-Proxy-Server dar, die seit Eclipse 3.5 nicht mehr direkt unterstützt werden. Neben der korrekten Einrichtung der Proxy-Adresse und der Authentifizierungsdaten unter Preferences > General > Network Connections muss in der Datei eclipse.ini (im Eclipse-Programmverzeichnis) am Ende folgende Zeile hinzugefügt werden:
-Dorg.eclipse.ecf.provider.filetransfer.excludeContributors=org.eclipse.ecf.provider.filetransfer.httpclient
In Eclipse 3.5 war es in der o.g. Preferences-Seite zudem notwendig, den "Active Provider" auf "Native" zu stellen. In Eclipse 3.5.1 funktioniert auch die Einstellung "Manual".

Montag, 16. November 2009

Scala-Code als und in einer Java-Anwendung ausführen

Compilierter Scala-Bytecode lässt sich problemlos in bestehende Java-Anwendungen integrieren. Möglich ist dies, weil der Scala-Compiler ganz normalen Java-Bytecode erzeugt. Als Laufzeitumgebung sollte dabei Java 5.0 oder neuer zum Einsatz kommen.

Dazu wird eine Scala-Installation benötigt. Am besten nimmt man den IzPack-Installer. Das Installationsverzeichnis heißt im folgenden Beispiel "scala-2.7.7".
object HalloScalaWelt extends Application {
println("Hallo Scala!")
}
Dieses ausführbare Singleton-Objekt speichert man als Datei "HalloScalaWelt.scala", die nun übersetzt und ausgeführt wird:
HeartOfGold:~ much$ scalac HalloScalaWelt.scala
HeartOfGold:~ much$ ls Hallo*.class
HalloScalaWelt$.class HalloScalaWelt.class
HeartOfGold:~ much$ scala HalloScalaWelt
Hallo Scala!
Bereits jedem Java-Einsteiger sollten diese Kommandos irgendwie bekannt vorkommen. Entsprechend führen wir die erzeugten class-Dateien ganz einfach als Java-Anwendung aus:
HeartOfGold:~ much$
java -cp scala-2.7.7/lib/scala-library.jar:. HalloScalaWelt
Hallo Scala!
Unter Windows gibt man beim Klassenpfad (Option -cp oder -classpath) vor dem Punkt am Ende (= aktuelles Verzeichnis) ein Semikolon anstelle des Doppelpunkts an.

Ebenso einfach kann man Scala-Code in bestehende Java-Anwendungen integrieren. Man übernimmt einfach die compilierten class-Dateien und setzt scala-library.jar auf den Klassenpfad – fertig!

Die Benutzung von Klassen zwischen Java und Scala besteht meistens ganz einfach darin, wie gewohnt den (vollqualifizierten oder importierten) Klassennamen zu verwenden.

Freitag, 13. November 2009

Java ME SDK 3.0 für Mac OS X

Die Entwicklung von Applikationen für Java ME, der Java-Plattform für mobile Geräte, war unter Mac OS X ein eher schwieriges Thema. Wichtige Bestandteile des SDKs fehlten oder wurden nicht offiziell unterstützt (Anleitungen für "inoffizielle" Lösungen gibt es z.B. hier, hier oder hier).

Vor drei Wochen hat Sun nun endlich das Java ME SDK 3.0 als Early Access (EA) für Mac OS X 10.5.8 und neuer veröffentlicht. Das DMG enthält das komplette SDK als eine Applikation, die einfach per Drag&Drop in den Programme-Ordner installiert wird.

Die SDK-Entwicklungsumgebung basiert auf der NetBeans-Plattform und ermöglicht erstmalig CLDC-Entwicklung auf Mac OS X. Enthalten ist außerdem der JavaFX 1.2.1 Mobile Emulator.

VisualVM 1.2

Nachdem im Oktober Version 1.2 des Monitoring- und Profiling-Werkzeugs VisualVM veröffentlicht wurde, folgte Anfang dieser Woche das Bugfix-Release 1.2.1. Beide Versionen basieren auf dem Profiler von NetBeans 6.7.1.

Neu ist u.a. die stabile Version des "Sampler"-Plugins, mit dem schnell ein einfaches (aber oft schon vollkommen ausreichendes) CPU- und Speicher-Profiling durchgeführt werden kann. Wie die übrigens Plugins muss auch dieses im Menü Tools > Plugins installiert werden:

Außerdem kann man nun endlich eventuell notwendige Proxy-Einstellungen innerhalb von VisualVM vornehmen. Weitere Änderungen und Ergänzungen sind hier aufgelistet.