Respuesta serializada entre Applets y Servlets
En uno de nuestros tutoriales anteriores, os mostramos
como se podría comunicar un Applet y un servlet.
Dentro de los procedimientos de comunicación, una de las técnicas preferidas
es la serialización de datos. En el citado tutorial os mostrabamos una porción de
código para comunicar un applet con un servlet y os comentamos que la
comunicación al contrario sería igual.
Ya he recibido varios correos donde os interesáis como hacerlo … podéis
creerme…. es igual (aunque hay que tener en cuenta reglas simple) …. y para
demostrarlo, os voy a poner un ejemplo.
Obviamente, si la respuesta que vas a retornar la vas a querer procesar como
un elemento binario… debes eliminar cualquier respuesta textual … o
asegurarte de ignorarla en el Stream de lectura del applet..
Podemos ir al grano y ver el servlet que hemos generado
/* * servletsimple.java * * Modificado el 15 abril de 2004 */ import java.io.*; import java.net.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; /** * * @author Roberto Canales * @version */ public class servletsimple extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // establecemos el formato de la respuesta response.setContentType("application/octet-stream"); try { // recuperamos el stram de entrada ObjectInputStream bufferentrada = new ObjectInputStream(request.getInputStream()); // leemos un array de datos int[] arrayRecuperado = (int[])bufferentrada.readObject(); // cramos una variable auxiliar String cadenaAux = ""; // iteramos por los elementos for(int i=0; i < arrayRecuperado.length ;i++) { System.out.println("El valor recuperado del elemento " + i + " es " + arrayRecuperado[i]); // concatenamos los elementos que leemos cadenaAux += (arrayRecuperado[i] + " - "); } // Configurarmos un Stream de Salida ObjectOutputStream buffersalida = new ObjectOutputStream(response.getOutputStream()); // construimos el objeto a retornar String[] resultado = new String[2]; // asignamos un elemento fijo resultado[0]="Esta es la cadena retornada"; // y concatenamos el variable resultado[1]= cadenaAux; // escribimos los datos buffersalida.writeObject(resultado); // y los enviamos buffersalida.flush(); } catch(Exception e) { System.out.println("Error al recuperar datos"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } } |
Ahora vamos a realizar una pequeña modificación del applet para que al pulsar
el botón…. se envíe un array de numeros y podeamos leer el array de cadenas
que nos retorne el sistema.
No tenemos porque enviar o recibir un solo elemento …. auque para demostrar
que funciona es suficiente.
Vemos ahora el código del Applet
/* * appletsimple.java * * Modificado el 15 de Abril de 2004 */ package roberto; import java.net.*; import java.io.*; /** * * @author Roberto Canales */ public class appletsimple extends java.applet.Applet { /** Initializes the applet appletsimple */ public void init() { initComponents(); } /** This method is called from within the init() method to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { label1 = new java.awt.Label(); mensajeenviar = new java.awt.TextArea(); label2 = new java.awt.Label(); mensajerecibir = new java.awt.TextArea(); botonenviar = new java.awt.Button(); setLayout(new java.awt.GridLayout(5, 1, 2, 5)); label1.setAlignment(java.awt.Label.CENTER); label1.setForeground(new java.awt.Color(51, 51, 255)); label1.setText("Introduzca el mensaje a enviar al servidor"); add(label1); add(mensajeenviar); label2.setAlignment(java.awt.Label.CENTER); label2.setForeground(new java.awt.Color(255, 0, 0)); label2.setText("Mensaje recibido del servidor"); add(label2); add(mensajerecibir); botonenviar.setLabel("Pulsar para conectar al servidor"); botonenviar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { botonenviarActionPerformed(evt); } }); add(botonenviar); } private void botonenviarActionPerformed(java.awt.event.ActionEvent evt) { String s_textoaenviar = mensajeenviar.getText(); mensajerecibir.setText("Simulacion: " + peticionPost(s_textoaenviar)); } // enviamos la peticion por post String peticionPost(String mensaje) { URL miurl = null; String cadenaaux = null; String cadenaretorno = ""; String consulta = "param1=" + URLEncoder.encode(mensaje); try { // recuperamos la direccion de servidor destino String host = this.getCodeBase().getHost(); // elegimos la URI del recurso a invocar String peticion = "/servlet/servletsimple"; // montamos la direccion base miurl = new URL(getCodeBase(),peticion); // abrimos la conexion URLConnection conexion = miurl.openConnection(); // aactivamos la salida conexion.setDoOutput(true); // Creamos el stream de escritura ObjectOutputStream buffersalida = new ObjectOutputStream(conexion.getOutputStream()); // montamos un array de elementos para enviarlos int array[] = new int[10]; // inicializamos el array for(int i=0;i <array.length;i++) { array[i] = i*3; } // escribimos el objeto buffersalida.writeObject(array); // enviamos buffersalida.flush(); // Creamos el Stream de lectura ObjectInputStream bufferentrada = new ObjectInputStream(conexion.getInputStream()); // creamos la referencia que recogera los datos String respuesta[]; // leemos la respuesta respuesta = (String [])bufferentrada.readObject(); // iteramos por la respuesta y montamos el mensaje for(int i=0 ; i < respuesta.length; i++) { cadenaretorno += (respuesta[i] + "\n"); } buffersalida.close(); bufferentrada.close(); } catch (Exception e) { return "Error al generar url " + e.getMessage(); } return cadenaretorno; } // enviamos por get la petición String peticionGet(String mensaje) { URL miurl = null; String cadenaaux = null; String cadenaretorno = ""; try { String host = this.getCodeBase().getHost(); String peticion = "/servlet/servletsimple?param1=" + URLEncoder.encode(mensaje); miurl = new URL(getCodeBase(),peticion); InputStream buffer = miurl.openStream(); BufferedReader bufferreader = new BufferedReader(new InputStreamReader(buffer)); while( (cadenaaux = bufferreader.readLine()) != null) { cadenaretorno += cadenaaux; } buffer.close(); } catch (Exception e) { return "Error al generar url " + e.getMessage(); } return cadenaretorno; } // Variables declaration - do not modify private java.awt.Button botonenviar; private java.awt.Label label1; private java.awt.Label label2; private java.awt.TextArea mensajeenviar; private java.awt.TextArea mensajerecibir; // End of variables declaration } |
Y, activando el ejemplo …. vemos que funciona correctamente.
¿A que no era tan complicado 😉 ?
Podéis bajaos el WAR (Web
ARchive)… y recordar que es un ZIP renombrado (poco más o menos)
Cuando he tenido la necesidad de realizar estos procesos de comunicación (applet/servlet),
he procurado que sea completamente transparente el mecanismo de transporte: Sockets, cadenas textuales, RMI, serialización, etc… Esto es fácil si tenéis
conocimientos básicos de patrones de diseño.
En concreto, una implementación sencilla del patrón estrategia (polimorfismo
puro) junto con una factoría …. puede solucionar el problema … aunque
esto… es otra historia….
Muy interesante y muy útil , gracias.
Tengo una pregunta:
como podriamos pasar un arraylist de objetos (como objeto persona con atributos de nombre, apellido, edad, etc) a un applet ? siguiendo el ejemplo presentado.
Hola, sería igual.
Prueba primero a mandar/recibir un objeto serializable y luego prueba a mandar un array de esos objetos.
De todos modos, a estas alturas (el tutorial tiene 14 años) probablemente no sea el mejor modelo para hacer aplicaciones reales (bien si es simplemente por aprender o por algún problema concreto en el que requieras un applet por comunicarte con la máquina del cliente). Ya los applets están en deshuso (seguridad) y casi el modelo estandar de comunicación es json y servicios rest