martes, 2 de septiembre de 2014

ADF11gR1: Task Flow ejecutados en Dialogo/Popup

Hay dos modos de ejecutar un Task Flow en popup.

Versión en inglés [comming soon]
  • Generando la Bounded Task Flow basada en páginas JSPX en lugar de fragmentos JSFF. Con ello se consigue que el Task Flow pueda ser llamado como diálogo en una actividad de otro Task Flow.

    Task Flow invocado como inline-popup

  • Usando la Bounded Task Flow como Region dentro de un af:popup
    
        
          
            
              
            
            
              
              
                
              
            
          
        
        
        
          
          
            
          
        
     
    

Ventajas e Inconvenientes de cada solución

Solución basada en TF-Call JSPX

Ventajas:
  • Se puede utilizar el framework de ADF para llamar en módo diálogo el Task Flow.
  • El Task Flow puede devolver valores a su vuelta usando el Return Values.
Inconvenientes:
  • Mayor dificultad para aplicar estílos específicos al Diálogo/Popup.
  • El Task Flow no puede ser embebido como Region.

Solución basada en Region embebida en un af:popup

Ventajas:
  • Se puede reutilizar como Region en otras Unbounded/Bounded Task Flow.
  • Facilidad para aplicar styleClass específicos para af:popup y af:dialog.
Inconvenientes:
  • No se puede devolver valores en el Return Values. Se debe realizar mediante Eventos Contextuales y un regionNavigationListener.
  • Para refrescar el Task Flow ejecutado dentro del popup. No basta con una política de refresco en Refresh y Refresh Condition. Hace falta controlar la activación del Task Flow cuando éste se abre y se cierra.

El ejemplo

El ejemplo requiere conocimientos básicos de ADF 11gR1 y contiene ambas soluciones. A través de las siguientes páginas de test se puede seguir el ejemplo:
  • testPopupInTFCall.jspx: Ejecuta los Task Flow que demuestra como un TF es invocado en modo diálogo y, a su vez, devuelve valores utilizando su Return Value. Puntos importantes del ejemplo:
    • El Task Flow es invocado como TF-Call en modo dialogo. Por ello el botón de navgación hacia el dialogo debe tener useWindow="true".
       
      


    • Al tener configurado Return Values, se mapean a una variable de Page Flow Scope para poder ser usada por el fragmento.

      Return Values definidas para el Task Flow invocado como diálogo

      Mapeo del valor devuelto por el Task Flow a una variable local del Task Flow
  • testPopupInRegion.jspx: En el se encuentra una Task Flow que es invocada en un af:popup. Configurada la política de activación para que el Task Flow se active y se cierre según . Además, incluye el uso de Eventos Contextuales para obtener los datos de respuesta. Puntos importantes de esta parte:

    • Politica de activación del Task Flow para que se desactive y active según es abierto / cerrado el popup.
      Política de activación del Task Flow
    • Uso de eventos contextuales (disparado programaticamente) en el botón que cierra el diálogo / popup para devolver los datos al Task Flow llamador.

      
        
        
          
          
            
              
            
          
        
        
          
            
          
        
        
          
            
              
                
                  
                
              
            
          
        
      
      

      /**
       * Closer Picker action
       * @param ae Action Component used
       */
      public void performClose(ActionEvent ae) {
       
       // Execute the Contextual Event programmatically before of unloading the popup
       BindingContainer bindingContainer = BindingContext.getCurrent().getCurrentBindingsEntry();
       JUEventBinding eventBinding = (JUEventBinding)bindingContainer.get("returnDialogEventBinding");  
       ActionListener actionListener = (ActionListener)eventBinding.getListener();  
       actionListener.processAction(ae);  
       
       // Check the Input Parameter if the TF has to be considered as executed in popup
       AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
       Map flowScope = adfFacesContext.getPageFlowScope();
       Boolean isPopup = (Boolean)flowScope.get("isPopup");
       if (isPopup != null && isPopup) {
        this.closePopup(ae);
       }
      }
      
      /**
       * Auxiliar method to close the popup
       * @param ae
       */
      private void closePopup(ActionEvent ae) {
       // Looking for the RichPopup parent of picker
       UIComponent component = ae.getComponent();
       while (!(component instanceof RichPopup))
        component = component.getParent();
       if (component != null)
        ((RichPopup)component).cancel();
      }
      

      public final class ContextualEventHandlerDC {
          
          /**
           * Default Constructor
           */
          public ContextualEventHandlerDC() {
              super();
          }
          
          /**
           * Get the list of names returned by the Contextual Event
           * @param names
           */
          public void handleReturnEvent(List names) {
              for (String s: names) {
                  System.out.println(s);
              }
              AdfFacesContext.getCurrentInstance().getPageFlowScope().put("returnedNames", names);
          }
      }
      
Enlace al repositorio GitHub del Ejemplo

Ejemplo desarrollado en JDeveloper 11.1.1.7

viernes, 20 de junio de 2014

Migrando los ejemplos a GitHub

Para evitar pérdidas de código asociado a algunos de los ejemplos he abierto mi propio repositorio de GitHub donde dejaré el anterior y futuro código que postee por el blog.

Repositorio GitHub con los ejemplos

Mientras no esté todo migrado a https://github.com/DanielMerchan los enlaces seguirán bajando los ejemplos de Dropbox.

Un saludo.

af:panelTabbed, Task Flows y WebCenter Portal

Los Task Flow en ADF 11gR1 (framework en el cual se basa WebCenter Portal 11g) se cargan de manera secuencial. Esto significa que hasta que el último Task Flow no finaliza su primera actividad la página no es renderizada.

Existe un truco del ATEAM para simular un Lazy Loading de los Task Flows.
http://www.ateam-oracle.com/improving-adf-page-rendering-time/

Existe un número mágico que dice de no tener más de 8 Task Flows por página.

En numerosas ocasiones, estos Task Flows se encuentran en componentes af:panelTabbed separados por pestañas. El problema reside en que todos los Task Flows (incluyendo las pestañas no visibles) ejecutarán todos los Task Flows que contengan.

Ejecución de los 3 Task Flows aunque los otros dos no se vean
 Cómo ejecutar solo los componentes de la pestaña actual?
  1. Configuración de la activación de los Task Flows
    Andrejus
    explica como configurar la propiedad de Activation de los Task Flow. Con esta propiedad se puede controlar la activación y desactivación de Task Flows cuando se seleccionan las distintas pestañas del panel.
    http://andrejusb.blogspot.com.es/2013/09/conditional-task-flow-activation-in-adf.html

  2. Configurar la propiedad childCretion de af:panelTabbed
    Configurando la propiedad childCreation se puede conseguir que las pestañas no activas no ejecuten los Task Flows o componentes que tienen hasta que son seleccionadas. Los valores que puede tomar childCreation son:

    • immediate: Al cargar la página todas las pestañas se ejecutan.
    • lazy: Solamente se ejecuta la pestaña actual y guarda el estado en el que se quedó el Task Flow. Al volver a la pestaña NO se ejecutara de nuevo el Task Flow desde el principio.
    • lazyUncached:  Solamente se ejecuta la pestaña actual. A diferencia de lazy, cada vezs que se vuelva a una pestaña que ya fue ejecutada el Task Flow se re-ejecutara desde el principio.
     
Con una configuración de af:panelTabbed a lazy o lazyUncached se puede conseguir un aumento de rendimiento considerable en el caso de que algún Task Flow de alguna pestaña sea pesado.

Recordar que por defecto es immediate.

Referencias:
http://docs.oracle.com/cd/E28280_01/apirefs.1111/e12419/tagdoc/af_panelTabbed.html