Posts mit dem Label Java werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Java werden angezeigt. Alle Posts anzeigen

Donnerstag, 30. Dezember 2010

Start der Glassfish Admin-Konsole beschleunigen

[UPDATE]
Es gibt auch einen offiziellen Weg, den Start zu beschleunigen:

http://www.mentby.com/Group/glassfish-users/glassfish-v3-admin-console-very-slow.html

Hierzu ist bei gestopptem Glassfish in der domain.xml die Option


<jvm-options>
-Dcom.sun.enterprise.tools.admingui.NO_NETWORK=true
</jvm-options>

zu setzen sowie die Datei

glassfish/modules/console-updatecenter-plugin.jar

zu löschen. Danach noch in der Domain die beiden Verzeichnisse
  • osgi-cache
  • generated

löschen und den Glassfish wieder starten.
[/UPDATE]

Beim Aufruf der Admin-Konsole des Glassfish dauert es manchmal recht lange, bis sich diese öffnet. Der Grund hierfür sind nicht umfangreiche Initialisierungen - die CPU-Last liegt währenddessen bei 0 - sondern ein "nach Hause Telefonieren", um auf Updates zu prüfen. Man kann dies unterbinden, indem man in /etc/hosts diesen Eintrag einfügt:

127.0.0.2       pkg.sun.com pkg.glassfish.org

Damit startet die Admin-Konsole deutlich schneller.

Sonntag, 13. September 2009

Azureus auf AMD64 (x86_64)

Azureus verweigert unter einem 64-Bit-Linux den Dienst mit der Meldung, dass ihm das 32-Bit SWT unter 64-Bit nicht passt. Zur Abhilfe lädt man das 64-Bit SWT herunter und ersetzt mit der darin enthaltenen swt.jar diejenige von Azureus. Aktuell (12. Juni 2009) ist die URL für SWT diese hier:

http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.5-200906111540/swt-3.5-gtk-linux-x86_64.zip

Da die Zeit vergeht und diese Seiten bestehen bleibt, hier der Weg zur jeweils aktuellsten Version:
  1. Auf der SWT-Seite unter "Releases - Stable" den Link "more..." anklicken
  2. dort unter "SWT Binary and Source" den Link "Linux (x86_64/GTK 2) verwenden.

Dienstag, 31. März 2009

Glassfish, JDBC und DB/2

Der JDBC-Treiber von IBM für DB/2 hat es in sich: normale Verbindungen über den DriverManager funktionieren, aber der Zugriff über eine DataSource - was der Glassfish macht - bricht ab mit einer Fehlermeldung in der Art

Caused by: com.ibm.db2.jcc.a.SqlException: jcc10389122453.51.90
Beim Laden der nativen Bibliothek db2jcct2,
java.lang.UnsatisfiedLinkError: no db2jcct2 in java.library.path ist ein Fehler aufgetreten: ERRORCODE=-4472, SQLSTATE=null

Dies kommt daher, dass der Treiber standardmäßig als Typ-2-Treiber eine native Bibliothek nachladen will. Ich hab es selbst nach Kopieren von 36 MB Bibliotheken nur geschafft, dass er nicht mehr über fehlende Bibliotheken meckert, dafür aber mit einem Segmentation Fault abstürzt. Die Lösung für das Problem ist es dem Treiber zu sagen, dass er ein Typ-4-Treiber sein soll. Beim DriverManager reicht hierfür die Angabe des Ports in der URL. Bei der DataSource muss man die Methode "setType(4)" aufrufen:

DB2DataSource dB2DataSource = new com.ibm.db2.jcc.DB2DataSource();
dB2DataSource.setDriverType(4);
dB2DataSource.setServerName("192.168.1.194");
dB2DataSource.setPortNumber(50000);
dB2DataSource.setUser("XXX");
dB2DataSource.setPassword("YYY");
dB2DataSource.setDatabaseName("ZZZ");
dB2DataSource.setSysSchema("XYZ");
dB2DataSource.getConnection();

und schon klappt es. Im Glassfish ist dies folgendermaßen einzurichten: man wählt als Datenbank DB/2 aus, ändert die Datasource-Klasse in "com.ibm.db2.jcc.DB2XADataSource" und setzt als Type "javax.sql.XADataSource".



Bei den Properties muss man eine zusätzliche Property "driverType" einfügen und sie auf den Wert 4 setzen:


Hat man das gemacht, wir der Ping grün und das ganz ohne native Bibliotheken. Natürlich nicht vergessen, die Treiberdatei in das lib-Verzeichnis der Glassfish-Domain zu kopieren, damit er ihn überhaupt finden kann.

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, 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.

Dienstag, 30. Oktober 2007

Auf JBoss von Außen zugreifen

JBoss lauscht von Hause aus auf der lokalen Adresse, spricht 127.0.0.1. Will man über das Netzwerk darauf zugreifen, muss man ihn mit

run.sh -b

starten, wobei man auch

run.sh -b 0.0.0.0

angeben kann, dann akzeptiert er Verbindungen auf allen Adressen. Auf meinem Ubuntu kam es aber dazu, dass der InvokerLocator noch auf 127.0.0.1:3873 lauschte, was sich so zeigt:

> netstat -ln | grep 3873
tcp 0 0 127.0.1.1:3873 0.0.0.0:* LISTEN

bzw. auf dem Client durch diese Exception:

org.jboss.remoting.CannotConnectException: Can not get connection to server. Problem establishing socket connection for InvokerLocator [socket://127.0.1.1:3873/]

Durch sehr genaues Hinschauen merkt man, dass dort 127.0.1.1 steht, was einen dazu bringt, man in der Datei /etc/hosts nachzusehen:

127.0.1.1 ubuntu

und da hat man den Schuldigen gefunden: JBoss bestimmt den Namen, unter dem er erreichbar zu sein glaubt und lauscht nur auf dieser Adresse. Trägt man hier die richtige eigene Adresse ein, am besten mit dem kompletten Namen, dann funktioniert es auch, also beispielsweise

192.168.1.31 ubuntu.local

Montag, 22. Oktober 2007

JDK 1.3.1 unter Feisty/Gutsy

Installiert man das Sun JDK 1.3.1 unter Ubuntu/Feisty oder Gutsy, so erhält man beim Starten folgende Fehlermeldung:

/opt/jdk1.3.1_20/bin/i386/native_threads/java: error while loading shared libraries: libstdc++-libc6.1-1.so.2: cannot open shared object file: No such file or directory

weil die entsprechende LibC nicht mehr unter diesem Namen verfügbar ist (das mit den unterschiedlichen inkompatiblen (G)LIBC-Versionen hab ich eh noch nie verstanden). Das Problem lässt sich glücklicherweise mit 3 Befehlen beheben:

sudo apt-get install libstdc++2.10-glibc2.2
cd /usr/lib
sudo ln -s libstdc++-3-libc6.2-2-2.10.0.so libstdc++-libc6.1-1.so.2

Danach klappt es auch wieder mit dem Java:

/opt/jdk1.3.1_20/bin/java -version
java version "1.3.1_20"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_20-b03)
Java HotSpot(TM) Client VM (build 1.3.1_20-b03, mixed mode)

Montag, 9. Juli 2007

Maven-Archiva zum Laufen bringen

Archiva erlaubt es, einen zentralen Server für JAR-Dateien aufzusetzen, der von Maven verwendet wird. Es arbeitet als Caching-Proxy, so dass die Pakete nur einmal heruntergeladen werden müssen. Ebenso können damit die intern erstellten Pakete leicht für alle Entwickler zugängig gemacht werden.

Bei der Installation bin ich über mehrere Probleme gestolpert:

Port ändern
Der Port steht in der Datei apps/archiva/conf/application.xml; diese Datei existiert erst nach dem Auspacken der JAR-Datei, was beim ersten Start passiert.

Authentisierung notwendig
Archiva wollte unbedingt Benutzername und Passwort haben. Nachdem ich im User Management dem Guest die Rolle Global Repository Observer gab, ging es auch ohne.

Keine Downloads
Archiva wollte partout keine Pakete runterladen. Nachdem ich bei beiden Proxy Connectors der Whitelist ein **/** hinzugefügt hatte, ging es.


Jetzt kämpfe ich nur noch damit, dass das Eclipse-Plugin die Einstellungen ignoriert und direkt auf das central-Repository zugreift.

Sonntag, 17. Juni 2007

Derby und OutOfMemoryError

Nachdem ich heute wieder mal mehrere Stunden im Derby rumgewühlt habe, hab ich Folgendes zum Derby-Cache gefunden:

"Derby autotunes the database pagesize. If you have long columns, the default pagesize for the table is set to 32K. Otherwise, the default is 4K."

"long columns" sind beispielsweise VARCHAR(32000). Die Standard-Cachegröße ist 1.000 Pages, damit belegt Derby konkret 32MB für seinen Cache, nicht schlecht wenn man bedenkt, dass die JVM standardmäßig nur 64MB hat. Die Folge ist oftmals diese Fehlermeldung:

Exception in thread "main" java.sql.SQLException: Java exception: 'Java heap space: java.lang.OutOfMemoryError'.

Netterweise ist dieser Satz nicht bei den entsprechenden Konfigurationsoptionen - dort steht "Default: 4096" - sondern auf der Seite "Performance trade-offs of large pages". Da guckt man natürlich nicht direkt rein, wenn man die Seitengröße gar nicht ändern will.

Zum Ändern der Seitengröße muss man diese Properties beim Programmstart setzen (hier mit den Standardwerten), wobei die Seitengrölße vor einem CREATE TABLE bzw. CREATE INDEX bereits gesetzt sein muss.

System.setProperty("derby.storage.pageCacheSize", "1000");
System.setProperty("derby.storage.pageSize", "4096");

geht natürlich auch über -Dderby.storage.pageCacheSize=1000 bzw. -Dderby.storage.pageSize=4096 beim Aufruf der JVM.

Montag, 21. Mai 2007

Maven den Download abgewöhnen

Wenn man eigene Jar-Dateien in Maven einbaut, so soll man laut Dokumentation dies folgendermaßen machen:

mvn install:install-file -DgroupId=org.hibernate -DartifactId=hibernate-all -Dversion=3.2 -Dpackaging=jar -Dfile=hibernate-all-3.2.jar

Bei dieser Variante versucht Maven jedoch bei jedem Compilieren die entsprechende POM-Datei herunterzuladen:

Downloading: http://repo1.maven.org/maven2/org/hibernate/hibernate-all/3.2/hibernate-all-3.2.pom

Dies verhindert man, indem man dem "install:install-file"-Aufruf noch die Option "-DgeneratePom=true" hinzufügt. Damit wird eine entsprechende POM-Datei erzeugt und es erfolgen keine Downloads mehr.