jueves, 26 de febrero de 2009

El próximo estándar web

(Fuente: http://www.pc-actual.com/actualidad/noticia/2009/02/26/El-proximo-estandar-Web)

Desde su nacimiento, la Web ha ido evolucionando, pasando de ser una red de documentos simples entrelazados a principios de los ochenta a una granestructura para ejecutar aplicaciones y servicios

En ocasiones, los fabricantes del software que permite acceder a la Web, los conocidos navegadores, han incluido en sus productos extensiones de manera unilateral, como las etiquetas propietarias en el lenguaje HTML, dando lugar a incompatibilidades entre navegadores.

Éste fue el origen de todos los problemas para los diseñadores web, que tenían que comprobar el navegador empleado por el usuario para adaptar el código o bien decantarse por uno de ellos e indicar en las páginas qué programa debía ser utilizado para verlas correctamente.

Aunque se trata de una excepción a la regla, en casos contados, esas extensiones unilaterales han terminado siendo aceptadas, explícita o implícitamente, por el resto de la industria y han alcanzado el nivel de cuasi estándar. El caso más claro es el objeto XMLHttpRequest, introducido por Microsoft en Internet Explorer y con el que actualmente cuentan todos los navegadores, siendo el pilar de las técnicas AJAX.

A fin de ofrecer una mayor funcionalidad y mejor experiencia de usuario, acercando el funcionamiento de las aplicaciones web al de los programas clásicos con interfaz nativa, surgieron las denominadas RIA (Rich Internet Applications) y, con ellas, los motores necesarios para ejecutarlas en los navegadores: Adobe Flash Player, Microsoft Silverlight, Adobe AIR, etc.

El inconveniente de todas estas soluciones, de cara a las empresas que desarrollan aplicaciones web, es la dependencia que crean respecto de un fabricante, aparte de la obligación que transfieren a los clientes de instalar un cierto complemento en sus navegadores, un runtime que puede no estar disponible para todas las combinaciones de sistemas operativos/navegador.

Nuevos elementos de la versión 5 de HTML

La actual versión de HTML cuenta como únicos elementos estructurales con las secciones div y los párrafos de texto, los diferentes niveles de encabezado tienen más una finalidad visual que de definición de estructura, un repertorio claramente insuficiente para la composición de documentos cada vez más extensos. En HTML 5 resultará mucho más fácil estructurar dichos documentos gracias a cinco nuevos elementos: header, section, article, nav y footer.

Cualquier sección del documento se delimitará entre las marcas <section> y </section>, pudiendo existir secciones anidadas. En el interior de cada sección, pueden separarse artículos independientes, por ejemplo, entradas de un blog, a través de las marcas <article> y </article>, así como introducir enlaces de navegación a otros documentos recurriendo a las marcas <nav> y </nav>.

Por su lado, mediante las marcas <header> y </header> se delimitarán los encabezados, por ejemplo precediendo a una sección, mientras que <footer></footer>, como es fácil imaginar, establecerían el pie de sección.

El modelo de distribución de contenidos se completa con el nuevo elemento address, cuya finalidad es acoger la información de contacto relativa al contenido de una página o una sección. Habitualmente, se introducirá como elemento anidado dentro del bloque footer asociado a un bloque section.

El texto y las imágenes habituales en cualquier página se complementan, cada vez con mayor frecuencia, con contenidos multimedia, principalmente en forma de audio y vídeo. Existen multitud de complementos o plug-ins para conseguir que un navegador reproduzca prácticamente cualquier formato, cada uno de ellos con sus especificidades, limitaciones e incompatibilidades. HTML 5 agrega los nuevos elementos audio y vídeo estableciendo claramente cuáles son los formatos que, como mínimo, debe ser capaz de procesar el navegador.

Camino hacia la Web semántica e interactiva

La cantidad de información disponible en la Web crece de manera exponencial, hasta tal punto que prácticamente es imposible obtener siquiera una aproximación del número de documentos a los que se puede acceder desde un navegador. El mayor problema que plantea esta abundancia estriba en la dificultad de encontrar aquello que interesa, de ahí el éxito de los servicios de búsqueda que mejor funcionan.

A pesar de que la separación clara entre contenido y estilo, que se consigue gracias a HTML y CSS, facilita hasta cierto punto el proceso de búsqueda, aún es posible mejorar mucho en este sentido, siendo éste el objetivo de la denominada Web semántica. HTML 5 incorporará una serie de elementos nuevos con los que quiere contribuir a dar forma a ese nuevo concepto, elementos que permiten marcar el tipo de contenido, como meter, progress, time, dialog, figure y aside.

También es importante, desde una perspectiva funcional, incrementar la interactividad de las interfaces web, campo en el que HTML 5 agrega técnicas hoy totalmente comunes en las interfaces GUI nativas, como son las de arrastrar y soltar o deshacer/rehacer contenidos modificados.

Uno de los elementos de mayor interés en este sentido es datagrid, un control pensado para facilitar la visualización y edición de datos con estructura de lista, tabular o de árbol y que cuenta con los métodos y eventos necesarios para insertar nuevas filas y columnas, detectar cambios en los datos, etc. En las celdillas de esta rejilla de datos es posible introducir no solamente datos simples, sino también otros elementos HTML, como, por ejemplo, el elemento menu, pensado para ofrecer listas de comandos.

En la misma dirección de mejorar la interactividad, aportan su granito de arena elementos como command, details y bb. El primero representa cualquier comando ejecutable por parte del usuario, pudiendo tomar la forma de botón de radio, caja de selección, etc. Con el segundo es posible incluir en los documentos información adicional, no mostrada por defecto, que el usuario puede hacer visible cuando le interese.

El elemento bb, mucho menos detallado en el actual borrador de especificación, serviría para invocar a funciones específicas soportadas por un cierto navegador, como podría ser la conversión de una aplicación web corriente en una aplicación accesible sin conexión.

Comunicación y almacenamiento

Los navegadores que implementen HTML 5 harán lo mismo con el nuevo DOM2, una remodelación del modelo de objetos accesible desde los guiones, normalmente escritos en JavaScript, ejecutados en el navegador. Es en este campo donde seguramente se encuentran las novedades más importantes de cara a los desarrolladores de aplicaciones.

La comunicación entre el cliente, la interfaz web compuesta de HTML 5, CSS y JavaScript, y el lado servidor se verá facilitada gracias a la nueva interfaz WebSocket, de tipo más genérico que XMLHttpRequest.

También se abren las puertas a la comunicación entre documentos (interfaces) ejecutándose en el mismo navegador, a través del envío y recepción de mensajes. Asimismo, se habilita un nuevo mecanismo para que el cliente reciba asíncronamente eventos generados por el servidor, sin una actualización completa de la página, a través de la interfaz RemoveEventTarget.

En la actualidad, las aplicaciones web utilizan datos recuperados de un servidor y los devuelven al servidor para su almacenamiento, lo cual impide su funcionamiento en caso de no tener disponible una conexión. Hay herramientas desplegadas, como es el caso de Adobe AIR o Google Gears, que ofrecen mecanismos para el almacenamiento y recuperación de datos en el cliente a esas aplicaciones. Con HTML 5, dichas herramientas ya no serán necesarias, gracias a las cachés de aplicación.

La nueva interfaz ApplicationCache permite detectar a una aplicación la existencia de esa caché, comprobar los elementos que contiene, recuperarlos y actualizarlos. La caché de cada aplicación se asociará de manera única con una URL.

Además de la caché de aplicación y el usual sistema de almacenamiento y recuperación de cookies en el cliente, DOM2 también aportará una nueva interfaz, llamada Storage, implementada por dos objetos distintos: sessionStorage y localStorage.

La información almacenada en un sessionStorage está accesible para cualquier página procedente de la misma aplicación, mientras que localStorage representará un depósito privado para una página. En ambos casos, se cuenta con las operaciones apropiadas para agregar, comprobar, recuperar y eliminar pares clave-valor.

Finalmente, en cuanto a las funciones relacionadas con el tratamiento de datos en el cliente, hay que mencionar la posibilidad de utilizar bases de datos a través del método openDatabase() y la interfaz Database, aunque con ciertas limitaciones.

Resumiendo

Los objetivos propuestos tanto por el W3C como por el WHATWG en el actual borrador del futuro HTML 5, cuyos puntos fundamentales se han recogido en este artículo, deben interpretarse como buenas noticias para desarrolladores y diseñadores. A todos ellos nos hará la vida más fácil, al no tener que recurrir a complementos externos para conseguir la funcionalidad que necesitamos en nuestras aplicaciones.

Por el momento, no obstante, una buena parte de esos propósitos son solamente buenas intenciones. Pasarán varios años hasta que HTML 5 se convierta en una recomendación oficial, primero, y sea completamente implementada por los principales navegadores mucho tiempo después. El futuro, sin embargo, tiene un matiz indudable: el navegador se convertirá en la plataforma principal para la ejecución de aplicaciones.

Evolución del HTML 5

HTML 4 surgió en 1997, con ligeras modificaciones en 1999, por lo que la evolución del lenguaje de descripción de contenidos en la Web lleva invariable desde hace una década. El actual trabajo en HTML 5 está promovido por el WHATWG (Web Hypertext Application Technology Working Group), un grupo del que forman parte empresas como Mozilla Foundation (Firefox), Apple (Safari) y Opera.

A pesar de que Microsoft no contribuyó a la fundación de esta entidad, el futuro Internet Explorer 8 implementará ciertas partes de HTML 5. El último borrador data del 24 de octubre pasado (www.w3.org/html/wg/html5), recogiendo una versión preliminar de la especificación en la que se lleva trabajando desde el año 2003 y que, posiblemente, no vea la luz, en su versión definitiva, hasta dentro de bastante tiempo.

Se estima que la especificación alcance el grado de Candidate Recomendation en torno a 2012. Esto no es óbice, sin embargo, para que los fabricantes de navegadores vayan incorporando en sus productos algunos de los avances propuestos. De hecho, en algunos de ellos ya es posible encontrar innovaciones concretas, como el objeto canvas.

HTML 5 es una evolución de HTML 4 y, al igual que éste, cuando se expresa en sintaxis XML se denomina XHTML. De hecho, el objetivo del W3C es que HTML 5 sustituya ciertos aspectos de XHTML 1.0, incorporando al tiempo especificaciones ya finalizadas y estables, como la de Web Forms 2.0. La evolución de XHTML 2.0, por el contrario, seguirá un camino independiente.

La nueva versión de HTML vendrá también acompañada de una actualización de DOM (Document Object Model), a la que se denominará DOM2. Con HTML 5 y DOM2, se persigue que los diseñadores/desarrolladores puedan crear aplicaciones tipo RIA con independencia de fabricantes, apoyándose en servicios ofrecidos por el navegador sin precisar extensión alguna.

miércoles, 25 de febrero de 2009

Guardar imágenes en base de datos usando JPA

Hay infinidad de ejemplos de cómo guardar una imagen a base de datos con JDBC, y cómo recuperarla.

Pues esta vez mostraré un ejemplo usando JPA.

Supongamos que nuestra clase entidad tiene una propiedad llamada imagen que es donde se guardará la imagen. Esta propiedad debe declararse así:

@Lob
@Column(name = "imagen")
private byte[] imagen;


Para guardar una imagen (supongamos una que esté en el disco), debemos realizar lo siguiente:
Entidad i = new Entidad(); // nuestra entidad
File f = new File("D:/Imagen006.jpg"); //asociamos el archivo fisico
InputStream is = new FileInputStream(f); //lo abrimos. Lo importante es que sea un InputStream
byte[] buffer = new byte[(int) f.length()]; //creamos el buffer
int readers = is.read(buffer); //leemos el archivo al buffer
i.setImagen(buffer); //lo guardamos en la entidad
em.persist(i); //y lo colocamos en el EntityManager


Ahora, para recuperar el contenido haremos que se muestre el contenido en un JFrame:

Entidad ent = em.find(Entidad.class, new Integer(1)); //ubicamos una entidad
Image image=new ToolkitImage(new ByteArrayImageSource(ent.getImagen())); //lo convertimos a Image
JLabel label=new JLabel(new ImageIcon(image)); //creamos un JLabel con la imagen como icono
JFrame frame=new JFrame("imagen"); //creamos el jframe
frame.setLayout(new BorderLayout()); //.. con un Layout clasico
frame.add(label,BorderLayout.CENTER); //.. agregamos el JLabel en el centro
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); //y lo mostramos


Después haré un ejemplo usando JTable, y - si puedo - usando ICEfaces.

viernes, 20 de febrero de 2009

Ya no habrá versión 7 de NetBeans

Ya no habrá NetBeans 7.0 Habrá NetBeans 6.7 para junio de 2009.

El equipo de desarrollo de NetBeans - según indican en su noticia (http://www.netbeans.org/servlets/NewsItemView?newsItemID=1346) - que se centrarán en cambios más pequeños, y no harán sus clásicos nuevas versiones que son dos veces cada año. (Al menos nos dará un respiro para los que traducimos el NetBeans al español)

Indican también que los cambios de versiones en decimales (6.1, 6.5, 6.7..) son cambios pequeños en la aplicación y que mantienen la compatibilidad del API. Muy bueno para los desarrolladores de plugins.

Mientras que las versiones de números enteros (5, 6, 7) son cambios considerables en el API de NetBeans, y en su plataforma.

La versión oficial de 6.7 será lanzada en junio de este año, y entre las características importantes son las integraciones de Maven y de Kenai.

La próxima semana será lanzada la versión 6.7 ML 2.

Sería intersante bajarlo cuando esté disponible e irlo probando, a fin de ayudar en su mejora.

Aquí algo de sus características: http://wiki.netbeans.org/NewAndNoteworthyMilestone2NB67

Pues bien, espero que sea una buena versión.

martes, 17 de febrero de 2009

Resolviendo examenes

Este post no tiene nada que ver con NetBeans ni Java, ni tecnología parecida.
Me llegó un mail bastante divertido y me gustaría compartirlo.

El problema de los exámenes son los profesores que no entienden las habilidades de uno:

no entiendo por qué me puso cero, si la hallé!
pero si la estuve expandiendo!
 
 

Aquí tuve un accidente.. y me desesperé


"Profe, le juro que el elefante ya estaba ahí cuando me dió el examen!"

Esta estaba regalada la respuesta.

viernes, 13 de febrero de 2009

Aprendiendo sobre Alcances de variables de Sesión en JSF

(Versión Wiki: http://wiki.netbeans.org/AprendiendoSobreAlcancesJSF)

Introducción

Sabemos que es un dolor de cabeza usar las variables de sesión a través de los objetos HttpSession y HttpRequest. No sabemos si una variable está en nivel de sesión o en nivel de request, simplemente lo ponemos y lo usamos, aunque después nos pueden dar problemas a lo largo de la aplicación Pero al usar JSF esto se hará mucho más sencillo. JSF nos permite utilizar tres tipos de alcances:
  • Aplicación: Una variable guardada en este alcance es visible durante toda la aplicación, hasta que se repliegue la aplicación o hasta que se detenga el servidor.
  • Sesión: Una variable guardada a nivel de sesión, puede ser visible durante el tiempo de vida del usuario en la aplicación, hasta que se invalide la sesión.
  • Request: Una variable en nivel request dura solo hasta la siguiente página, Una página 1, guarda la variable en nivel request y redirecciona la petición a la página 2. La página 2 la utiliza, y el objeto desaparece.
Por tanto, haremos una aplicación que permita hacer votos y mostrar el resultado. Las alternativas y cuenta de votos se guardarán a nivel de la aplicación; el usuario que haya hecho el voto no podrá volver a votar, por tanto la aplicación sabrá que se trata del mismo usuario porque mantiene la sesión; y cuando el usuario quiera ver los resultados, estos se mostrarán en de acuerdo al requerimiento.

Software necesario:

  • Java 6
  • Glassfish V2
  • NetBeans 6.5 con el componente Visual ICE Faces que se puede descargar desde el Centro de Actualización (Herramientas > Complementos)


Creando una aplicación JSF con Visual ICEFaces

Diseñando la aplicación visual

  1. Crearemos una aplicación Web al que llamaremos Scopes
  2. En la Paso "4. Frameworks" activamos el framework Visual Web ICEfaces
  3. Al terminar de crear el proyecto, se mostrará un texto de advertencia. Lo borramos ya que advierte que en este proyecto no funcionarán las paletas Woodstock
  4. Ahora, desde el panel ICEfaces arrastramos y colocamos los siguientes componentes al diseño de Page1.jsp
    • OutputText: Y en el atributo value escribimos '¿Cuál es tu lenguaje de programación favorito?'
    • SelectOneRadio: cuyo atributo id será opcionesRadio
    • Y dos CommandButton: uno con id=votarButton, value='Votar' y el otro id=resultadosButton, value='Ver resultados', action='ver_resultados'
      En general, podemos escribir el código y por cada declaración de clase que vayamos usar, escribimos unos cuantos caracteres del nombre y presionamos Ctrl+Espacio para que el IDE nos sugiera las clase, y al seleccionarla nos hará el import de esas clases de manera automática. O al finalizar de escribir todo el código, presionamos Mayus+Ctrl+I para importar las clases necesarias y borrar las innecesarias.
  5. En el explorador del proyecto, abrimos el nodo de fuentes de clase y abrimos la clase ApplicationBean1.java. Esta clase contendrá todas las variables que se usarán en toda la aplicación. Para nuestro caso, aquí colocaremos las opciones de la encuesta, y el contador por cada opción marcada. Así que, después de la declaración de la clase, justamente después de { escribimos
    private com.sun.webui.jsf.model.Option[] opciones;
    private java.util.HashMap votos;
    Además, crearemos sus métodos set y get. Podemos hacer esto desde la opción Reestructurar > Encapsular campos...
  6. También necesitamos hacer una pequeña lógica de negocio para incrementar los votos a alguna opción seleccionada. Así que crearemos el siguiente método:

    public void votoPara(String votoHecho) {
    Integer cuenta = votos.get(votoHecho);
    if (cuenta == null) {
    cuenta = 0;
    }
    cuenta++;
    votos.put(votoHecho, cuenta);
    }
  7. Ahora, vamos al método init() de la misma clase, y en la última línea del cuerpo del método escribiremos la inicialización de los valores de las propiedades que acabamos de crear:

    opciones = new Option[]{
    new Option("java", "Java Programming Language"),
    new Option("cpp", "C++"),
    new Option("fortran", "Fortran")};
    votos = new HashMap();
    for (Option o : opciones) {
    votos.put(o.getValue().toString(), 0);
    }
  8. Ya tenemos las variables que son visibles desde toda la aplicación. Ahora haremos la variable que durará la sesión del usuario. Así que abrimos la clase SessionBean1.java y agregamos la propiedad boolean haVotado con sus respectivos set/get

    private boolean haVotado;

    public boolean isHaVotado() {
    return haVotado;
    }

    public void setHaVotado(boolean haVotado) {
    this.haVotado = haVotado;
    }
  9. Y la última variable de nivel de requerimiento (request) será la hora en que se accede al resultado de los votos. Así que abriremos la clase RequestBean1.java y agregamos la propiedad java.util.Date hora con su respecto set/get

    private java.util.Date hora;

    public Date getHora() {
    return hora;
    }

    public void setHora(Date hora) {
    this.hora = hora;
    }

Manejando los valores de los controles

  1. Necesitamos colocar los valores de nuestro arreglo de la clase ApplicationBean1 en el formulario. Vayamos al modo diseño visual de Page1.jsp, hagamos clic derecho sobre el objeto opcionesRadio y seleccionamos Bind to data...
  2. Seleccionamos el objeto opciones que se encuentra bajo el objeto ApplicationBean1
    Clic en Aceptar
  3. Al hacer esto, el objeto del diseño se habrá 'desaparecido. No sucede tal cosa, sino que se adecuo al contenido. Como las opciones solo se verán en tiempo de ejecución, no se pueden visualizar en el modo de edición.
  4. Ahora, debemos establecer que cuando el usuari haya hecho clic en el botón "Votar", ya no puede volver a votar. Para ello necesitamos desactivar el botón. Así que el estado de este control depende del valor de la propiedad haVotado que está en la clase SessionBean1. Haremos clic derecho sobre el botón, y seleccionamos Properties binding... y seleccionamos en el panel izquierdo la propiedad disabled y en el panel derecho seleccionamos de SessionBean1.haVotado
    Clic en Close.
  5. Hacemos clic en el botón superior Java para ver el código de la clase Page1.java, y agregamos los siguientes métodos. Estos nos permitirán acceder a los objetos ApplicationBean1, SessionBean1 y RequestBean1

    protected ApplicationBean1 getApplicationBean1() {
    return (ApplicationBean1) getBean("ApplicationBean1");
    }

    protected RequestBean1 getRequestBean1() {
    return (RequestBean1) getBean("RequestBean1");
    }

    protected SessionBean1 getSessionBean1() {
    return (SessionBean1) getBean("SessionBean1");
    }
  6. Hacemos clic en el botón superior Design para ver el modo diseño de Page1.jsp y hacemos doble-clic sobre el botón Votar. Esto creará el método votarButton_action() en la clase Page1.java. Aquí obtendremos el valor seleccionado y lo incrementaremos en el contador de votos:

    public String votarButton_action() {
    if (selectOneRadio1Bean.getSelectedObject() != null) {
    String votoHecho = (String) selectOneRadio1Bean.getSelectedObject();
    getApplicationBean1().votoPara(votoHecho);
    getSessionBean1().setHaVotado(true);
    Date hora = new Date();
    getRequestBean1().setHora(hora);
    }
    return null;
    }
  7. Regresamos al modo diseño de Page1.jsp y hacemos doble clic en el botón resultadosButton y hacemos que devuelva la cadena "mostrar_resultados"


    public String resultadosButton_action() {
    return "mostrar_resultados";
    }

Página de respuesta

  1. Creamos una nueva página de la categoría JavaServer Faces y el tipo ICEfaces Visual Web JSF Page
    al cual lo llamaremos Page2.jsp
  2. Agregaremos los siguientes controles:
    • Un outputText con value="Resultados de los votos"
    • Un commandButton con value="Inicio" y id="inicioButton"
    • Otro commandButton con value="Recargar" y id="cargarButton"
    • Un outputText con id="resultadoText", escape=(desmarcado) y value=""
    • Otro outputText con id="fechaText" y value=""
  3. Tanto para resultadoText como para fechaText hacemos clic derecho sobre el control y seleccionamos "Add Binding Attribute"
  4. Hagamos doble en el botón "Inicio". Se abrirá el editor del código de Page2.java, y se creará el método inicioButton_action(), modificamos el código para que tenga el siguiente contenido:

    public String inicioButton_action() {
    return "inicio";
    }
    Posteriormente programaremos la navegación de las páginas.
  5. Estando en el archivo Page2.java, buscamos el método prederender() y lo editamos con el siguiente código
        public void prerender() {
    //Mostrar los últimos propositos
    ApplicationBean1 appBean = getApplicationBean1();//El Bean de toda la aplicacion
    Option[] opciones = appBean.getOpciones();//las opciones de la aplicacion
    Map cuentasVotos = appBean.getVotos(); //y obtenemos las cuentas de los votos hechos
    StringBuilder sb = new StringBuilder(); //para contatenar las cadenas que vamos a crear.
    sb.append("");//vamos a crear un table para resultados
    for (Option opcion : opciones) { //recorremos todas las opciones de la encuesta
    String idVoto = (String) opcion.getValue(); //obtenemos el id de la opción
    String etiqueta = opcion.getLabel();//obtenemos el valor que se muestra como opciones
    int cuenta = cuentasVotos.get(idVoto); //obtenemos cuantos votos se hizo para la opción actual
    sb.append(""); //nueva fila en el table
    sb.append(""); //agregamos la etiqueta de la opcion de voto
    sb.append("");//agregamos los votos hechos a la opcion de voto actual
    sb.append(""); //fin de la fila en el table
    }
    sb.append("
    " + etiqueta + "" + cuenta + "
    "); //fin del table
    resultadoText.setValue(sb); //mostramos el resultado. Se mostrará como String

    //Ahora, obtendremos la hora y fecha en que se hizo el voto
    RequestBean1 reqBean=getRequestBean1(); //obtenemos el bean del requerimiento
    Date hora=reqBean.getHora();
    if (hora!=null){
    fechaText.setValue("Su voto fue realizado el "
    +(String)DateFormat.getTimeInstance(DateFormat.FULL).format(hora)); //imprimos la fecha en un formato completo
    }
    }


Navegación entre las páginas

  1. Abrimos el archivo faces-config.xml. La manera más rápida de ubicar el archivo es presionando Mayus+Alt+O y escribimos el nombre del archivo.
  2. Hacemos clic en el botón superior que dice "PageFlow" para entrar al modo visual de la navegación de las páginas de JSF. Más o menos se visualizará así:
    Vemos que en cada ícono de página hay un cuadrado de color celeste en la parte derecha. Así que hacemos clic en ese cuadrado del ícono del archivo Page1.jsp, lo arrastramos y lo soltamos en Page2.jsp.
  3. Al soltar la flecha, se habrá creado un vértice dirigido con el nombre "case1" Hacemos doble clic sobre este texto y lo cambiamos con el nombre "mostrar_resultados"
  4. Haremos otro enlace desde la Page2.jsp a Page1.jsp y se llamará "inicio"
Estos textos son los que escribimos como return en los métodos resultadosButton_action() de Page1.jsp y inicioButton_action() de Page2.jsp respectivamente. Hagamos clic en el botón superior "XML" de faces-config.xml. Cuando arrastramos los flechas, el código que generó fue el siguiente:
    <navigation-rule>
<from-view-id>/Page1.jsp</from-view-id>
<navigation-case>
<from-outcome>mostrar_resultados</from-outcome>
<to-view-id>/Page2.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/Page2.jsp</from-view-id>
<navigation-case>
<from-outcome>inicio</from-outcome>
<to-view-id>/Page1.jsp</to-view-id>
</navigation-case>
</navigation-rule>

Ejecutando la aplicación

Ejecutamos el proyecto con la tecla F6.
Hagamos nuestro primer voto: Seleccionamos nuestro voto y hacemos clic en el botón "Votar". Notemos que en ese mismo momento el botón quedó desactivado.
Este botón quedará desactivado mientras duré la sesión o hasta que cerremos nuestro navegador. Hagamos clic en el botón "Ver resultados".
Podemos regresar al inicio haciendo clic en el boton "Inicio" y aún así no se podrá volver a votar. Recordemos que ese botón lo asociamos al objeto "haVotado" que se encuentra en el SessionBean
Ahora probemos entrando desde otro navegador. Entremos nuevamente a la misma dirección http://localhost:8080/Scopes/Page1.iface
Sin hacer ningún voto, hagamos clic en "Ver resultados"
Vemos que se ve el voto que hicimos desde el otro navegador. Pero no se visualiza cuando fue. Claro, eso se calculó al momento del voto desde el otro navegador. En este nuevo navegador hagamos clic en "inicio" y realicemos nuestro voto.
Regresemos a nuestro primer navegador, y hagamos clic en el botón "Recargar"

Conclusiones

Hemos podido ver cómo funcionan los diferentes alcances (scope) en una aplicación JSF. No fue necesario de algún request.setAttribute() o session.setAttribute Solo basta con colocar propiedades en los Bean de acuerdo a nuestro requerimiento. Si queremos que una variable dure en toda la aplicación para todos los usuarios, usamos ApplicationBean1; si queremos que una variable dure durante la sesión del usuario, usamos SessionBean1, y si solo queremos que dure solo en una página, usamos RequestBean1.

Recursos

El proyecto utilizado en este tutorial se puede descargar desde aquí http://diesil-java.googlecode.com/files/scopes.tar.gz

lunes, 9 de febrero de 2009

Convirtiendo Date a String / String a Date

Podemos convertir un objeto fecha a String de varias maneras. Cada manera es un tipo de formato establecido por el JVM instalado en nuestro computador. Consideremos este ejemplo:
        Date d1 = new Date();
DateFormat[] dfa = new DateFormat[6];
dfa[0] = DateFormat.getInstance();
dfa[1] = DateFormat.getDateInstance();
dfa[2] = DateFormat.getDateInstance(DateFormat.SHORT);
dfa[3] = DateFormat.getDateInstance(DateFormat.MEDIUM);
dfa[4] = DateFormat.getDateInstance(DateFormat.LONG);
dfa[5] = DateFormat.getDateInstance(DateFormat.FULL);

for (DateFormat df : dfa) {
System.out.println(df.format(d1));
}



En mi caso, el resultado es:
09/02/09 10:29 AM
09/02/2009
09/02/09
09/02/2009
9 de febrero de 2009
lunes 9 de febrero de 2009

Notemos el resultado del formato obtenido por DateFormat.getInstance(). Es toda la fecha en formato corto, además de la hora. Mientras que si obtenemos el formato con DateFormat.getDateInstance() la fecha se muestra en formato medio (Podemos consultar la configuración del sistema operativo referido al formato de fechas). También podemos ver los demás formatos: SHORT, MEDIUM, LARGE y FULL.

De la misma manera podemos convertir de String a objeto java.util.Date. Aquí muestro las diferentes maneras, de diferentes cadenas:

DateFormat df = DateFormat.getDateInstance();
Date d = df.parse("09/02/2009");

DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
Date d = df.parse("09/02/09");

DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
Date d = df.parse("09/02/09");

DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
Date d = df.parse("9 de febrero de 2009");

DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
Date d = df.parse("lunes 9 de febrero de 2009");

getParameter en JSF

En JSF todos los valores de los formularios se pasan por ManagedBeans (con más detalle lo veremos en el curso que está a punto de salir)
Pero ¿qué pasa si queremos procesar una petición con parámetros? En Java web y Struts podemos acceder a los parámetros a través del objeto implícito "request", pero JSF no hay ese objeto implícito ¿qué se hace?

Bueno, para acceder al objeto request debemos hacer lo siguiente:
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();


A partir de allí, podemos usar el objeto request. Ahora, los nombres de los controles tendrán un ligero cambio. Estará compuesto por el "id" del formulario y del "id" del mismo control. Por ejemplo, consideremos este .jsp
<h:form id="form0">
<h:outputLabel value="Escriba número:"/>
<h:inputText id="numeroText" value="#{form.numero}" /><br/>
...

Entonces, para acceder al input-text, escribimos:
String num=request.getParameter("form0:numeroText");

viernes, 6 de febrero de 2009

Diferencias entre JSF puro, Woodstock y ICEfaces en NetBeans

Soy sincero
para mi el mejor framework para web que conocí y trabajé era Struts 1, y no me quería pasar a JSF porque lo veía igual que Struts.

NetBeans sacó su Visual Web que es un editor visual pero con JSF. Los componentes adicionales son del framework Woodstock. Aún así, no me atraía, porque no tenía el mismo control que lo tenia en Struts.

Pero con la moda y ventajas de AJAX, mi pobre Struts me estaba dando algunos problemas, por lo que tuve que poner DWR, Dojo, y demás bibliotecas que hacían más pesada mi aplicación.

Hace poco NetBeans anunció el cambio de Woodstock a ICEfaces. Así que, me aventuré a usarlo.

La verdad lo veo mucho más sencillo, más ligero, y más completo.

Con JSF, las aplicaciones son tan clásicas como los request/response en servlets y jsp, solo que le da un toque especial. El desarrollo de la aplicación web parece ser de una de escritorio, ya que se pueden  acceder a los controles como si fueran variables. Una diferencia bastante notable comparada a Struts. En Struts todo está basado en request, session, variables de sesión y demás dolores de cabeza.

Woodstock es lo mismo que JSF puro, pero el diseño es más visual. Pero es lo mismo que el JSF.

ICEfaces cambia el panorama: Se programa como JSF, con ese toque de manejo de variables sobre controles como en una aplicación JSF, pero la visualización, la presentación de los resultados es con AJAX. Me he quedado realmente sorprendido.

Para ver mejor esto, he creado tres proyectos que hace el cálculo de fibonnaci:
En JSF puro, diseño la aplicación todo a mano. Al ejecutarse, me da el resultado, y si presiono F5 para volver hacer "submit", el navegador siempre me pregunta que si quiero volver a enviar los datos.

Con Woodstock, el diseño es más fácil, más visual (justamente), pero cuando presiono F5, el navegador me pregunta que si deseo volver a enviar los datos. Esto realmente puede ser una confusión para un usuario final, ¿no?

Pero con ICEfaces, el diseño es visual y rápido como en Woodstock, pero al ejecutarlo y presionar F5 para volver a calcular el resultado, no me pide que si deseo volver a enviar los datos ¿por qué? porque es AJAX.

Ahora ¿qué framework usarías para tu proyecto?