Newsgroup: it.comp.java
Titolo: [OT] "deployare" servlet che usano librerie grafiche su Linux

Buongiorno a tutti.
Stiamo tentando di "deployare" una servlet che fa dei grafici su OC4J
(l'application server di Oracle, in pratica Orionserver) che gira su
SuSE Linux (SLES 7). Questa servlet fa uso di librerie di Oracle le
quali, se ho ben capito, si appoggiano su awt.
Come server di test avevamo usato Tomcat su NT e il tutto funzionava.
OC4J viene lanciato dall'utente "oracle" e ascolta sulla porta 8888.
OC4J è un application server scritto in puro java e io lo lancio con
Java 1.3. Lo script che lo lancia setta la variabile di ambiente
DISPLAY a ":0.0".
Quando si lancia la servlet compare questo errore:
500 Internal Server Error
java.lang.InternalError: Can't connect to X11 window server using
':0.0' as the value of the
DISPLAY variable.
Sulla console è attivo il X server. L'errore scompare soltanto (e la
servlet funziona) soltanto se vado alla console e mi loggo come utente
oracle.
Questo è inaccettabile e ovviamente volevo chiedere lumi, nel caso
qualcuno abbia già incontrato il problema.
Qui di seguito riporto lo stacktrace completo. Grazie a tutti in
anticipo e scusate per l'OT.
Ciao, Cristian
java.lang.InternalError: Can't connect to X11 window server using
':0.0' as the value of the
DISPLAY variable.
        at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
        at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:59)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:120)
        at
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:58)
        at java.awt.Font.initializeFont(Font.java:264)
        at java.awt.Font.<init>(Font.java:298)
        at oracle.ord.media.chart.Chart.<init>(Chart.java:227)
        at oracle.ord.media.chart.legend.Legend.<init>(Legend.java:144)
        at oracle.ord.media.chart.axischart.AxisChart.<init>(AxisChart.java:583)
        at it.crpa.apps.GoCharts.GoCharts.doService(GoCharts.java:1175)
        at it.crpa.apps.GoCharts.GoCharts.doGet(GoCharts.java:1192)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:195)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:309)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:336)
        at com.evermind[Oracle9iAS (1.0.2.2.1) Containers for
J2EE].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:499)
        at com.evermind[Oracle9iAS (1.0.2.2.1) Containers for
J2EE].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:177)
        at com.evermind[Oracle9iAS (1.0.2.2.1) Containers for
J2EE].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:576)
        at com.evermind[Oracle9iAS (1.0.2.2.1) Containers for
J2EE].server.http.HttpRequestHandler.run(HttpRequestHandler.java:189)
        at com.evermind[Oracle9iAS (1.0.2.2.1) Containers for
J2EE].util.ThreadPoolThread.run(ThreadPoolThread.java:62)

 DISPLAY variable.
Be', il messaggio par chiaro. Probabilmente, se la variabile
d'environment DISPLAY non e' definito, per default la libreria usa
DISPLAY:0.0 quando tenta di collegarsi, appunto, al display X... ora, da
console probabilmente hai la variabile d'environment e' gia' settata
correttamente, ma talvolta questo e' fatto semplicemente nel .profile o
.cshrc o simili, e non e' una definizione di inizializzazione. 
Puo' essere quindi che non sia passata al runtime Java (che di solito e'
child di un processo diverso, quello servlet runner, a sua volta, spawn
dal web server, a sua volta spesso e' fatto partire con .rcinit o
simili). 
Prova a fare un export esplicito o far partire il servlet runner (tipo,
JServ, Tomcat o cos'altro usi) assicurandoti che DISPLAY sia
nell'environment del processo. 
Occhio che, non avendo mai usato la libreria, tutto cio' e' wild
guessing. :-) 
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

Può anche darsi che non sia stato installato l'ambiente X su linux... Ciò
può essere normale per un server.
Esisterebbero quindi due possibilità:
installare xvfb (X virtual frame buffer, se non sbaglio l'acronimo) che devi
cercare su internet (simula l'ambiente grafico via software)
installare pja (pure java awt toolkit) e configurarlo per girare con tomcat
(simula l'ambiente grafico, e sono scritte in java, quindi cross platform e
un po' più lente rispetto a xvfb).

 oracle.
Ciao Cristian,
innanzi tutto scusa la lunghezza del post ma, hei, X non è un cosa semplice in fondo! :)
Ci sono varii possibili motivi per cui non puoi connetterti ad un server X, tra i quali
1) non è attivo (ma non è il tuo caso)
2) l'utente non è abilitato a collegarsi (e questo mi dà l'idea che sia il tuo caso; per caso la
servlet gira sotto l'utenza oracle?)
3) varie ed eventuali che non stiamo a discutere
Per controllare che tu ti possa effettivamente connettere e/o per abilitare le connessioni il
comando da utilizzare è xhost. (man xhost)
xhost + permette a TUTTI di connettersi al server X (compresi utenti esterni), quindi in effetti
non è molto consigliabile. Dovresti semmai limitare l'accesso ai programmi che girano su
localhost e sull'IP della tua macchina (cosa che non fai e quindi la tua servlet s'inceppa).
Tuttavia potrebbe esserci la possibilità che tu voglia lanciare una servlet grafica anche quando
Linux è in modalità console (ossia non esista un server X attivo). In questo caso usi Xvfb.
Personalmente ritengo che sia meglio poter lanciare servlet grafiche anche quando X non è attivo
(in fondo consuma le sue belle risorse: memoria grafica, memoria RAM, rete - perchè X funziona
con TCP/IP IIRC), e quindi faccio proprio così (anche perchè sul mio server ho una S3Virge e
quindi con lei non posso andare a 1280x1024x24 bit... con Xvfb si :)
Per far questo occorre a) installare Xvfb stesso, b) verosimilmente mettere un link ad uno script
in /etc/rc3.d/ in modo che parta all'avvio, c) istruire JServ (o Tomcat) su DOVE sia Xvfb (nel
senso, come connettersi).
Per a) basta fare il tipico rpm -i xvfb.XXX.rpm come root.
Per b) ti includo in fondo uno script che lo avvia e che avevo postato poco tempo fa; ha un bug
(all'accensione della macchina non se la dà che Xvfb non è attivo) ma funziona lo stesso. Se hai
il tempo di darci un'occhiata e metterlo a posto tanto meglio... ;)
Per c) occorre includere nel file di configurazione di JServ la variabile di ambiente DISPLAY con
il corretto valore per 'agganciarsi' a Xvfb. Se guardi lo script vedrai che SCREEN è impostata a
1. In questo caso JServ (e qualsiasi applicazione grafica che voglia connettersi a Xvfb) deve
fare una export DISPLAY=:1.0 (IIRC ahimè, il server è a casa e io in ufficio), ossia devi
definire la variabile d'ambiente all'interno di JServ.properties.
A me funziona perfettamente; drawback: Xvfb deve allocare memoria per gestire lo schermo virtuale
- ma il mio server di casa ha 1 giga e 2 di memoria e quindi chissenefrega!!!; pro: puoi non
avere un server X attivo e la tua servlet va lo stesso. Se incontri problemi posso controllare
per filo e per segno la mia configurazione di JServ a casa e ti faccio risapere.
------ Inizio Script -----
#!/bin/sh
# Il seguente script serve a lanciare o fermare Xvfb
# nel processo di avvio o di arresto del server
# processname: xvfb
PIDFILE=/var/xvfb
SCREEN=1
RESOLUTION=1280x1024x24
XVFB=/usr/X11R6/bin/Xvfb
RETVAL=0
function getPID() {
 ps x | grep ^[^.*grep.*] | grep $XVFB >> /var/xvfb
 PID=`ps x | grep ^[^.*grep.*] | grep $XVFB | cut -c0-5`
 if [ "$PID" = "" ]; then
     echo ""
 else
     echo "$PID"
 fi
}
rm -f /var/xvfb >/dev/null 2>&1
echo >/var/xvfb Chiamato xvfb "$1"
# See how we were called.
case "$1" in
  start)
 echo "Start" >>/var/xvfb
 PID=`getPID`
 if [ "$PID" = "" ]; then
     echo -n "Starting Xvfb: "
     $XVFB :$SCREEN -screen 0 $RESOLUTION &
     RETVAL=$?
     if [ $RETVAL -eq 0 ]; then
  echo "started"
     else
  echo "problems encountered"
     fi
     echo
 else
     echo "$XVFB already running with pid $PID"
     echo "$XVFB already running with pid $PID" >>/var/xvfb
     ps x >>/var/xvfb
     RETVAL=10
 fi
 ;;
  stop)
 echo "Stop" >>/var/xvfb
 echo -n "Shutting down Xvfb: "
 PID=`getPID`
 if [ ! "$PID" = "" ]; then
     kill -15 $PID
     RETVAL=$?
     if [ $RETVAL -eq 0 ]; then
  echo "killed"
     else
  echo "problems encountered"
     fi
 else
     echo "$XVFB not running"
     RETVAL=1
 fi
 echo
 ;;
  status)
 echo "Status" >>/var/xvfb
 PID=`getPID`
 if [ "$PID" = "" ]; then
     echo "xvfb not running"
 else
     echo "Xvfb running with pid $PID"
 fi
 RETVAL=0
 ;;
  restart)
 echo "Restart" >>/var/xvfb
 $0 stop
 $0 start
 ;;
  *)
 echo "Unknown: $1" >>/var/xvfb
 echo "Usage: $0 {start|stop|status|restart}"
 exit 1
esac
echo "All done - return value is $RETVAL" >>/var/xvfb
exit $RETVAL
------ Fine Script -----
Se ti interessa il mio post precedente lo ritrovi cercando 'Xvfb Stefano Reksten
group:it.comp.java' con Google (gruppi).
Ciao,
 Stefano
----------
"X WindowSSS, teSSSoro mio... lo odieremo per SSSempre"
Bill Gollum
----------

 simili).
O (più probabile) xhost non lo permette... ;)


 O (più probabile) xhost non lo permette... ;)
Be', se gli funziona dalla console.. ammenoche' l'user o la macchina su cui 
gira la JVM non sia del tutto diversa..


 gira la JVM non sia del tutto diversa..
In effetti la frase "Sulla console è attivo il X server. L'errore scompare
soltanto (e la
servlet funziona) soltanto se vado alla console e mi loggo come utente oracle."
mi incuriosisce. Suppongo che la macchina parta con runlevel 5, e forse
loggandosi l'utenza Oracle abiliti xhost +. Beh se Cristian risolve sicuramente
ci dirà. :)


 ci dirà. :)
Eccomi :)
Ho risolto nel modo suggerito da Stefano, cioè usando Xvfb. Sì, facevo
partire la macchina in runlevel 5, confesso che ho tentato di ciappinare
un po' con xhost ma senza risultati. Poi ho... ehm... fatto una ricerca
su 
groups.google.com
 (lo so, dovevo farlo *prima* di postare, chiedo
venia), ho trovato il vecchio post di Stefano sull'argomento e ho visto
la luce :)
Mi piace molto la soluzione Xvfb, è elegante e mi permette di far
partire la macchina in runlevel 3. Ah, che soddisfazioni che mi da
questo Linux... speriamo soltanto che Xvfb non si mangi troppa RAM! :)
Grazie a tutti per le risposte e buon weekend.
Ciao, Cristian
-- 
Cristian Veronesi ><((((º> 
http://www.crpa.it
"Do you pine for the nice days of minix-1.1, when men were men and wrote
their own device drivers?" (Linus Torvalds, comp.os.minix, 05-10-1991)

 questo Linux...
A chi lo dici... :)


>Ho risolto nel modo suggerito da Stefano, cioč usando Xvfb.
Non te l'avevo suggerito io? :)))
rgds,
~Jigi