Dienstag, 16. Dezember 2008

UTF-8 in HTML-Formularen

Bei einem HTML-Formular kann man den zu verwendenden Zeichensatz mit dem Parameter

accept-encoding="UTF-8"

auf UTF-8 stellen. Leider wird dieser Zeichensatz beim Abschicken des Formulars nicht mit übermittelt, so dass der Server raten muss, welcher Zeichensatz verwendet wurde. Und er rät immer "ISO-8859-1", so dass bei einem Formular mit UTF-8 die Umlaute falsch interpretiert werden. Abhilfe schafft der folgende Aufruf:

request.setCharacterEncoding("UTF-8");

er muss vor dem ersten request.getParameter() kommen, damit er funktioniert. Damit werden die Parameter als UTF-8 interpretiert und das Formular funktioniert.

Freitag, 21. November 2008

Tomcat, Glassfish auf Port 80

Unter Unix Betriebssystemen dürfen die Ports unter 1024 nicht von normalen Benutzern verwendet werden, sondern nur vom Benutzer root. Aus Sicherheitsgründen will man so wenig Prozesse wie möglich mit Root-Rechten laufen lassen, da eine Sicherheitslücke damit automatisch Vollzugriff auf das System bedeutet. Webserver wie Apache helfen sich dadurch, dass ein Prozess mit Root-Rechten auf dem Port 80 lauscht, die Anfragen aber von normalen Benutzer-Prozessen bearbeitet werden. Die Funktionalität des Benutzerwechsels eines Prozesses ist Java nicht möglich. Man kann es auch nicht über JNI tricksen, da Java Threads verwendet und die immer einem gemeinsamen Benutzer gehören.

Eine mögliche Lösung ist es, den Webserver auf einem hohen Port - zum Beispiel 8080 - laufen zu lassen und eine passende Umleitung einzurichten. Dies kann beispielsweise über mod_jk oder mod_proxy im Apache geschehen, oder über eine Umleitung über iptables:

iptables -t nat -A PREROUTING -i eth0 -p tcp \
--dport 80 -j REDIRECT --to-ports 8080


Beide Ansätze haben den Nachteil, dass der Tomcat oder Glassfish denkt, er wird über Port 8080 angesprochen. Dies kann zu Problemen führen, wenn komplette URLs ausgegeben werden, denn diese haben dann :8080 darin. mod_jk und Tomcat kennen als Abhilfe entsprechende Optionen ("proxy-port"), mit denen ein anderer Port mitgeteilt wird.

Es gibt aber auch eine bessere Möglichkeit, mit der ein beliebiges Java-Programm auf privilegierten Ports lauschen kann und trotzdem als normaler Benutzer läuft: authbind und privbind. Die Einrichtung ist sehr einfach; als Beispiel hier die Freigbe des Ports 80 für den Benutzer glassfish: authbind ist SUID-root und kann deshalb direkt vom Benutzer gestartet werden. Bei dem Versuch auf einem niedrigen Port zu lauschen prüft es, ob der Benutzer Schreibzugriff auf eine bestimmte Datei hat. In unserem Beispiel wäre dies die Datei

/etc/autbind/byport/80

Um diese anzulegen, müssen die folgenden Befehle als root eingegeben werden:

touch /etc/authbind/byport/80
chmod 500 /etc/authbind/byport/80
chown glassfish /etc/authbind/byport/80

Für privbind ist eine solche Konfiguration nicht notwendig. Da es nicht SUID-root ist, muss es von root direkt gestartet werden. Außerdem ist es nicht möglich, den Zugriff auf einen Port einzuschränken - es sind immer alle möglich.

Leider haben beide Programme eine große Einschränkung: sie funktionieren nicht mit IPv6 sondern nur mit IPv4. Java versucht standardmäßig auch IPv6 zu nutzen, was einen Fehler zur Folge hat. Dem Java-Prozess muss deshalb die Option
-Djava.net.preferIPv4Stack=true
mitgegeben werden. Beim Tomcat schreibt man dies in die Variable CATALINA_OPTS in der Datei setenv.sh/setenv.bat, die man ggf. noch erzeugen muss. Beim Glassfish kommt diese Option in die entsprechende domain.xml in den Abschnitt mit den JVM-Optionen:

<jvm-options>-Djava.net.preferIPv4Stack=true</jvm-options>

Gestartet wird beispielsweise der Glassfish bei Verwendung von authbind als Benutzer glassfish mit

authbind --deep asadmin start-domain domain1

Die Option --deep ist notwendig, da der Java-Befehl ein Skript ist, das den eigentlichen Befehl erst aufruft und hierbei die Rechte für den Port sonst verloren gehen. Will man privbind verwenden, so lautet der Befehl so:

sudo privbind -u glassfish $(which asadmin) start-domain domain1

Starte man den Befehl als Root, kann man das sudo weg lassen.

Dies Ausgabe ist in beiden Fällen diese:

Starting Domain domain1, please wait.

Log redirected to /opt/glassfish-v2ur2/domains/domain1/logs/server.log.

Redirecting output to /opt/glassfish-v2ur2/domains/domain1/logs/server.log

Domain domain1 is ready to receive client requests. Additional services are being started in background.

Domain [domain1] is running [Sun Java System Application Server 9.1_02 (build b04-fcs)] with its configuration and logs at: [/opt/glassfish-v2ur2/domains].

Admin Console is available at [http://localhost:4848].

Use the same port [4848] for "asadmin" commands.

User web applications are available at these URLs:
[http://localhost:80 https://localhost:443 ].

Following web-contexts are available:
[/web1 /__wstx-services ].

Standard JMX Clients (like JConsole) can connect to JMXServiceURL:
[service:jmx:rmi:///jndi/rmi://pckurt:8686/jmxrmi] for domain management purposes.

Domain listens on at least following ports for connections:
[80 443 4848 3700 3820 3920 8686 ].

Domain does not support application server clusters and other standalone instances.

Auf diesem Server wurde auch der SSL-Port von 8181 auf 443 umgestellt; hierfür ist bei Verwendung von authbind auch die entsprechende Datei notwendig.

Dienstag, 19. August 2008

Fix Imports im NetBeans unter KDE

Die Tastenkombination für Fix-Imports (Strg+Umschalt+I) funktioniert unter KDE nicht solange der Kopete diese Kombination für sich beantsprucht. Zum Ändern die Kontaktliste öffnen und dann

Einstellungen - Globale Kurzbefehle einrichten...

auswählen. Dort kann man dann die Kurzbefehle ändern oder deaktivieren.

Dienstag, 13. Mai 2008

Eclipse auf AMD64

Eclipse auf einem 64-Bit-Prozessor mit Suns JDK stürzt ständig ab. Der Grund hierfür ist Bug #6614100: eine fehlerhafte Optimierung durch den Hotspot-Compiler, die nur unter ganz bestimmten Umständen auftritt, aber leider eben bei Eclipse. Betroffen sind alle JDK/JRE von Sun. Abhilfe schafft das Deaktivieren des Hotspot-Compilers. Macht man dies für das komplette Eclipse, schlafen einem die Füße ein. Erfreulicherweise kann man dies auch ganz gezielt für die eine Klasse deaktivieren, die den Fehler verursacht. Hierfür muss man in seiner eclipse.ini folgende Option am Ende setzen - nach dem -vmargs:

-XX:CompileCommand=exclude,org/eclipse/core/internal/dtree/DataTreeNode,forwardDeltaWith

Hier als Beispiel meine eclipse.ini:

-showsplash
org.eclipse.platform
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms1536m
-Xmx1536m
-XX:PermSize=512m
-XX:MaxPermSize=512m
-XX:CompileCommand=exclude,org/eclipse/core/internal/dtree/DataTreeNode,forwardDeltaWith

Das Erhöhen des Speichers auf 1536 MB und der PermSize auf feste 512 MB beschleunigt Eclipse, sollte aber nur mit ausreichend Speicher gemacht werden. Ob es geklappt hat, sieht man unter Linux mit

ps ux|grep java

Dort müssen die Optionen erscheinen.

Sonntag, 11. Mai 2008

ftplicity auf Ubuntu 8.04 Hardy Heron

Hardy enthält eine neuere Duplicity-Version, bei der sich die Aufrufsyntax geändert hat. Deshalb funktioniert die ftplicity-Version von Heise nicht mehr. Ich hab das Skript passend geändert, so dass es mit neueren - und leider auch nur mit neueren - Versionen von duplicity funktioniert.

Download von ftplicity v2.0

Mittwoch, 30. April 2008

duplicity und ftplicity auf Microsoft FTP Server

Versucht man mit duplicity oder ftplicity auf einen Microsoft FTP-Server zu sichern, erhält man folgende Fehlermeldung:

The filename, directory name, or volume label syntax is incorrect

Dies liegt daran, dass duplicity standardmäßig Dateinamen mit Dopplepunkten erzeugt, die ein Microsoft Betriebssystem nicht verarbeiten kann. Zum Glück gibt es eine duplicity-Option, mit der auf ein anderes Format für Dateinamen umgeschaltet werden kann:

--short-filenames

If this option is specified, the names of the files duplicity writes will be shorter (about 30 chars) but less understandable. This may be useful when backing up to MacOS or another OS or FS that doesn’t support long filenames.

Jetzt gilt es nur noch ftplicity zu überzeugen, diese Option zu verwenden. Da es keinen entsprechenden Parameter in der Konfigurationsdatei gibt, muss man die Programmdatei von ftplicity direkt bearbeiten: um die Zeile 80 herum muss man in der letzten Zeile der Funktion

function ftply { # die eigentliche Wrapper-Funktion
FTP_PASSWORD="$ZIEL_PW" \
PASSPHRASE="$GPG_PW" \
TMPDIR="$TEMP_DIR" \
$DUPLICITY --encrypt-key $GPG_KEY \
--sign-key $GPG_KEY --verbosity $VERBOSITY \
"$@"
}

die zusätzliche Option eintragen:

function ftply { # die eigentliche Wrapper-Funktion
FTP_PASSWORD="$ZIEL_PW" \
PASSPHRASE="$GPG_PW" \
TMPDIR="$TEMP_DIR" \
$DUPLICITY --encrypt-key $GPG_KEY \
--sign-key $GPG_KEY --verbosity $VERBOSITY \
--short-filenames "$@"
}

Danach klappt das Backup auch mit einem Microsoft FTP-Server.

Dienstag, 15. April 2008

GWT das Heimtelefonieren abgewöhnen

Der Hosted-Modus des GWT prüft bei Google, ob die aktuellste Version verwendet wird. Wer dies abschalten möchte, der editiert .java/.userPrefs/com/google/gwt/dev/shell/prefs.xml. Diese Datei enthält die Uhrzeit der nächsten Abfrage in Millisekunden seit 1970. Da dies ein long ist, kann man getrost zwei, drei Neuen vornedran schreiben. Danach gibt es für absehbare Zeit kein nach Hause telefonieren mehr.

Donnerstag, 28. Februar 2008

Exception mit JAX-RPC und SAAJ

Verwendet man JDK 1.6 und JAX-RPC in der mit NetBeans ausgelieferten Version, so erhält man u.U. folgende Exception:

Exception in thread "main" java.lang.ClassCastException: com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl cannot be cast to com.sun.xml.messaging.saaj.soap.MessageImpl
at com.sun.xml.rpc.client.StubBase._postSendingHook(StubBase.java:231)
at com.sun.xml.rpc.client.StreamingSender._send(StreamingSender.java:324)

Die Ursache hierfür ist eine inkompatible SAAJ-Bibliothek. Nach dem Installieren der aktuellen Version von https://saaj.dev.java.net/ klappt es.

Mittwoch, 23. Januar 2008

Java druckt nicht unter Ubuntu 7.10

Versucht man unter Ubuntu 7.10 aus einem Java-Programm etwas heraus zu drucken, so erhält man auf den meisten Systemen diese Exception:

java.lang.NullPointerException: null attribute
at sun.print.IPPPrintService.isAttributeValueSupported(IPPPrintService.java:1147)
at sun.print.ServiceDialog$OrientationPanel.updateInfo(ServiceDialog.java:2121)
at sun.print.ServiceDialog$PageSetupPanel.updateInfo(ServiceDialog.java:1263)

die Ursache hierfür ist die Drehbarkeit der Seite in CUPS v1.3. Hierbei wird beim Modus "automatisch" ein Nullpointer zurückgegeben, mit dem die aktuelle Java-Version noch nichts anfangen kann:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6633656

Damit man trotzdem drucken kann, muss man entweder
  • die Seitendrehung von "automatisch" auf einen festen Wert stellen
  • CUPS auf eine ältere Version umstellen
Da bei meinem Drucker die erste Option nicht ging, hab ich die zweite realisiert. Hierzu musste ich zuerst in der Datei /etc/apt/sources.list Feisty als Quelle angeben:

deb http://de.archive.ubuntu.com/ubuntu/ feisty main restricted

Dann in der Datei /etc/apt/preferences - die ich neu erstellen musste - folgenden Eintrag machen:

Package: cupsys
Pin: version 1.2.8-*
Pin-Priority: 1001

Danach kann man mit

sudo apt-get update
sudo apt-get upgrade

die Version von CUPS auf die ältere deaktualisieren und das Drucken klappt wieder.