SEO-friendly URLs con Seam II

Vamos a ampliar la información del post anterior con conceptos más avanzados.
Partimos de la base de que tenemos configurado y funcionando el módulo UrlRewrite.

El primer problema con el que me topé es que mi aplicación usaba identificadores numéricos, tipo .../product.seam?idProduct=123. Por lo tanto necesitaba traducir el identificador numerico a una palabra descriptiva del producto, como .../product/silla o .../product/mesa.

Afortunadamente con Seam eso no presenta mucha dificultad y puede emplearse una EL Expression tipo #{rewriter.fromNameToId('silla')}.
Por desgracia, en el archivo urlrewrite.xml no pueden incluirse EL Expressions.

Para solucionarlo, creé una 'página virtual' en el pages.xml que recogía los parámetros como String de la url y mediante una llamada a un componente de Seam los traducía en el correspondiente identificador numérico, aprovechando que en el archivo pages.xml sí que se pueden usar EL Expressions.

  • Fichero urlrewrite.xml
    1. <urlrewrite>
    2.    <rule>
    3.      <from>^/pruduct/([A-Za-z]*)$</from>
    4.      <to last="true">/virtual_product.seam?name=$1</to>
    5.    </rule>
    6.  </urlrewrite>

  • Fichero pages.xml
    1. .....
    2. <page view-id="/virtual_product.xhtml" action="#{product.init}">
    3.     <param name="name"/>
    4.     <navigation>
    5.         <redirect view-id="/product.seam">   
    6.             <param name="idProduct" value="#{urlRewriter.idProductFromName(name)}"/>
    7.         </redirect>
    8.     </navigation>
    9. </page>
    10. .....

  • Componente rewrite
    1. public int idProductFromName(String name) {
    2.     // Consulta en la bbdd para halar
    3.     // el id del producto a partir del nombre
    4. }

Leave a Comment

SEO-friendly URLs con Seam

Hoy en día están muy de moda las aplicaciones web y blogs con URLs amigables, tipo http://seamcity.madeinxpain.com/archives/category/seam.

Estas URLs además de ser más intuitivas y agradables a la vista, también son más agradables para buscadores de internet como google (o podríamos decir más agradables para EL BUSCADOR de internet).Esta es una de las técnicas seo más simples, destinadas a mejorar tu posicionamiento en buscadores.

En Seam podemos obtener estas URLs sencillas a través del filtro URLrewrite. Este filtro básicamente se encarga de traducir URLs, y es muy muy fácil de usar.
Una de las principales ventajas es que es una capa independiente que se coloca por encima de la aplicación. No es necesario modificar ni una línea de código ya existente, simplemente definir cómo se van a traducir las direcciones.

  1. Añadir el archivo urlrewrite.jar que viene incluido en la distribución de Seam en la carpeta WEB-INF/lib del proyecto. La mejor forma de hacerlo es mediante el archivo de ant que crea el seam-gen
  2. Configurar el filtro UrlRewrite en el web.xml tal y como se indica aqui
  3. Crear el fichero urlrewrite.xml que contiene las reglas de traduccion de urls en la carpeta WEB-INF. Aqui pongo el fichero del ejemplo seambay, pero lo mejor es mirar la documentacion oficial
    1. <!DOCTYPE urlrewrite
    2.     PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
    3.     "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
    4.  
    5. <urlrewrite>
    6.  
    7.    <rule>
    8.      <from>^/feedback/([A-Za-z0-9]*)$</from>
    9.      <to last="true">/feedback.seam?member=$1</to>
    10.    </rule>
    11.    
    12.    <rule>
    13.      <from>^/itemdetail/([0-9]*)$</from>
    14.      <to last="true">/auction.seam?id=$1</to>
    15.    </rule>
    16.    
    17.    <rule>
    18.      <from>^/bidhistory/([0-9]*)$</from>
    19.      <to last="true">/bidhistory.seam?id=$1</to>
    20.    </rule>
    21.  
    22. </urlrewrite>

En otro post esplicaré con más detalle las posibilidades del fichero urlrewrite.xml, cómo usar parámetros, cómo traducir de nombres a identificadores numéricos, y cómo conseguir que las urls amigables las pueda generar nuestra aplicación tras el envío de formularios o acciones.

Leave a Comment

Seam y Ajax con Seam Remoting

Realizar peticiones Ajax a tus componentes en Seam es increíblemente fácil gracias al framework Seam Remoting.
Con solo añadir un par de lineas de javascript, tu componente escrito en Java se convierte en un componente javascript, pudiendo acceder a sus campos y ejecutar sus métodos asíncronamente.
En simplemente tres pasos podemos invocar a un componente y manejar la respuesta.

1) Indica los métodos que van a invocarse vía Ajax
Simplemente marca con la anotación @WebRemote los métodos que quieras invocar por Ajax.

  1. @Name("calculadora")
  2. public class Calculadora {
  3.  
  4.    private float pi = 3.14;
  5.    private float n = 10;
  6.  
  7.     @WebRemote
  8.     public int suma(float a, float b) {
  9.         return a+b
  10.     }
  11.  
  12.     @WebRemote
  13.     public int sumaConstante(float a) {
  14.         return this.n + a;
  15.     }
  16.  
  17.     // Este metodo no está marcado con @WebRemote, por lo que no se puede invocar desde javascript
  18.     public void metodoNoAjax() {
  19.     }
  20.  
  21.     public float getPi() { return this.pi;}
  22. }

Si quisieses invocar un EJB en lugar de un POJO, las anotaciones @WebRemote deberán estar en la declaración los métodos de la interface del EJB.

2) Importa los scripts necesarios
Primero debes importar el script que contiene el código que permite las llamadas remotas:

  1. <script type="text/javascript" src="seam/resource/remoting/resource/remote.js"></script>

Ahora por cada componente que contenga métodos que quieras invocar vía Ajax debes importar otro script en el que indicas el nombre del componente (el que has definido en la anotacion @Name).
Este script contiene el stub del componente, que indica los métodos a los que puedes llamar y la definición de sus tipos.
Por ejemplo, si tienes un componente anotado con @Name("calculadora") deberás incluir la siguiente linea

  1. <script type="text/javascript" src="seam/resource/remoting/interface.js?calculadora"></script>

Si quisieses acceder a más de un componente en la misma página puedes especificar varios componentes:

  1. <script type="text/javascript" src="seam/resource/remoting/interface.js?calculadora&componente2&componente3"></script>

También puedes importar el javascript de los componentes usando el tag s:remote.

  1. <s :remote include="calculadora,componente2,componente3"/>

3) Invoca el método y maneja la respuesta
Ahora podemos invocar los métodos de nuestra calculadora marcados con @WebRemote.
Para obtener los objetos javascript que representan nuestros componentes debemos hacerlo a través de Seam.Component.
En la llamada le pasamos los parámetros que tenga el método al que estemos invocando (admite sobrecarga) y un último parámetro que será la función a la que se invocará con el resultado de la invocación

  1. <script type="text/javascript">
  2.   //<![CDATA[
  3.  
  4.   function suma() {
  5.     Seam.Component.getInstance("calculadora").suma(1, 5, muestraResultado);
  6.   }
  7.  
  8.   function muestraResultado(result) {
  9.     alert(result); // --> mostrará un 6
  10.   }
  11.  
  12.    // ]]>
  13. </script>

También puedes acceder a los campos del componente que tengan un getter asignar un valor a los que tengan un setter.

  1. <script type="text/javascript">
  2.   //<![CDATA[
  3.  
  4.   var calc = Seam.Component.getInstance("calculadora");
  5.   function suma() {
  6.     calc.n = 25;
  7.     calc.sumaConstante(5, muestraResultado)
  8.   }
  9.  
  10.   function muestraResultado(result) {
  11.     alert(result);   // --> mostrará 30
  12.     alert(calc.pi); // --> mostrará 3.14
  13.   }
  14.  
  15.    // ]]>
  16. </script>

Seam Remoting también permite evaluar EL Expressions, trabajar con Collections, hacer debug de las llamadas enviadas y recibidas, suscribirse a una cola JMS.
Toda esta información y más se encuentra disponible en la documentación en inglés

Leave a Comment

Seam Generator (seam-gen)

La distribución de Seam incluye una aplicación de linea de comandos para crear y mantener aplicaciones Seam.
Esta herramienta es capaz de generar un proyecto Seam que contenga el esqueleto de una aplicación, incluyendo configuración y librerías. Esta es la forma más rápida de empezar un desarrollo con Seam. Genera una aplicación en blanco con facelets, drools (seguridad), página de login y bienvenida, configuración de la base de datos... así como scripts para su compilación, empaquetación y despliegue.
Las opciones que ofrece esta herramienta son las siguientes:

  • setup: Sirve para configurar el proyecto. Te pregunta entre otras cosas el directorio de instalación de JBoss, si quieres desplegar un archivo war (sin EJBs) o un ear (con EJBs), el nombre del paquete donde irán las clases, y parámetros de la conexión con la base de datos.
  • new-project: Crea un proyecto para eclipse con todas las dependencias y la configuración básica a partir de los datos proporcionados a través del setup.
  • update-project: Actualiza el proyecto con las últimas dependencias.
  • delete-project: borra el proyecto
  • deploy: Despliega el proyecto y el datasource en JBoss
  • undeploy: Replega el proyecto y el datasource.
  • explode: Desplega el proyecto y el datasource en JBoss como una estructura de ficheros, sin empaquetar.
  • restart: Resetea el proyectodesplegado con ”explode”
  • unexplode: Replega el proyecto y el datasource desplegado con ”explode”
  • new-action: Crea un nuevo Stateless Session Bean con su correspondiente interface y sus anotaciones.
  • new-form: Crea un nuevo Stateful Session Bean con su correspondiente interface y sus anotaciones.
  • new-conversation: Crea un nuevo Stateful Session Bean con su correspondiente interface y sus anotaciones. Añade anotaciones y esqueletos de métodos para trabajar con Tasks. También crea una clase de Test que puede usarse para simular el ciclo de petición/respuesta de JSF.
  • new-entity: Crea un nuevo Entity Bean con sus anotaciones.
  • generate-entities: Genera Entity Beans a partir de un modelo existente en la base de datos

Aunque seamgen está pensado para trabajar principalmente con eclipse y JBoss AS, también puede configurarse para crear aplicaciones para netbeans y glassfish, que tiene diferentes archivos de configuración.
Además puedes modificarla facilmente, ya que no deja de ser un simple script que trabaja con ant.

Al usar la opción new-project se crea un nuevo proyecto con una estructura de directorios que a primera vista parece algo compleja. Sin embargo vamos a ver como cada carpeta tiene una función o
definida.

  • bootstrap: Contiene el JBoss Embeddable EJB 3.0 container, para poder desplegar EJBs fuera del servidor de aplicaciones.
  • classes: Contienen los archivos de bytecodes (.class) de los componentes definidos por el desarrollador.
  • dist: Contiene los archivos empaquetados (ear, war, jar) que serán desplegados en el servidor de aplicaciones.
  • exploded-archives: Contiene la estructura de directorios que se puede desplegar directamente en el servidor de aplicaciones.
  • lib: Contiene todas las librerías(.jar) con las dependencias necesarias para la compilación y ejecución de la apliación.
  • nbproject: Contiene los archivos necesarios para trabajar en el proyecto con netbeans.
  • resources: Contiene todos los archivos de configuración.
  • src: Contiene el código fuente de los componentes definidos por el desarrollador, separados en tres bloques: entidades, acciones y test.
  • test-build: Esta carpeta está destinada a almacenar los test de integración.
  • view: Contiene todos los elementos relativos a la vista, como archivos css, imágenes, archivos xhtml...

Leave a Comment

Archivos de configuración de Seam

JBoss Seam intenta minimizar todo lo posible la cantidad de xml necesario para configurar la aplica-
ción.
Sin embargo, parte de la configuración es preferible tenerla en archivos xml, como reglas de navegación o configuración de componentes del framework, para así aislarla del código java y poderla
cambiar sin recompilar. En otros casos, como los descriptores, es obligatorio tener los archivos xml para cumplir las especificaciones.

Vamos a ver los archivos de configuración que podemos encontrarnos en un proyecto Seam, su localización y cometido.

  • *-ds.xml: Contiene los par ́metros de conexión a la base de datos. Este archivo debe desplegarse en el directorio "deploy" de JBoss
  • seam.properties: Este archivo debe estar presente obligatoriamente (aunque esté vacío) en la carpeta raíz del archivo jar que va a desplegarse o en la carpeta classes del archivo war.
    Este archivo se usa para configurar las propiedades de los componentes.
    components.xml: Puede aparecer en tres lugares; el directorio "META-INF" del archivo jar, el directorio "WEB-INF" del archivo war, o cualquier directorio que contenga clases anotadas con @Name. En él se declaran y configuran componentes.
  • components.properties: Especifica el valor de variables que pueden usarse en el archivo components.xml, como @debug@. Estas variables se reemplazan cuando se despliega la aplicación.
  • persistence.xml: Se sitú en el directorio "META-INF"" del archivo jar y en él se declaran las unidades de persistencia.
  • security.drl: En él se declaran las reglas de autorización del subsistema Drools. Se coloca en la raíz del archivo ear o en el directorio "classes" en el caso de desplegar en un archivo war.
  • application.xml: Es el descriptor de despliegue de Enterprise Application Archives y es un archivo estándar en aplicaciones java 2 EE. Se sitúa en el directorio "META-INF" del archivo ear y en él se declaran los módulos de la aplicación y las dependencias.
  • ejb-jar.xml: Es el descriptor de despliegue est ́ndar de la especificació EJB. Se coloca en el directorio META-INF del archivo jar, y en Seam contiene la declaración del SeamInterceptor.
  • jboss-app.xml: Es el descriptor de aplicación específico de JBoss y se sitúa en el directorio "META-INF" del archivo ear.
  • faces-config.xml: Es el archivo de configuración central de JavaServer Faces. Se encuentra en el directorio "WEB-INF" del archivo war.
  • pages.xml: Especifica las reglas de navegación. Se encuentra en el directorio "WEB-INF" del archivo war.
  • web.xml: Es el descriptor Web estádar especificado en J2EE. Se encuentra en el directorio "WEB-INF" del archivo war.
  • import-*.sql: Se coloca en la raíz del archivo jar. Puede contener código sql que será ejecutado cada vez que se despliegue la aplicación

Una aplicación Seam típica tendrá la siguiente estructura de archivos

my-application.ear/
    jboss-seam.jar
    jboss-el.jar
    jboss-el-api.jar
    META-INF/
        MANIFEST.MF
        application.xml
    my-application.war/
        META-INF/
            MANIFEST.MF
        WEB-INF/
            web.xml
            components.xml
            faces-config.xml
            lib/
                jsf-facelets.jar
                jboss-seam-ui.jar
        login.jsp
        register.jsp
        ...
    my-application.jar/
        META-INF/
            MANIFEST.MF
            persistence.xml
        seam.properties
        mi/
            paquete/
                myapplication/
                    Clase1.class
                    Clase2.class
                    Clase3.class

Leave a Comment

Bijection

Para entender el funcionamiento básico de JBoss Seam debes familiarizarte con dos conceptos: Contexto y Componente.

Un componente es un objeto con estado (normalmente stateful session beans). Una instancia de un componente vive en un contexto y se le asigna un nombre en dicho contexto.
Para asociar la instancia de un componente al nombre de dicho componente en un contexto Seam proporciona el mecanismo de Bijection

          Bijection = Injection + Outjection

El mecanismo de injection permite a un componente A obtener de un contexto una referencia a una
instancia de un componente B, haciendo que el contenedor de aplicaciones ”inyecte” el componente B en una variable del componente A.
El mecanismo de outjection permite que un componente B esté disponible en un contexto para poder ser inyectado en un componente A.
Es decir, mediante outjection se toma una instancia de un componente y se deposita en un contexto
y mediante injection se toma una instancia de un componente de un contexto y se asocia a una
variable de otro componente.

A diferencia del mecanismo de Injection, el mecanismo de Bijection es:

  • contextual: Es usada para asociar componentes con estado desde diferentes contextos.
  • bidireccional: Los componentes pueden ser depositados en el contexto o tomados de él.
  • dinámico: Como los valores de las variables de los contextos cambian con el tiempo y los
    componentes tienen un estado definido, la bijection sucede cada vez que el componente es
    invocado.

Comments (1)

Qué es JBoss Seam ?

JBoss Seam es un framework que integra y unifica los distintos standars de la plataforma Java EE 5.0, pudiendo trabajar con todos ellos siguiendo el mismo modelo de programación.
Ha sido diseñado intentado simplificar al máimo el desarrollo de aplicaciones, basando el diseño en Plain Old Java Objects (POJOs) con anotaciones. Estos componentes se usan desde la capa de persistencia hasta la de presentación, poniendo todas las capas en comunicación directa.

El núcleo principal de Seam está formado por las especificaciones Enterprise JavaBeans 3 (EJB3) y JavaServer Faces (JSF).
A grandes rasgos podemos definir EJB3 como una arquitectura para un sistema transaccional (como bases de datos) de objetos distribuidos basado en componentes que permite construir aplicaciones portables, reusables y escalables.
JSF es un framework de la capa de presentación que define componentes para el interfaz gráfico y "managed beans" para la lógica de la aplicación que interactúan a travé de un sistema de eventos.

Sin embargo, estos frameworks tienen algunas limitaciones y no han sido concebidos para trabajar juntos (esto pretende resolverse con la futura especificación web beans ); tienen distinto tipo de configuraciones (JSF usa archivos XML mientras que EJB3 usa anotaciones), distinto ciclo de vida y no pueden comunicarse directamente a nivel de framework.
Para hacerlos cooperar necesitaríamos escribir "clases fachada" y multitud de código de relleno que se encargase de pasar las llamadas de una capa de la aplicación a otra. Ahí es donde entra en juego Seam.
Seam elimina la barrera existente entre estas tecnologías, permitiendo usar EJBs directamente como "backing beans" de JSF y lanzar o escuchar eventos web.

Leave a Comment