viernes, 13 de julio de 2012

ADF 11g: af:query + af:table con datos precargados al iniciar

Al hacer Drag & Drop de una Named Criteria de una View (del Data Control de un Application Module), se puede crear un formulario de búsqueda con una tabla asociada para el manejo de los datos de nuestra base de datos.
Drag & Drop para formulario de búsqueda + tabla
Cuando se ejecuta la vista se puede observar que por defecto la tabla está vacía puesto que no se ha realizado ninguna búsqueda.
Tabla vacía nada más cargar la vista
Esto se debe a que es necesario que se realice una búsqueda (aunque sea con los campos vacíos) para que la tabla se rellene. Sin embargo, modificando el binding asociado a la View Criteria sobre la que se basa el af:query se puede lograr precargar una búsqueda para que cuando se cargue la página salgan datos inicialmente.
Para conseguirlo únicamente es necesario modificar el atributo InitialQueryOverriden poniendo su valor a true.
Modificación del binding a la View Criteria para precargar la búsqueda
Con esta configuración, al ejecutar por primera vez la vista que contiene la tabla asociada a un af:query vendrá precargada.

Datos precargados al ejecutar la vista

Ejemplo desarrollado en JDeveloper 11.1.1.6

lunes, 9 de julio de 2012

ADF 11g: JDBC Connection vs Data Source

Una de las dudas / problemas que surgen a la hora de desplegar aplicaciones ADF viene ligada con las conexiones a base de datos que se configuran en el Model de la aplicación.

En esta entrada voy a intentar aclarar cuál es el modo correcto para configurar las conexiones a BBDD de una aplicación ADF.

Cuando se comienza el desarrollo de una aplicación ADF con capa de negocio en base de datos. Lo primero que se hace es crear una conexión de Base de Datos desde las Application Resources.

Conexión a BBDD configurada
El siguiente paso es la creación de los ADF Business Components a partir de esa conexión a BBDD.
ADF BC generados a partir de la conexión

Como podrá observarse, también se ha generado un fichero llamado Model.jpx. Este fichero tiene, entre otras cosas, una conexión a BBDD. La conexión configurada en Model.jpx es la conexión de BBDD que utiliza la aplicación por defecto para generar los ADF Business Components. No es la utilizada por la aplicación en Runtime.

Model.jpx. Archivo donde se configura la conexión de la que se generan ADF BC

¿Entonces donde esta configurada la conexión que usará la aplicación?.
En los ApplicationModule.

El siguiente paso que se suele dar, es el de comenzar a utilizar directamente el Data Control generado en el View Controller. Por lo que el Data Control que se registra en DataBindings.cpx será algo parecido al siguiente:

DataControl usando la configuración Local por defecto del AppModule
Como se puede observar, la configuración del Data Control estará ejecutando la configuración por defecto del AppModule, en el caso del ejemplo MiEjemploAppModuleLocal que es una de las configuraciones por defecto que genera el AppModule.

Para cambiar las configuraciones de conexión a BBDD, así como el pool de conexiones inicial y demás parámetros comunes a una conexión de BBDD debemos ir al AppModule pestaña Configurations.

Configuraciones por defecto del AppModule

En esta ventana es donde se establece que configuración por defecto utilizará el Data Control asociado así como las distintas configuraciones que se quieran crear por si se quiere generar más Data Control con distinta conexión y parámetros de inicio.
En el caso del ejemplo se va a editar la configuración MiEjemploAppModuleLocal que es la que está por defecto configurada.
Editando la Configuración Local del AppModule
En las opciones se encuentran tres pestañas:
  • ApplicationModule: Aquí es donde realmente se configura la conexión a BBDD a utilizar. Ésta puede ser una conexión directa por JDBC URL o por Data Source (esta última es la recomendada).
  • Pooling and Scability: Aquí se configuran los datos típicos de inicio del pool de conexiones, timeouts etc...
  • Properties: Opciones avanzadas de la configuración del AppModule.
En la entrada de Blog nos centramos en la conexión a BBDD.
Como se puede comprobar, por defecto hay una conexión JDBC URL a la conexión de BBDD que se configuró al principio.
Es aquí donde tenemos que modificar para que en lugar de ejecutarse sobre una JDBC URL sea sobre un JDBC DataSource (que tenemos que habre creado en nuestro servidor de WebLogic y asociado al nodo manejado donde se ejecutará la aplicación).
Configuración por defecto al cambiar de JDBC URL a JDBC DataSource

Además, por cuestión de rendimiento, es conveniente eliminar el prefijo por defecto java:comp/env/... (en el ejemplo, java:comp/env/jdbc/MiConexionDS)

Modificación del nombre JNDI
Con este cambio lograremos que las aplicaciones ADF reduzcan considerablemente el tiempo que tardan en ser "Undeployed" del servidor. Por lo tanto el nombre del JNDI de WebLogic como el de la Configuración del AppModule quedaría como jdbc/MiConexionDS.

Pero esto no acaba aquí... 
Cuando empaquetamos la aplicación ADF en un EAR y se despliega en un WebLogic que no es el integrado veremos que tendremos problemas de conexión a BBDD aunque el Data Source esté generado correctamente puede que nos de un error en el que no encuentra la conexión a BBDD etc...
Esto se debe a que JDeveloper, por defecto, trae la opción de auto-generar y sincronizar el archivo weblogic-jdbc.xml al generar el EAR. 

¿Por qué ocurre esto?

Con la opción de sincronizado y auto-generado activada, la aplicación ADF va a buscar Data Sources globales generados en WebLogic. Como hemos hecho el renombrado del Data Source para ganar tiempo en cuanto a desarrollo en local tendremos problemas a la hora de desplegar en otros entornos.

Para evitar esto solamente hay que acceder a Application Properties -> Deployment.
Quitar la selección de Auto Generate and Synchronize weblogic-jdbc.xml Descriptors During Deployment.

Quitando la sincronización y autogeneración de weblogic-jdbc.xml
Referencias:

viernes, 6 de julio de 2012

Refrescar un UI Component externo a una af:region

Un caso muy común en el desarrollo con WebCenter Portal / Spaces es el de refrescar componentes de la página según acciones que se ejecuten en los Task Flow que esta incluye.


¿Cómo refrescar un UI Component según lo que haya ocurrido en un Task Flow?
Esta pregunta se responde fácilmente. Eventos Contextuales

La mayoría de Task Flows de WebCenter, como por ejemplo el de People Connections, disparan eventos según las acciones que se realicen en los mismos. Por ejemplo en People Connections las acciones de aceptar, ignorar o declinar una petición son disparadas.

En el siguiente ejemplo se va a simular esta problemática refrescando un af:outputLabel según los eventos que dispare un Task Flow.


En el ejemplo el caso es el siguiente:
UI Component que se refresca por PPR de una af:region
  • Tenemos un componente af:outputLabel cuyo valor debe ser modificado según ocurra algo en el Task Flow.
  • Tenemos una af:region con el Task Flow.
Para lograr hacer PPR en el UI Component consumiremos desde la pageDef los eventos disparados por la Task Flow. Seguir los siguientes pasos para realizar PPR en un componente consumiendo los eventos disparados:
  • Crear una clase Java para el manejo de eventos la cual será la encargada de realizar el PPR sobre el componente. En el caso del ejemplo, el método recibe un parámetro puesto que consumirá un valor emitido por los eventos. En muchas ocasiones no se suele necesitar el parámetro y directamente se hace PPR sin consumir nada.

    Clase de manejo de eventos que realiza el PPR
  • Crear un Data Control de la clase.

    Creación de Data Control del manejador de eventos
  • Acceder a la pageDef donde se encuentra nuestro UI Component y nuestra Task Flow y publicar en la Binding Layer un binding hacia el método del Data Control recién creado.

    Binding de tipo methodAction al método manejador
  • Abrir la pestaña de Contextual Events de la pageDef y en la pestaña Subscriber suscribirse a alguno de los eventos disparados asignando como método consumidor el método recientemente publicado en la Binding Layer. (También se puede hacer desde la Structure View, botón derecho a la pageDef y Edit Event Map).
    Suscripción de la pageDef al evento disparado por el Task Flow
  • Ejecutar la aplicación y al pulsar uno de los botones del Task Flow, el mensaje que se pasa por el payLoad (información transmitida del Task Flow a la página) será mostrado en la UI Component externa al mismo.
    PPR de la acción del Task Flow sobre el UI Component
Ejemplo desarrollado en JDeveloper 11.1.1.6

Enlace a descarga del ejemplo: RefreshUICompByEventApp

jueves, 5 de julio de 2012

ADF 11g: af:progressIndicator y af:statusIndicator

En muchas ocasiones se ejecutan servicios o procesos duros en los que la aplicación parece quedar "congelada". Para evitar que el usuario de la aplicación crea que nuestra aplicación "pasó a mejor vida" ADF nos proporciona dos componentes:

Enlace a la descarga del ejemplo

Interfaz del ejemplo
  • af:statusIndicator. Es el "simpático" iconito de la O de Oracle que cambia de icono a otro girando en el caso de que haya algún proceso en ejecución de la aplicación. Es posible modificar estos iconos (referencia a como hacerlo más adelante).
    Icono sin actividad 
  • af:progressIndicator. Es una barra de progreso típica que indica el estado de una operación. Siempre se puede usar cuando realmente se sabe el estado de la operación que se está realizando como, por ejemplo, insertar numerosas filas a base de datos (sabemos por que row del total vamos).
    Barra de progreso
¿Cómo usar cada una de ellas?

af:statusIndicator

Es el más sencillo puesto que solo se debe realizar Drag & Drop desde la paleta de componentes. Automáticamente, en caso de que alguna ejecución esté en curso, el componente cambiará entre dos gif's animados, uno estático y uno dinámico.

    Icono con actividad
    Icono sin actividad 
Componente de estado
Para cambiar estos iconos requiere aplicar Skinning de ADF. Referencias: 
af:progerssIndicator


Barra de progreso
Componente de progress con poll
Para usar la barra de progreso no basta únicamente con realizar Drag & Drop. Es necesario al menos:
  • Un Bean Java que extienda una clase abstracta del tipo BoundedRangeModel. Esta clase mantiene en todo momento cual es el máximo y cual es el valor actual de la barra de progreso.
  • Una operación af:poll para que se consulte el estado actual de la barra de progreso y se refresque.
  • Un método que se ejecute en el actionListener de la af:progressIndicator puesto que este evento es disparado cuando la barra de progreso llega a su fin y, por lo menos, hay que parar el af:poll.
El ejemplo
En el ejemplo adjunto a esta entrada se proporciona un ejemplo básico de barra de progreso junto al indicador de estado. En este ejemplo se lanza un hilo de ejecución y se refresca la barra de progreso mediante un poller (af:poll).

Para construir una barra de progreso como la del ejemplo (descarga disponible al final de la entrada) se deben tener en cuenta los siguientes pasos:
  • Crear una clase Java que extienda de BoundeRangeModel. En el ejemplo, además de poder acceder al máximo, y valor actual de la barra, se añade la posibilidad de consultar el porcentaje de la misma. Importante recordar que el bean que maneja la barra de progerso debe tener un scope mínimo de viewScope puesto que un scope menor haría que se perdiera el valor de progreso de la misma.
    Clase que implementa el modelo de la barra: BoundedRangeModel

  • Realizar Drag & Drop de manera conjunta de la af:progressIndicator y un af:poll configurando un PartialTrigger de la barra hacia el disparador de eventos programado (poll). Además, asociar en el value de la barra de progreso el bean que exitende de BoundedRangeModel.
  • Crear una clase Java encargada del manejo de la interfaz, de los valores iniciales de la barra de progreso, de iniciar / parar el poll y de lanzar / parar el proceso costoso.
    Clase controlador de los hilos / valores de la barra
  • Crear una clase que implemente Runnable para poder lanzar la ejecución en paralelo del proceso costoso y que tenga lectura sobre los valores actuales de la barra de progreso (por ejemplo una clase interna a la de manejo de la interfaz).
    Clase del proceso costoso que es lanzado como hilo
Más datos a tener en cuenta:
  • Para parar / iniciar un af:poll se debe cambiar su propiedad rendered y además el PartialTrigger debe ser al componente padre del mismo.
  • Tener cuidado con la clase Thread y verificar que realmente los hilos terminan su ejecución. Esto puede llevar a problemas en cuanto a consumo de JVM. Normalmente se generan los de incidencias de WebLogic inc_[numero] donde podremos consultar errores que han ocurrido en el hilo de ejecución.
Ejemplo desarrollado en JDeveloper 11.1.1.6

Enlace al ejemplo: BarraProgresoApp

Referencias:

miércoles, 4 de julio de 2012

ADF 11g: Variables de página

Una duda que suele surgir a la hora de crear la pageDef de una página es la siguiente:

Enlace a descarga del ejemplo

¿Para qué sirve el 'executable' variables?
Una de las funcionalidades que nos permite es la creación de "variables" asociadas a Data Controls (como cuando hacemos Drag & Drop de una View Object y genera el Iterator). Pero, por otro lado nos permite la generación de variables del tipo que queramos (por ejemplo java.lang.String).


Executable variables de una pageDef

¿Cómo puedo crear una variable?
En la propia pageDef lo podemos realizar desde la vista Structure o desde la propia pageDef haciendo click derecho en el propio ejecutable variables.
Seleccionar en Insert Inside Variables -> variable para crear una variable.


Creación de una variable en el executable variables (I)

Dar un nombre lógico y el tipo de datos de la variable.


Creación de una variable en el executable variables (II)

Generar un binding a dicha variable para facilitar el acceso a la misma. El binding será de tipo attributeValues.

Creación del Binding a la variable (I)
Elegir la fuente del binding, en este caso, variables y la variable recién creada.

Creación del Binding a la variable (II)
Con ello ya podemos usar la variable para almacenar o mostrar los valores que queramos:

Binding a la variable creado


  • Uso en JSPX.
    Uso del Binding en JSPX

  • Uso desde JAVA.
    Uso del Binding desde JAVA
Aprovechando el ejemplo comentar que se puede modificar la ruta donde crea automáticamente JDeveloper las pageDef. Para ello seleccionar en las propiedades de proyecto del ViewController. Navegar a ADF Model y en el apartado PageDef sub-package podemos decir el prefijo de carpetas donde se almacenarán las pageDef. Hay que tener en cuenta que este prefijo será adherido al ya configurado por defecto para la aplicación como ruta de paquetes base.

Cambio de ubicación por defecto de las pageDefs

Ejemplo desarrollado en JDeveloper 11.1.1.6

Enlace al ejemplo descargable: PageDefVarApp

martes, 3 de julio de 2012

ADF 11g: No se puede encontrar o invalida su entidad propietaria

Un error clásico cuando se hace un Create de una fila para una entidad es:

Enlace de descarga del ejemplo

"oracle.jbo.InvalidOwnerException: JBO-25030: La entidad de detalle Y con la clave de fila null no se puede encontrar o invalida su entidad propietaria."
Error al realizar una operación Create en una tabla Detalle sin su Maestro

¿A que se debe este error?
Cuando se tiene un modelo de datos en el que existen entidades "Maestro - Detalle" se hace muy común este problema.
El problema reside en la creación de filas en la entidad Detalle sin que la entidad Maestra se encuentre en la misma página.
Supongamos el siguiente modelo de datos: 

Modelo de datos, Tabla Maestro-Detalle. Dado un idioma, tienes los portales asociados


Como se puede comprobar, existe una relación de Foreign Key entre PortalesWeb e Idiomas por el campo ID del idioma. Esto lo que supone es que:
  • Tabla Idioma es la maestra.
  • Tabla PortalesWeb es el detalle.
Por lo tanto, al generar los Business Components se generará una asociación entre las entidades forzando una Composite Association entre ambas. Esto quiere decir que existirá una relación fuerte entre ambas y no permitirá el uso de la tabla detalle de manera independiente.

Asociación generada automáticamente con los ADF BC

¿Cómo solventar el problema si queremos contribuir más detalles en una página aparte de la tabla maestra?
Existen varias soluciones al problema: Eliminar la fuerte asociación entre entidades o usar realmente la entidad detalle conjuntamente con su maestra. A continuación se describen las dos soluciones.
  • Eliminar la fuerte asociación entre las entidades. Es lo más fácil, rápido, pero poco ético puesto que se pierde la relación a nivel de modelo de la aplicación. Sin embargo, suele ser común el uso de esta solución puesto que en numerosas ocasiones el atributo que actúa de Foreign Key realmente es una List Of Values de la tabla maestra logrando así restringir los valores posibles para dicho atributo.
    Para conseguir eliminar la fuerte asociación abrir la assoc entre las dos entidades Maestro-Detalle y cambiar la siguiente configuración:
    • En el modo Overview del XML, navegar a Relationship -> Behaviour.
      Assoc entre Maestro-Detalle sin modificar
    • Desactivar Composite Association y así no existirá más dicho problema.
      Desactivando la fuerte asociación entre entidades.

  • Usar la vista del AppModule procedente de la View Link. Con esta solución se está generando una fila para un valor determinado de la entidad maestra. Por lo que no se esta violando la restricción.
    DataControl del AppModule, explicando cada vista con su solución.
Ejemplo descargable: ForeignAssocApp

Desarrollado en JDeveloper 11.1.1.6 apoyado en una BBDD Oracle XE 10g.

Datos: El ejemplo demuestra el problema de intentar crear una fila de una entidad detalle sin su maestra. Podéis modificar el assoc para comprobar que realmente el problema desaparece con la primera solución.
El modelo y los datos iniciales se encuentran en los script: script1.sql, insert.sql respectivamente
Existe una Offline DataBase en el proyecto Model para que podais cargar automáticamente el modelo de datos en un esquema de vuestra BBDD.

Referencias: