Refrescar la página

Febrero 1st, 2009
Hay veces que se nos puede dar el caso, que tenemos que realizar una página donde se van a registrar ciertos tipos de datos, en formularios diferentes, y queremos que una vez el usuario a rellenado todos los campos y los ha validado e insertado en la base de datos, mediante la pulsación de un botón, se de la posibilidad de limpiar y refrescar todos los campos de todos los formularios, para que pueda seguir registrando más datos sin necesidad de salir de la página y volver a entrar en ella.

Existe un objeto en ADF de tipo botón llamado Reset pero para este caso no nos serviría pues tendríamos que asociar uno por cada formulario que tengamos. La solución a nuestro problema sería crear un metodo que refresque el objeto ViewRoot. Se haría del siguiente modo:

    public void recargarPagina(FacesContext contexto) {
        String currentView = contexto.getViewRoot().getViewId();
        ViewHandler vh = contexto.getApplication().
            getViewHandler();

        UIViewRoot x = vh.createView(contexto, currentView);
        x.setViewId(currentView);
        contexto.setViewRoot(x);
    }

Si nos fijamos, este metodo recoge la vista actual de la página (viewId) y lo que hace básicamente es crearla de nuevo y crear un nuevo viewRoot. Una vez que hemos creado el nuevo viewRoot se lo asociamos al contexto y el entenderá que tiene que refrescar la página completamente.

Subida de ficheros

Febrero 1st, 2009
ADF, igual que otros muchos frameworks, trae su propio sistema de gestión para procesar la subida de ficheros. En este tutorial vamos a aprender como hacerlo.

Lo primero que necesitamos es configurar en el fichero web.xml ciertos parametros necesarios para gestionar la subida del fichero, vamos a darle valor a las propiedades que se van a encargar de gestionar donde se almacenarán los ficheros temporales, y cual va a ser el tamaño máximo permitido para los ficheros y para el buffer de memoria:

    <context-param>
        <!– Memoria maxima para cada peticion (en bytes) –>
        <param-name>
            oracle.adf.view.faces.UPLOAD_MAX_MEMORY
        </param-name>
        <param-value>992000000</param-value>
    </context-param>
    <context-param>
        <!– Tamano maximo en disco por peticion (en bytes) –>
        <param-name>
            oracle.adf.view.faces.UPLOAD_MAX_DISK_SPACE
        </param-name>
        <param-value>992000000</param-value>
    </context-param>
    <context-param>
        <!– Directorio de los ficheros temporales –>
        <param-name>
            oracle.adf.view.faces.UPLOAD_TEMP_DIR
        </param-name>
        <param-value>/tmp/ADFUploads/</param-value>
    </context-param>

Una vez configurado el fichero web.xml, podríamos comenzar a generar nuestra página. Para poder realizar la subida de ficheros, el componente que vamos a necesitar es <af:inputFile>. Nuestra página además llevará un botón que llevará asociado el evento ActionEvent para procesar la subida de ficheros cuando se pulse el mismo.

    <af:messages />
    <af:inputFile label="Seleccione el archivo"
        value="#{backing_registro.file}" />
    <af:commandButton text="Enviar"
        actionListener="#{backing_registro.procesarUpload}" />

Un dato a tener muy en cuenta, ya que a veces se nos puede olvidar, es que a la etiqueta que define el form, ya sea <h:form> o <afh:form>, debe llevar seteada una propiedad para indicarle que lo que se va a gestionar es una subida de ficheros. Veamos que valor hay que dar dependiendo del tipo de form que hayamos establecido:

    <af:form usesUpload="true">

    <h:form enctype="multipart/form-data">

Solo nos quedaría realizar el código del backing bean, como indicamos antes, el metodo llevará como parametro un ActionEvent para capturar el evento lanzado por el actionListener. En el método lo que vamos a realizar es una comprobación previa que el fichero no nos llega nulo, y si el fichero llega correctamente mostraremos un mensaje por pantalla:

    private UploadedFile file;
   
    public void procesarUpload(ActionEvent evento) {
        UploadedFile file = getFile();
      
        if (file != null)
        {

            FacesContext context =
                FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(
                "Subida del fichero " + file.getFilename() +
                " satisfactoria (" + file.getLength() +
                " bytes)");
            context.addMessage(
                evento.getComponent().
                    getClientId(context),message);

            // Aqui procesariamos el fichero
            // para guardarlo donde queramos
       
        }
       
    }
   
    public UploadedFile getFile() {
        return file;
    }

    public void setFile(UploadedFile file) {
        this.file = file;
    }

Aún no habríamos guardado el fichero en nuestro servidor, ya es cuestión del programador realizarlo de una manera u otra, y para ello ya no es necesario ningún framework, con las librerías de Java debería bastar. De todos modos, si alguien tuviera dudas de como realizarlo, hacédnoslo saber y ampliaríamos el tutorial.

Si hemos realizado todo correctamente, la página nos quedaría del siguiente modo:

subidaFicheros
Pulsa la imagen para verla en más detalle.

Internacionalización

Febrero 1st, 2009
Cuando tenemos aplicaciones web, que pueden ser visitadas por muchos tipos de clientes, es conveniente internacionalizar la misma. En Java, el método para ello, suele ser siempre el mismo, se crea un fichero properties por cada idioma, y las cadenas de texto que aparecen en nuestra página se cargan desde ese fichero.

En JSFADF el proceso es similar, a continuación vamos a explicar paso a paso, como internacionalizar nuestra propia aplicación web.

Lo primero que debemos hacer será crear nuestro fichero properties, el nombre que debemos darle a este fichero, variará dependiendo de los idiomas que queramos que soporte nuestra página. Por ejemplo, si queremos que la aplicación soporte los idiomas inglés y español, deberemos crear dos properties con el siguiente formato :

  • mensajes_ES.properties
  • mensajes_EN.properties

Donde el código que va siguiendo al caracter _, será el correspondiente al idioma que se usa en el mismo.

El contenido de estos ficheros siempre será el mismo:

    KEY = CADENA

Por ejemplo si queremos mostrar el mensaje Bienvenido debemos rellenar en nuestros ficheros properties lo siguiente:

  • mensajes_ES :

                SALUDO = Bienvenido

  • mensajes_EN :

                SALUDO = Welcome

Debemos de tener en cuenta que las cadenas que insertamos en estos ficheros no llevan la doble comilla.

Vamos a ver ahora, como cargar estos ficheros en nuestras páginas. Estos ficheros se cargan justamente debajo de la declaración de directivas del fichero .jsf, y para ello hacemos uso del componente de JSF llamado <f:loadBundle>. A este componente debemos setearle dos propiedades:

  • basename : nombre del fichero properties sin incluir el código del idioma.
  • var : nombre por el que vamos a referenciar al fichero.

    …    <f:view>
       <f:loadBundle basename="mensajes"
          var="msg">
    …

Ya sólo queda asociarle dichos mensajes, a los distintos componentes que tengamos en nuestra ventana, esto se hace mediante el etiquetado EL:

    <af:panelBox text="#{msg['SALUDO']}">

Si queremos asociar varias cadenas diferentes dentro de una misma propiedad, el formato sería el siguiente:

    <af:panelBox text="#{msg['SALUDO']} #{msg['USUARIO']}">

Para terminar, sólo quedaría definir los lenguajes que soporta nuestra aplicación, en el fichero de configuración faces-config.xml, así como el bundle que vamos a utilizar:

    <application>
       
        <default-render-kit-id>
            oracle.adf.core
        </default-render-kit-id>

       
        <locale-config>
            <default-locale>es</default-locale>
            <supported-locale>en</supported-locale>
        </locale-config>

        <message-bundle id="mensajes">mensajes</message-bundle>
       
    </application>

Desde los ficheros .java, muchas veces, también mostramos mensajes por pantalla al usuario, estos mensajes también se pueden internacionalizar. La manera de realizarlo es creandonos un objeto de tipo ResourceBundle:

    …        
    ResourceBundle bundle = ResourceBundle.getBundle("mensajes");
    …

Y a través de este nuevo objeto, podemos acceder a las cadenas contenidad en el fichero properties que le hemos pasado como parámetro:

    //String mensajeSaludo = bundle.getString(key);
    String mensajeSaludo = bundle.getString("SALUDO");    

Es importate recordar, que las diferentes key que definamos, tienen que estar soportadas en todos los archivos properties que tengamos asociados a la aplicación, ya que sino, corremos el riesgo que a los usuarios, le aparezcan mensajes de error en la lectura del fichero, si no está soportado dicho mensaje en su idioma. Por tanto, es recomendable, si no sabemos traducir una palabra en otro idioma, dejar esa key sin traducir, al menos así, no le apareceran mensajes de error a los usuarios.

El idioma se configura automaticamente, es el navegador del cliente de nuestra aplicación, el que va a detectar, que fichero properties debe usar en cada momento. Por tanto, no debemos nosotros crear ninguna regla ni condición en nuestro código para ello.

Messages in the FacesContext

Febrero 1st, 2009
Although to insert messages of error or information in the FacesContext, can be for many something quite simple, but it can be good explaining it for those people who are beginning in JSF. In the following tutorial we are going to learn to create them and show it in our pages with ADF.

In order to insert error messages simply we must call to the static object FacesContext and accede to the present context of the page:

FacesContext facesContext = FacesContext.getCurrentInstance();


Once we have gathered the object, we must call to one of its methods that are addMessage (…), of intuitive way, thanks to javaDoc we are going to insert the values to him to the parameters that need to us:

facesContext.addMessage
    ("cadena", new FacesMessage
        (FacesMessage.SEVERITY_ERROR, "cadena", "cadena"));

If we paid attention, the FacesMessage object is the one that will generate the type to us of message which we are going to show, that can be or of error, information, warning, etc.

Now we are going to remember, that component of ADF shows the information to us generated by the FacesContext:
<af:messages>


Adding this component, when the requests arrive at Phase 6 of the life cycle, the value of the component with the messages will be setted automatically that has contained in the FacesContext.

In addition to inserting messages, the FacesContext object has other functionalities, that already we will be seeing in tutorial futures.

Primeros pasos con JDeveloper

Febrero 1st, 2009
En este tutorial vamos a aprender lo más básico respecto al IDE JDeveloper, consistirá en como crear nuestro primer proyecto y a empezar a trabajar con una página en JSF y ADF.

Empezamos creando un nuevo proyecto:

  • Pulsamos el boton derecho en la ventana donde están listadas las distintas aplicaciones disponibles:

crear_aplicacion

Le debemos asignar un nombre a la aplicación que estamos creando, además debemos seleccionar el directorio donde queremos que se guarde nuestro proyecto. Como Application Template seleccionamos Web Application JSF, ADF BC, este campo se refiere a la tecnología que vamos a utilizar.

Para crear la primera página de nuestra aplicación pulsamos el segundo botón del ratón sobre la carpeta WebContent alojada en el directorio ViewController de nuestro proyecto, y a continuación seguimos los mismos pasos que se muestran en las siguientes imagenes:

tipoPagina

tipoPagina2

En la siguiente ventana del formulario, tenemos la opción de que el propio IDE nos cree el backing_bean y lo configure él mismo en el faces-config.xml. Seleccionaremos la opción que más nos interese en cada caso:

autoBinding

Ahora nos queda seleccionar que TLD(taglibs) queremos que aparezcan importados en nuestra página, para páginas en ADF normalmente sólo será necesario importar los taglibs de ADF y JSF, salvo que queramos usar tecnologías adicionales:

tld

Ya hemos completado el wizard para la creación de nuestra primera página. Siguiendo los ejemplos que aparecen en otros tutoriales podrás aprender a como usar los componentes que ahora te aparecen en la paleta de componentes.

First steps with JDeveloper

Febrero 1st, 2009

In this tutorial we are going to learn most basic with respect to the IDE JDeveloper, will consist of like creating our first project and to begin to work with a page in JSF and ADF.

We will begin creating a new project:

We pressed the right button in the window where the different applications available are listed:

create

We must assign a name to him to the application that we are creating, in addition we must select the directory where we want that our project keeps. As Application Template we selected Web Application JSF, ADF BC, this field talk about the technology that we are going to use.

In order to create front page of our application we pressed the second button of the mouse on the WebContent folder lodged in the ViewController directory of our project, and next we such followed steps that are in the following images:

type

type2

In the following window of the form, we have the option of which the own IDE creates to us backing_bean and it forms he himself in the faces-config.xml. We will select the option that interests to us more in each case:

autobinding

Now we have left to select that TLD (taglibs) we want that they appear mattered in our page, for pages in ADF normally will only be necessary to concern taglibs of ADF and JSF, unless we want to use additional technologies:

tld

We have already completed wizard for the creation of ours front page. Following the examples that appear in other tutorials you will be able to learn to like using the components that now appear to you in the trowel of components.

Navigation with popup

Febrero 1st, 2009
The creation of popups varies according to the JSF implementation that we use for each project. Each implementation gives to us the option to create popups modals or non modals. Today we are going to speak on popups in ADF, which are modals.

In order to create popup in ADF, we must define a rule of specific navigation, which will open the new window in form of popup, for it, in the file faces-config.xml we must write the following thing:

    <navigation-rule>
        <from-view-id>/ejemplo1.jspx</from-view-id>
        <navigation-case>
              <from-outcome>dialog:abrirPopup</from-outcome>
              <to-view-id>/ejemplo2.jsxp</to-view-id>
        </navigation-case>
    </navigation-rule>

Like any other rule of navigation, when executing a method and giving back a string like “dialog: abrirPopup” will redirect us to this page, but this time like a popup.

The case can be given that we want to pass values to the new page which we are opening, because equally that would happen if not outside popup, we would have to call to the static class AdfFacesContext and to do the following thing in our method associated to action:

    AdfFacesContext().getCurrentInstance().getProcessScope().put ( " key " , " objeto " );

If we want to get from the backing_bean these values would be made in the same way, but instead of set the values we would gather them:

    AdfFacesContext().getCurrentInstance().getProcessScope().get( " key " );

The only thing that we would have left to do would be to associate a property to him to the button that is going to open popup:

    useWindow = true;

This way we would have created simple popup in our page. Average ones exist other to be able to pass values to him to popup, and would be associating an event to him of type launchEvent to the button, and the only thing that would be to do is to capture the component and to pass the values to him of way to similiar to since we have explained previously. The problem to this is that sometimes, we want that according to that type of condition is made in the method associated to the event makes a navigation or another one, or that does not open any popup.

It can happen that we have in the event a condition that according to the size of a list, is sent to popup certain values to him, our intention would be that if that list is empty not sends popup but that is sent a message to the FacesContext. The parameters would be associated acceding to launchEvent, gathering the component and executing the method getDialogParameters().put (…);

To the same time, this being associated action to the button that sends popup, that would be executed before the previous event, therefore, is already settling down the string that is due to return to send popup (dialog: …).

If case gave us that not we must to send popup, we commanded message of error to FacesContext, would appear painted in screen, but since the navigation rule has been defined before the event is executed, is also opened to us popup.

The solution to the problem would be to eliminate that launchEvent and to execute the logic in action, and the values of popup of passing them through AdfFacesContext as we explain at the beginning of the tutorial.

Create components in runtime

Febrero 1st, 2009
Sometimes, the case, that can occur we want to create different components according to the state from the page or some action that has been executed in the same one. A solution to show the wished component would be to create a switcher component and be rotating the visibility of the component wished at every moment, but this can be a technique limited enough and “sometimes troublesome” to write the file jspx of our page.

A quite useful possibility is the one to create the component in run time, thus we would save extra code in the file jspx and in addition it gives control much more us of which we want to show in the page. With this we would clear an unnecessary weight to the initial charge of the page, because we will only load the components when we need them.

The way to create a component would be thus:

    FacesContext.getCurrentInstance().getApplication().
       createComponent(COMPONENTE.COMPONENT_TYPE);
This call would give like result a Object that we must cast to the wished component:

    CoreInputText input = (CoreInputText)FacesContext.
        getCurrentInstance().getApplication().
        createComponent(CoreInputText.COMPONENT_TYPE);

Once we have created the component, only we would already have left to give him the typical values of similar way to since we do it in jspx:
    input.setId("id1");
    input.setLabel("Etiqueta");

In the same way that we can create components, we can also create validators or converters in run time, the only thing that it would change is that in time to give as parameter constant COMPONENT_TYPE we would pass another constant called COMPONENT_FAMILY:

    FacesContext.getCurrentInstance().getApplication().
       createComponent(Validator.COMPONENT_FAMILY);


There will be times that besides to create the component, we want to associate actions to him to he himself, and lack makes associate to action a MethodBinding to him, the way to create it is not very complicated, simply we must know as it is the name associated to backing_bean and that values is going to receive like parameter the method to which we are going it to associate. The method to make is using it the following method:
    FacesContext.getCurrentInstance().getApplication().
       createMethodBinding(String, Class[]);

Where string that receives corresponds to label EL that reference to method that we want to call, that is to say, “# {nombre_backing_bean.metodo}”, and as second parameter receives an Array of the classes that is going to receive like parameters, like for example:

    Class[] array = new Class[1];
    array[0] = ValueChangeEvent.class;

This MethodBinding that we will receive we have it to associate to the component, by means of its corresponding one setter.

When we created components, although it is not required, always is advisable to set an id, there are a method which it is possible to be acceded to him through FacesContext, that will generá to us you go only for that component in the page, but in pages where we use to the same time several east UIViewRoot objects method can cause many problems to us, more than to help us. This happens because that method simply crosses the list of existing components for that object viewRoot and it assigns a found value to him corelative to the last one. Therefore, the best thing always will be to assign to him you go of a safe and unique way for all the cases that can be given in the page. The method is the following one:

    FacesContext.getCurrentInstance().getViewRoot().
       createUniqueId();

Once we already know like creating components, validators, etc only we have left to show them in some place of the page, because we have them created, but not positioned. The way to insert it in some place of the page is very simple, it would be acceding to the method getChildren () of some component that allows to insert children to him, and to add our component. The form to do it is always the same one:

    getPanel().getChildren().add(input);

CoreTable (1)

Febrero 1st, 2009
Vamos a dedicar este tutorial al uso del componente Table del framework ADF. Se encuentra en la librería:

	oracle.adf.view.faces.component.core.data.CoreTable 

El componente Table se usa para mostrar datos de manera ordenada. Este componente permite la selección de datos única y multiple, ordenación de campos por las columnas, así como más funcionalidades que iremos viendo a lo largo del manual.

Los valores que acepta este componente son CollectionModel, aunque nosotros podemos darle como valor un List o un SortableModel y él mismo se encargará de convertirlo en el tipo CollectionModel.

Para renderizar correctamente este componente, debemos asociarle unos hijos, que serán de tipo Column. Cada Column representará una columna de la tabla.

Podemos ver como deberíamos anotar una tabla en el fichero JSF en el siguiente ejemplo:

    <af:table …>
        <af:column …/>
        <af:column …/>
    </af:table>

A cada columna, podemos darle como valores de los hijos, cualquier componente que queramos que sea mostrado. Normalmente este componente será un OutputText que mostrará la información necesaria en cada momento:

    <af:table …>
       <af:column …>
          <af:outputText …/>
       </af:column>
    </af:table>

Las tablas tienen asociados una serie de facet en los cuales podemos colocar distintos componentes para darle un aspecto y funcionalidades distintos a las tablas según lo que añadamos. Vamos a ver uno a uno cuales son estos facets:

  • Actions : En este facet podemos añadir botones que aparecerán en la cabecera de la tabla y que son usados normalmente para realizar operaciones con los datos de las filas que tengamos seleccionadas.
  • DetailStamp : Se nos habilitará una columna extra donde aparecera un desplegable que controlará que aparezcan o desaparezcan los componentes asociados a dicho facet.
  • Footer : Los componentes añadidos a este facet se mostrarán en el pie de la tabla.
  • Header : Los componentes añadidos a este facet se mostrarán en la cabecera de la tabla.
  • Selection : A este facet le podemos añadir dos tipos de componentes, TableSelectOne o TableSelectMany que habilitan una columna extra donde dependiendo de cual componente hayamos añadido la tabla podrá ser de selección única o simple.

Un ejemplo completo de tabla sería el siguiente:

    <af:table emptyText="No items were found" banding="row"
        bandingInterval="1" binding="#{backing_untitled1.table1}"
        id="table1" rows="3" var="row"
        value="#{backing_untitled1.listaManuales}">
       
        <af:column sortable="false" headerText="Titulo"
            binding="#{backing_untitled1.column1}" id="column1">
            <af:outputText value="#{row.titulo}"
                binding="#{backing_untitled1.outputText1}"
                id="outputText1"/>
        </af:column>
       
        <af:column sortable="false" headerText="Autor"
            binding="#{backing_untitled1.column2}" id="column2">
            <af:outputText value="#{row.autor}"
                binding="#{backing_untitled1.outputText2}"
                id="outputText2"/>
        </af:column>
       
        <af:column sortable="false" headerText="Formato"
            binding="#{backing_untitled1.column3}" id="column3">
            <af:outputText value="#{row.formato}"
                binding="#{backing_untitled1.outputText3}"
                id="outputText3"/>
        </af:column>

       
        <f:facet name="detailStamp">
            <af:commandButton text="commandButton 1"
                binding="#{backing_untitled1.commandButton1}"
                id="commandButton1" blocking="true"/>
        </f:facet>
           
        <f:facet name="selection">
            <af:tableSelectMany text="Select items and …"
                binding="#{backing_untitled1.tableSelectMany1}"
                id="tableSelectMany1" required="false"/>
        </f:facet>
      
        <f:facet name="actions">
            <af:commandButton text="commandButton 2"
                binding="#{backing_untitled1.commandButton2}"
                id="commandButton2"/>
        </f:facet>
       
        <f:facet name="header">
            <af:outputText value="Cabecera"
                binding="#{backing_untitled1.outputText4}"
                id="outputText4"/>
        </f:facet>

        <f:facet name="footer">
            <af:outputText value="Pie de tabla"
                binding="#{backing_untitled1.outputText5}"
                id="outputText5"/>
        </f:facet>
    </af:table>

Vamos a conocer ahora más propiedades que tienen asociadas los componentes Table:

  • Banding : Indica si queremos que haya una separación de color entre las diferentes filas o columnas. Los valores aceptados son : none, column o row.
  • BandingInterval : El intervalo con el que se mostrará la separación de color explicada anteriormente.
  • EmptyText : Texto que aparecerá cuando la tabla no contenga ningun resultado.
  • Rows : El número de filas que apareceran en la tabla. Si hubiera más resultados que filas definidas, la tabla paginará automaticamente los resultados según el valor que le hayamos seteado. Si le damos el valor 0 se mostrarán todos los resultados sin ningún tipo de paginación.
  • Sortable : Indica si la columna es ordenable o no.
  • SortProperty : Acepta como parámetro el valor de un String o una expresión EL, que corresponderá a la propiedad por la que queremos que se organice la tabla (Ej. Ascendente, Descendente, etc).
  • Var : nombre con el que vamos a referenciar los valores de la tabla cuando le demos valor a las propiedades en los elementos Column. Es decir, si a la propiedad le hemos dado el valor "row" cuando vayamos a acceder a un valor de la tabla desde un Column se haría del siguiente modo:

            <af:outputText value="#{row.formato}" />

Como hemos comentado antes, las tablas aceptan varios tipos de valores, los cuales se encargará de convertir a CollectionModel, para nuestro ejemplo vamos a crear una lista de objetos del tipo List y se la asociaremos a la tabla para que sean mostrados por pantalla:

    public List<Manuales> getListaManuales(){
       
        List<Manuales> listaManuales = new ArrayList<Manuales>();
       
        Manuales manual = new Manuales();
       
        manual.setTitulo("Tablas");
        manual.setFormato("HTML");
        manual.setAutor("nuevascreaciones");
       
        listaManuales.add(manual);
       
        manual = new Manuales();
               
        manual.setTitulo("JSF");
        manual.setFormato("Word");
        manual.setAutor("nuevascreaciones");
               
        listaManuales.add(manual);
               
        manual = new Manuales();
               
        manual.setTitulo("ADF");
        manual.setFormato("PDF");
        manual.setAutor("nuevascreaciones");
               
        listaManuales.add(manual);
       
        return listaManuales;

    }

Este resultado es el que le asociamos a la propiedad value de la tabla:

    <af:table emptyText="No items were found" banding="row"
        bandingInterval="1" binding="#{backing_untitled1.table1}"
        id="table1" rows="3" var="row"
        value="#{backing_untitled1.listaManuales}">

Ahora sólo bastaría crear 3 columnas en nuestra tabla, que se encarguen de mostrarnos los valores de la lista. Como vimos antes, primero debemos setear un valor a la propiedad var y desde los outputText que están asociados como hijos en los column acceder a las propiedades de la lista:

    <af:column sortable="false" headerText="Formato"
        binding="#{backing_untitled1.column3}" id="column3">
        <af:outputText value="#{row.formato}"
            binding="#{backing_untitled1.outputText3}"
            id="outputText3"/>
    </af:column>

Si ejecutásemos ahora nuestra página, nos debería de aparecer algo parecido a lo siguiente:

CoreTable
Los componentes Table llevan también asociadas unas propiedades para capturar los eventos referentes a las filas de la table. Estos son el SelectionListener, Disclosure Listener, etc. Con ellos, podemos acceder a las filas y realizar su tratamiento de manera individual. Esto se realiza de igual manera que con cualquier otro componente. Debemos asociar al Listener el evento que tenemos en el BackingBean que reciba como parámetro el correspondiente Event.

Existen métodos del componente para acceder al elemento seleccionado, como es el getSelectedRowData() que nos devuelve la fila marcada. Éste y otros métodos serán estudiados con más detalles en futuros manuales.

Proyecto web Seam

Febrero 1st, 2009

Este tutorial cubre los primeros pasos necesarios para configurar la base de Seam en su versión 1.2.0.PATCH1 y para un proyecto Web Dinámico de Eclipse, el resto de librerías son adicciones para mayor funcionalidad. En primer lugar tras descargar el paquete de JBoss y descomprimirlo copiaremos los jars siguientes a nuestro WEB-INF/lib:

  • JBoss Seam Framework
    • jboss-seam.jar
  • Utilidades Apache
    • commons-lang-2.1.jar
    • commons-beanutils-1.7.0.jar
    • commons-codec-1.3.jar
    • commons-collections-3.1.jar
    • commons-digester-1.6.jar
    • commons-el-1.0.jar
  • MyFaces y JSTL Vista
    • myfaces-impl-1.1.4.jar
    • myfaces-api-1.1.4.jar
    • jstl-1.1.0.jar
  • BPM Eficiencia y Velocidad en Procesos de Negocio
    • jbpm-3.1.4.jar
  • Persistencia de Datos
    • hibernate-all.jar
  • Librerías de Terceros
    • thirdparty-all.jar

Otras librerias que no se deben usar si no se hace uso de EJB3 ralentiza la aplicación.

  • Implementaciones EJB
    • jboss-ejb3-all.jar

Una vez copiados todos los jars necesarios creamos un fichero seam.properties bajo nuestro src. Ya que si este fichero aunque vacío si no se crea durante la ejecución de nuestro proyecto Seam no cargara nuestros beans.

Llegados a este punto, pasamos a preparar los ficheros de configuración que irán bajo WebContent/WEB-INF, en primer lugar crearemos nuestro fichero faces-config.xml. Este fichero es el encargado de configurar quien gestiona el ciclo de vida de los componentes JSF (si tienes alguna duda al respecto visita alguno de los demas tutoriales de trinidadytobago.org) y la asociación de nombres a nuestras templates jsp.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE faces-config 

    PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"

    "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

	<lifecycle>

		<phase-listener>

			org.jboss.seam.jsf.SeamPhaseListener

		</phase-listener>

	</lifecycle>

</faces-config>

Como se observa lo único necesario para configurar minimamente es el listener encargado del ciclo de vida JSF. Así que en nuestro caso JSF delega el control del ciclo de vida de sus componentes sobre el listener de fases de Seam.

Ya configurado nuestro faces-config.xml creamos un fichero componentes.xml, ¡vacio!. Con esta estrutura:

<?xml version="1.0" encoding="UTF-8"?>

<components xmlns="http://jboss.com/products/seam/components"

	xmlns:core="http://jboss.com/products/seam/core"

	xmlns:drools="http://jboss.com/products/seam/drools"

	xmlns:security="http://jboss.com/products/seam/security"

	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://jboss.com/products/seam/core http://jboss.com/products/seam/core-1.1.xsd 

                 http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-1.1.xsd

                 http://jboss.com/products/seam/security http://jboss.com/products/seam/security-1.1.xsd

                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-1.1.xsd">

</components>

Este fichero es el encargado de controlar y gestionar la logica y componentes EJB que agregaremos a Seam. Recordemos que aunque este tutorial de configuración solo se enfoca a montar Seam como proyecto Web, el fin de Seam aunque no se haga uso de ellos es trabajar con EJB’s.

Solo nos queda crear nuestro fichero web.xml que contrendra las siguientes lineas:

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4"

	xmlns="http://java.sun.com/xml/ns/j2ee"

	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<display-name>tt</display-name>

	<!-- 1 -->

	<listener>

		<listener-class>

			org.jboss.seam.servlet.SeamListener

		</listener-class>

	</listener>

	<!-- 2 -->

	<servlet>

		<servlet-name>Faces Servlet</servlet-name>

		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

		<load-on-startup>1</load-on-startup>

	</servlet>

	<servlet-mapping>

		<servlet-name>Faces Servlet</servlet-name>

		<url-pattern>*.seam</url-pattern>

	</servlet-mapping>

	<!-- 3 -->

	<welcome-file-list>

		<welcome-file>index.html</welcome-file>

	</welcome-file-list>

</web-app>

Viendo esta configuración vamos a comentar paso a paso que es realmente lo que estamos viendo en el:

  1. org.jboss.seam.servlet.SeamListener: Este es el listener general de Seam y es totalmente obligatorio, ya que es el encargado de gestionar todas las peticiones.
  2. Faces Servlet: Este es el servlet para las componentes JSF. El filtro de este tambien apunta a *.seam esto implica que todas las peticiones serán reenviadas a un bean con la extensión *.seam y como ya vimos en nuestro faces-config.xml estos beans serán los que nosotros creemos para Seam.
  3. Finalmente los ficheros de bienvenida.

Con esto ya tendríamos configurado totalmente nuestro proyecto base. Solo nos queda arrancar Jboss con un despliegue de nuestro proyecto y ver que realmente no nos devuelve ninguna excepción.