Newsgroup: it.comp.java
Titolo: iniziamo con le applet nelle JSP...

A malinquore :) mi tocca cominciare a mettere le applet nelle JSP
Vi spiego ciò che voglio fare:
L'utente deve compilare un form HTML in cui ci sono due combo: la prima è la
provincia e la seconda è il comune.
All'inizio la combo del comune è disabilitata.
Quando l'utente seleziona la provincia (esempio "TO") la combo dei comuni
deve essere popolata con tutti i comuni in provincia di Torino. Questo,
vorrei farlo attraverso una applet che viene notificata da un JavaScript
"onChange" di eseguire una query (stavo pensando ad un servizio XML
simil-soap).
Dico giusto?
Ho dato uno sguardo a AppletContext, ma non dà la possibilità di accedere (e
modificare) i contenuti del documento HTML. Immagino che, per accedere ai
componenti del documento HTML dovrò fare il downcast all'implementazione
utilizzata dal browser... o sbaglio ?
In altre parole... sto per cominciare a sondare la rete alla ricerca di
soluzioni a questi due problemi
1) un JavaScript che notifica un applet all'interno della stessa pagina
2) un'applet "invisibile" che modifica i controlli presenti nella pagina che
la contiene.
Spero di ricevere qualche informazione utile.
Thanks & regards.
-Jigi

Siccome Netscape non ha innerHTML (DynamicHTML) non riesco a far funzionare
l'aggeggio...
Qualcuno sa dirmi come si fa in Netscape a riempire un tag
programmaticamente da Java o JavaScript?
questo è il mio html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "
http://www.w3.org/TR/xhtml1/DTD/transitional.dtd
">
<html xmlns="
http://www.w3.org/TR/xhtml1
">
  <head>
    <title>
      HTML Test Page
    </title>
    <script>
    <!--
    function writeHtml(arg) {
        document.dynamic.innerHTML = arg;
    }
    // -->
    </script>
  </head>
  <body>
    it.csi.sert.util.Comuni will appear below in a Java enabled browser.
    <br />
    <applet codebase="."
            code="it.csi.sert.util.Comuni.class"
            name="comuni"
            width="0"
            height="0"
            hspace="0"
            vspace="0"
            align="top"
            mayscript="mayscript">
      <param name="provincia" value="" />
    </applet>
    <FORM NAME>
    <INPUT TYPE="BUTTON" VALUE="Print"
      OnClick="javascript:comuni.print();">
    </FORM>
    <br>
    <span ID="dynamic" >
        hi!
    </span>
  </body>
</html>

Da un'applet è possibile aprire un URL che punti ad un servlet per poterne
leggere la risposta?
Se non sbaglio le connessioni di rete sono sottoposte a limitazioni nel caso
vengano stabilite da un'applet. Se non ricordo male l'applet può connettersi
soltanto all'host da cui è stata scaricata, altrimenti dovrebbe cacciar
fuori una SecurityException?
oppure sbaglio?



E' esatto, a meno che l'applet non sia segnato.
Ciao,
    Bruno.
|
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://bbruno.fasturl.it
|
| 
http://members.xoom.it/bbruno
| 
http://digilander.iol.it/bbossola
|

Per fare comunicare Java e JavaScript devi usare LiveConnect, tecnologia di Netscape a suo
tempo rubata da Microsoft :-)
Dai un'occhiata a questi post precedenti:
http://groups.google.com/groups?hl=en&th=7ae8f7615743e037&seekm=qbXyO%2BX%3DV6lrTyQMvPTyw88geyAP%404ax.com&frame=off
E a questo reference:
http://developer.netscape.com/docs/manuals/js/client/jsguide/lc.htm
Dai un'occhiata alla guida sul sito della Netscape per una panoramica completa
sull'argomento:
http://developer.netscape.com/docs/examples/index.html?content=liveconnect.html
e in particolare:
http://developer.netscape.com/docs/examples/livewire/liveconnect_js_java.html
Facci sapere!
Ciao,
    Bruno.


|


Uhmmmm
ora ho spostato quell'istruzione nel metodo che richiama il JavaScript
    /**
     * Callback al JavaScript "addComune(codice, descrizione)"
     */
    public void addComune(String codice, String descrizione){
        jsObject = JSObject.getWindow(this);
        jsObject.call("addComune", new Object[] {codice, descrizione});
    }
ecco lo stacktrace:
java.security.PrivilegedActionException:
java.lang.reflect.InvocationTargetException: netscape.javascript.JSException
 at netscape.javascript.JSObject.getWindow(Unknown Source)
 at it.csi.sert.util.Comuni.addComune(Comuni.java:84)
 at it.csi.sert.util.Comuni.findComuni(Comuni.java:68)
 at java.lang.reflect.Method.invoke(Native Method)
 at sun.plugin.liveconnect.PrivilegedCallMethodAction.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at sun.plugin.liveconnect.SecureInvocation.CallMethod(Unknown Source)

 ha scritto nel messaggio
news:newscache$e2gbpg$xam$1...@listsrv01.csi.it...


Dovresti postare un pezzo di software funzionante per riprodurre il problema... Ah, una
cosa che mi viene in mente ora: il metodo che richiama getWindow() deve per forza essrere
nella classe che estende java.applet.Applet: nel tuo caso e' cosi?
Poi, che ne dici di postare comunque una micro-applicazione funzionante a mo' di esempio?
Sicuramente apprezzerebbero in molti! Una cosa tipo quella che ho postato io in quel post
che ti ho indicato, o in quell'altro in cui parlavo di stampa in applicazioni Web. A quel
punto poi raccogliamo il tutto e lo spediamo a Cristiano che lo infila nelle FAQ.
Ciao,
    Bruno.


|


(ri-posto, perché in ufficio il news server ha deciso di non funzionare
più, e il newsgrou mi risponde picche se cerco di postare uno zip... )
Ecco il post.
L'ho testato e funziona bene con IE5 e Netscape Navigator 4.7.
Ho provato con Netscape Navigator 6.2 e mi dà quell'eccezione che ho
riportato in quel post; abbiam fatto delle prove con Opera 5 (con Java),
Mozzilla e HotJava e non va, non so perché...
Ad ogni modo IE+Ntscp potrebbero già essere sufficienti per rendere
utilizzabile l'applet nel mio programma (ammesso che mi daranno il benestare
per utilizzare l'applet e che ciò non crei problemi con i reverse proxy ce
usano quì).
Se riesci a farlo funzionare con Netscape 6 sarebbe molto utile, visto che
c'è gente in questo strano mondo che continua ad usare, insieme agli altri
browser sfigati, pure questo.
Al momento non fa connessioni a servlet x eseguire le query necessarie ad
estrarre i comuni di una data provincia, ma l'applet risponde con dei dati
fittizi.
Ciao
Luigi
comuni.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "
http://www.w3.org/TR/xhtml1/DTD/transitional.dtd
">
<html xmlns="
http://www.w3.org/TR/xhtml1
">
  <head>
    <title>
      HTML Test Page
    </title>
    <script>
      <!--
      // ripulisce la combo dei comuni
      function clearComuni() {
          var cmbComune = document.hostform.comune;
          var numOptions = cmbComune.length;
          for (i=0; i<numOptions; i++)
              cmbComune.options[0] = null;
      }
      // forza il resize della combo (solo x Netscape)
      function resizeCombo() {
          if (document.layers && ! document.getElementById)
                  history.go(0);
      }
      // aggiunge un comune alla combo dei comuni
      function addComune(codice, descrizione) {
          var cmbComune = document.hostform.comune;
          cmbComune.options[cmbComune.options.length] = new
Option(descrizione, codice);
      }
      // chiama il metodo findComuni sull' applet
      function callAppletComuni(codiceProvincia) {
          document.comuniApplet.findComuni(codiceProvincia);
      }
      // funzione richiamata dall' onChange della combo delle province
      function changeComboComuni(codiceProvincia) {
          clearComuni();
          callAppletComuni(codiceProvincia);
          resizeCombo();
      }
      // -->
      </script>
  </head>
  <body>
    Test comuni/provincia...
    <br />
    <applet codebase="."
            code="it.csi.sert.util.Comuni.class"
            name="comuniApplet"
            width="0"
            height="0"
            mayscript="mayscript">
    </applet>
    <form name="hostform" method="get" action="">
      <select name="provincia"
onchange="javascript:changeComboComuni(provincia.options[provincia.selectedI
ndex].value)">
        <option value="1">TO</option>
        <option value="2">MI</option>
      </select>
      <select name="comune">
      </select>
      <input type="submit" />
    </form>
  </body>
</html>
il file it\csi\sert\util\Comuni.java
package it.csi.sert.util;
import java.applet.*;
import netscape.javascript.*;
/**
 * @author Luigi R. Viggiano
 * @version 1.0
 */
public class Comuni extends Applet {
    private JSObject jsObject;
    /**Construct the applet*/
    public Comuni() {
    }
    /**Start the applet*/
    public void start() {
        jsObject = JSObject.getWindow(this);
    }
    public void findComuni(String codiceProvincia) {
        final int TO = 1;
        final int MI = 2;
        int cdProvincia = Integer.parseInt(codiceProvincia);
        switch (cdProvincia) {
            case TO :
                addComune("1", "TORINO");
                addComune("2", "SETTIMO");
                addComune("3", "VENARIA");
                addComune("4", "PECETTO");
                addComune("5", "PINEROLO");
                break;
            case MI :
                addComune("6", "MILANO");
                addComune("7", "SESTO SAN GIOVANNI");
                addComune("8", "GALLIATE");
                addComune("9", "GORGONZOLA");
                addComune("10", "ARESE");
                break;
        }
    }
    /**
     * Callback al JavaScript "addComune(codice, descrizione)"
     */
    public void addComune(String codice, String descrizione){



Io lo zip l'ho scaricato dal messaggio precedente, quindi fino al NG e' arrivato.
Comunque lo sto provando con netscape 6.21, ed effettivamente non va. Comunque l'errore
che riporti tu e' dovuto al fatto che il parametro MAYSCRIPT si specifica diversamente,
perche' funzioni devi cambiare il tag applet in questo modo:
    <applet MAYSCRIPT codebase="."
            code="it.csi.sert.util.Comuni.class"
            name="comuniApplet"
            width="0"
            height="0"
    </applet>
Cosi' riesci a prendere il reference a JSObject, senza errori, ma si pianta in un altro
punto :-D
Sfortunatamente non sono ancora riuscito a ricompilare con delle stampe perche' non riesco
a trovare sotto la 6.2 il malefico jar che contiene le classi liveconnect: se sai dov'e'
fammi un fischio. Nel frattempo prova tu apportando quella variazione.
Ciao,
    Bruno.


punto...
Okay, l'ho risolto!
Il problema nasce dalla struttura di sicurezza di Netscape che e' molto + stretta di
quella di IE. In particolare in Netscape i privilegi sono assegnati a livello di _thread_,
non di istanze di oggetti. 
Nel tuo caso il problema nasce quando la funzione javascript chiama il metodo findComuni()
dell'applet: in quell'istante il thread che lo percorre non ha i privilegi necessari per
eseguire poi la chiamata dall'applet verso il javascript, che viene acquisito infatto solo
dai thread che partono dell'applet. Chiaro?
Comunque, allego una soluzione becera (il modello ad oggetti e' inesistente :-D) che pero'
funziona su NS 6.2. Ho modificato il tuo applet in modo che usi un thread generato
dall'applet stesso (e quindi che possiede i privilegi) per eseguire l'operazione.
Provala anche tu e fammi sapere, sicuramente si puo' realizzare un modello ad oggetti che
nasconda la complessita' che adesso appare in questa soluzione brutale :-)(un bel wrapper
per le classi di liveconnect, ad esempio!)
Ciao, 
    Bruno.
package it.csi.sert.util;
import java.applet.*;
import netscape.javascript.*;
/**
 * @author Luigi R. Viggiano, contributi di Bruno Bossola :-D
 * @version 1.0
 */
public class Comuni extends Applet implements Runnable
{
    private static final boolean DEBUG = true;
    private Object   suoLock;
    private JSObject suaWindow;
    private int      suoCodiceProvincia;
 
    public void start() 
    {
        new Thread(this).start();
    }
    public void run()
    {
        if (DEBUG) System.out.println("thread - partito");
        try
        {
            suaWindow = JSObject.getWindow(this);
            suoLock = new Object();
            while(true)
            {
                // il thread si addormenta
                if (DEBUG) System.out.println("thread - in attesa di comandi");
                synchronized(suoLock)
                {
                    try {suoLock.wait();}
                    catch (InterruptedException ex) {}
                }
 
                // si e' svegliato - allora e' stato caricato un codice provincia
                if (DEBUG) System.out.println("thread - invocazione codice provincia");
                doFindComuni();           
            }
        }
        finally
        {
            if (DEBUG) System.out.println("thread - terminato");
        }        
    }
 
    public void findComuni(String codiceProvincia) 
    {
        if (DEBUG) System.out.println("findComuni() - invocata!");
        suoCodiceProvincia = Integer.parseInt(codiceProvincia);
 
        // sveglia il thread
        synchronized(suoLock)
        {
            suoLock.notify();
        }
    }
 
 
    public void doFindComuni() 
    {
        if (DEBUG) System.out.println("doFindComuni() - invocata!");
        final int TO = 1;
        final int MI = 2;
 
        switch (suoCodiceProvincia) 
        {
            case TO :
                addComune("1", "TORINO");
                addComune("2", "SETTIMO");
                addComune("3", "VENARIA");
                addComune("4", "PECETTO");
                addComune("5", "PINEROLO");
                break;
            case MI :
                addComune("6", "MILANO");
                addComune("7", "SESTO SAN GIOVANNI");
                addComune("8", "GALLIATE");
                addComune("9", "GORGONZOLA");
                addComune("10", "ARESE");
                break;
        }
    }
    /**
     * Callback al JavaScript "addComune(codice, descrizione)"
     */
    public void addComune(String codice, String descrizione)
    {
        suaWindow.call("addComune", new Object[] {codice, descrizione});



Subject: applet & nscp 6
Date: Fri, 4 Jan 2002 15:52:05 +0100
Ehilà...
avevi ragione, era l'attributo scritto male che non mi faceva poi funzionar le cose.
Strano che Netscape 6.2 sia più rompxxxlle del 4.7 su queste cose...
scusa se ti scrivo direttamente, ma quì il news server ha deciso di non funzionare più.
ho cambiato l'implementazione del metodo findComuni per far sì che reperisca i comuni
attraverso un URL. All'inizio pensavo di usare XML, ma avrei appesantito inutilmente
l'applet, quando invece usando un Property è più che sufficiente.
     public void findComuni(String codiceProvincia) {
         String path="/anagrafe/anagrafe/controller/comuni.jsp?provincia=" +
                     URLEncoder.encode(codiceProvincia);
         try {
             URL url = new URL(codebase.getProtocol(),
                               codebase.getHost(),
                               codebase.getPort(),
                               path);
             System.out.println("\nURL = " + url);
             Properties props = new Properties();
             props.load(url.openStream());
             Enumeration enum = props.keys();
             while (enum.hasMoreElements()) {
                 String key = (String)enum.nextElement();
                 String value = props.getProperty(key);
                 addComune(key, value);
             }
         } catch (MalformedURLException malfURLEx) {
             malfURLEx.printStackTrace();
         } catch (IOException ioEx) {
             ioEx.printStackTrace();
         }
     }
ho quest'eccezione:
URL = 
http://XXXXX:8080/anagrafe/anagrafe/controller/comuni.jsp?provincia=01+
java.security.PrivilegedActionException: java.lang.reflect.InvocationTargetException:
java.security.AccessControlException: access denied (java.net.SocketPermission XXXXX:8080
connect,resolve)
  at java.security.AccessControlContext.checkPermission(Unknown Source)
  at java.security.AccessController.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkConnect(Unknown Source)
  at sun.plugin.protocol.jdk12.http.HttpURLConnection.connectStep1(Unknown Source)
  at sun.plugin.protocol.jdk12.http.HttpURLConnection.getInputStream(Unknown Source)
  at java.net.URL.openStream(Unknown Source)
  at it.csi.sert.util.Comuni.findComuni(Comuni.java:39)
  at java.lang.reflect.Method.invoke(Native Method)
  at sun.plugin.liveconnect.PrivilegedCallMethodAction.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.liveconnect.SecureInvocation.CallMethod(Unknown Source)
La servlet è nello stesso contesto web da cui viene scaricata l'applet. E ciò, che io
sappia, dovrebbe essere "legale". Se per caso ti viene in mente perché la cosa non
funziona (magari tu il problema l'hai già incontrato e risolto), fammi sapere.
Grazie di tutto, buon weekend.
Luigi
|
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://bbruno.fasturl.it/
|
| 
http://members.xoom.it/bbruno
| 
http://digilander.iol.it/bbossola


Grazie di tutto Bruno.
Risolti i problemi con NS6 non dovrebbero + esserci pretesti per rifiutare
l'applet.
Secondo te è più giusto il modello di sicurezza adottato da NS o quello di
IE ? Le specifiche non dicono niente in merito?
Grazie dinuovo
Jigi


Francamente non saprei :-)
A naso, quello di IE mi sembra piu' passibile di buchi, mentre quello di NS e' fin troppo
sicuro... diciamo che comunque LiveConnect l'ha creato Netscape, quindi, per quanto
riguarda la sicurezza in quel caso, mi sa che hanno ragione loro.
Ciao,
    Bruno.


 riguarda la sicurezza in quel caso, mi sa che hanno ragione loro.
Non capisco quali problemi potevano esserci legandosi all'istanza piuttosto
che al thread, io pensavo addirittura che la discriminante fosse il
ClassLoader a cui appartengono le istanze per applicare i vincoli di
sicurezza, ma non ho mai studiato in dettaglio la cosa. Poi, forse sbaglio,
ma non mi sembra che il live connect c'entri con l'apertura di un URL da
parte di un'applet (che potrebbe anche non fare uso di liveconnect, credo
che in Netscape andrebbe in errore ugualmente, a questo punto).
Ok, il loro sarà più sicuro, però mi sembra che imponga delle restrizioni
che poi ti fanno scrivere del codice che non mi sembra molto "pratico". Alla
fine però la soluzione, come tu mi ha mostrato, è adeguarsi alle restrizioni
più forti, purtroppo...
Jigi


Beh, ma non c'e' problema, in fondo basta un po' di codice. E poi, diciamolo, io mi
diverto ancora un sacco a smanettare :-D
