Safari mata el applet de Java que lanzó un JFileChooser (inactivo)

Necesito abrir un cuadro de diálogo para abrir un archivo en una página web y hacer que el usuario seleccione un archivo (¡no para cargarlo!). Como necesito acceder a la ruta completa del archivo, no puedo usar un formulario/entrada. Por lo tanto, uso un applet de Java firmado.

En mi caso de prueba, se llama a un método de applet de Java desde una función de JavaScript. El método applet abre un cuadro de diálogo para abrir archivos (JFileChooser). Si se deja inactivo durante aprox. 30", Safari (*) elimina el subprograma. En mis pruebas, Chrome es más agradable, aparece la alerta "no responde", mientras que a Firefox aparentemente no le importa.

IIUC, este es un comportamiento específico de Safari, pero es muy inconveniente. Necesito que el diálogo permanezca activo hasta que el usuario haga una elección. Miré a enhebrar el JFileChooser pero ese camino parece ser mucho más complicado, y hacer todo el trabajo solo en Javascript no es posible, por razones de seguridad conocidas. ¿Tienes una solución limpia para esto?

(*) JVM termina en una InterruptedException

preguntado el 09 de marzo de 12 a las 13:03

¿Se puede implementar con devoluciones de llamada y no con un "diálogo modal"? Todavía puede ser un diálogo de tipo modal (por ejemplo, siempre visible). Necesito dejar que JavaScript regrese a su bomba de eventos principal... -

¿Podría dar más detalles sobre eso o indicarme información más detallada? -

"En mi caso de prueba, se llama a un método de applet de Java desde una función de JavaScript". Quizás el navegador está notando que el JS tarda demasiado en completarse y eso es lo que lo está matando. Si ese es el caso, la solución podría ser hacer que el applet llame al script una vez que haya terminado. De esa forma el script no se queda 'bloqueando el navegador'. -

@AndrewThompson Gracias por la explicación, eso es lo que pensé, pero no estaba seguro de los detalles. -

1 Respuestas

Su problema se deriva del hecho de que los diálogos en Java se comportan como llamadas de método de bloqueo (en realidad, es un truco de ingeniería increíble cómo lo hacen que desearía que adoptaran otros conjuntos de herramientas). Entonces, cuando su javascript invoca el método en el código Java, está esperando que se cierre ese cuadro de diálogo. El navegador detecta que el hilo de javascript no ha regresado por un tiempo y simplemente decide que está completamente bloqueado y lo elimina. Por lo tanto, el applet de Java se cae con la página.

Deberá hacer la transición a una interacción de estilo asíncrono. La llamada que hace Javascript debería regresar inmediatamente. Puede usar SwingUtilities.invokeLater() en Java para eliminar esa llamada del hilo de llamada de Javascript. El truco entonces es que una vez que se descarta el diálogo, necesita Java para llamar a Javascript. Así que tendrás javascript registrando algún tipo de mecanismo de devolución de llamada. Algo como lo siguiente. No puedo recordar cómo javascript externo -> Java funciona exactamente, así que esto es solo un pseudocódigo para ilustrar la idea:

function showFileDialog() {
    applet.showFileDialog( function( filepath ) {
       if( filepath ) {
          alert( "Hey they picked " + filepath );
       } // must have hit cancel if filepath is null
    } );
}

Mientras tanto en Java:

public void showFileDialog( JavascriptFunction someJavascriptFunction ) {
    SwingUtilities.invokeLater( new Runnable() {
        public void run() {
            JFileChooserDialog chooser = new JFileChooser();
            ...
            int option = chooser.showOpenDialog( parent );

            someJavascriptFunction.invoke( option == JFileChooser.APPROVE_OPTION ? 
                                           chooser.getSelectedFile().getAbsolutePath() : 
                                           null );
        }
    });
}

respondido 09 mar '12, 15:03

Oh hombre, el dolor que he tenido trabajando en una aplicación completamente implementada con el bloqueo de JDialogs... No sé si desearía eso en otro kit de herramientas alguna vez. ;) - Espina G

@chubbard Gracias por los fragmentos de código, me llevaron en la dirección correcta. La solución completa es un poco más elaborada, ya que incluye un subprograma firmado pero básicamente se ve como arriba. - usuario861847

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.