jueves, 28 de abril de 2016

Refrescar un iterador Bean Data Control en ADF

Cuando implementamos un formulario ADF basado en un Bean Java como es un Data Control, nos hemos encontrado que al navegar en una misma Bounded Taskflow entre diferentes jsff, los datos modificados del Bean no se han actualizado en la siguiente página.

Esto es debido a que cuando se modifican los datos del Bean mediante Java, hay que hacer un refresh del iterator que se alimenta del Data Control.
Por defecto la opción "CacheResults" de un iterator va a estar como true:




Si no queremos modificar esta opción, el método más adecuado es añadir el método "Execute" del iterator antes de cargar la página que no estaba refrescando. El método "Execute" se encuentra dentro de las Operations del iterator en la pestaña de Data Controls:

 


martes, 26 de abril de 2016

RIDC para integrar ADF con WCC

Si nos surge la necesidad de utilizar WCC como gestor documental para nuestras aplicaciones, la primera opción que nos surge es la de usar los servicios que proporciona Content. Estos servicios se pueden integrar mediante WS a través de WSDL. Pero hemos tenido alguna serie de problemas con algunos de ellos, como el servicio de Check-in que permitía hasta un máximo de X MB, o errores "java heap space".

Por ello WCC proporciona un API llamado RIDC (Remote Intradoc Client) que permite la comunicación utilizando diferentes protocolos para utilizar WCC.

El uso del API es bastante sencillo, debemos bien usar el JAR que se encuentra en la instalación de WCC 11g ([..]/weblogic/Oracle/Middleware/Oracle_ECM1/ucm/Distribution/RIDC/) o bien realizar la instalación de una extensión de JDeveloper (Oracle Remote Intradoc Client (RIDC) extension 11.1.1.6 (11gR1 PS5)).

En la página oficial tenemos información de uso y como realizar la instalación (https://docs.oracle.com/cd/E23943_01/doc.1111/e10807/c23_ridc.htm#CSSDK888).

lunes, 7 de marzo de 2016

Integración WS-ADF

Vamos a mostrar la integración de un WS para su consumo desde ADF. Para ello vamos a realizar los siguientes pasos:

1º) Creamos un proyecto Java donde residirá el punto de entrada al WS.











2º) Seleccionamos en el proyecto con New => Web Service  Client and Proxy.

3º) Indicamos la URL del WSDL del servicio e indicamos que queremos copiar el WSDL en nuestro proyecto.







4º) Dejamos las opciones por defecto hasta "Policy" donde debemos marcar la política del WS (tipo de autenticación y seguridad). En nuestro caso es la oracle/wss_http_token_service_policy




5º) Observamos la estructura de ficheros que se han creado. En la clase nameServicioPortClient se muestra un ejemplo de como se crea el servicio:

    public static void main(String[] args) {
        GlanceVolcadoBindQSService glanceVolcadoBindQSService = new GlanceVolcadoBindQSService();

        // Configure security feature
        SecurityPoliciesFeature securityFeatures = new SecurityPoliciesFeature(new String[] {
                                                                               "oracle/wss_http_token_client_policy" });
        GlanceVolcadoPtt glanceVolcadoPtt = glanceVolcadoBindQSService.getGlanceVolcadoBindQSPort(securityFeatures);
        // Add your code to call the desired methods.


    }


6º) Creamos un paquete aparte donde crearemos propiamente el servicio:

    public int getGlanceVolcado(String cdIdenti, int pendientes, Date fecha) {
        System.out.println("AnaliticasOperacionesServiceImpl::Llamada servicio...");
        int respuesta = -1;
        GlanceVolcadoBindQSService glanceVolcadoBindQSService = new GlanceVolcadoBindQSService();

        // Configure security feature
        SecurityPoliciesFeature securityFeatures = new SecurityPoliciesFeature(new String[] {
                                                                               "oracle/wss_http_token_client_policy" });


// Add your code to call the desired methods.

//Objecto que sirve el servicio
         GlanceVolcadoPtt glanceVolcadoPtt = glanceVolcadoBindQSService.getGlanceVolcadoBindQSPort(securityFeatures);
        try {

//Cogemos los parámetros de la request del contexto, en este caso el usuario y contraseña de la //policy
            Map<String, Object> reqContext = ((BindingProvider) glanceVolcadoPtt).getRequestContext();
            reqContext.put(BindingProvider.USERNAME_PROPERTY, AnaliticasOperacionesConstants.wss_http_token_client_policy_username);
            reqContext.put(BindingProvider.PASSWORD_PROPERTY, AnaliticasOperacionesConstants.wss_http_token_client_policy_pwd);



//Creamos un objecto de tipo solicitud para pasar los parámetros necesarios
            VolcadoRequestType request = new VolcadoRequestType();
            request.setCdidenti(cdIdenti);
            DatatypeFactory df = DatatypeFactory.newInstance();
            GregorianCalendar gc = new GregorianCalendar();
            gc.setTimeInMillis(fecha.getTime());
            request.setFechaIni(df.newXMLGregorianCalendar(gc));
            request.setPendientes(pendientes);
            System.out.println("AnaliticasOperacionesServiceImpl::getGlanceVolcado::cdIdenti::"+cdIdenti);
            System.out.println("AnaliticasOperacionesServiceImpl::getGlanceVolcado::pendientes::"+pendientes);
            System.out.println("AnaliticasOperacionesServiceImpl::getGlanceVolcado::fecha::"+fecha);

//Hacemos la llamada al servicio y recogemos la respuesta
            VolcadoResponseType response = glanceVolcadoPtt.glanceVolcado(request);
            if (response != null) {

//El resultado de la llamada al servicio
                respuesta = response.getResult();
                System.out.println("AnaliticasOperacionesServiceImpl::getGlanceVolcado::Respuesta::"+response.getResult());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("AnaliticasOperacionesServiceImpl::Fin llamada servicio");
        return respuesta;
    }


 6º) En nuestro proyecto ViewController, primeramente en "Dependencies" debemos añadir el build output del proyecto del servicio para poder utilizar sus clases.





7º) Creamos una clase Bean que contendrá la llamada al método del servicio de la clase creada anteriormente:

public class PruebaBean {
    public PruebaBean() {
        super();
    }
   
    public int getGlanceVolcado(String cdIdenti, int pendientes, Date fecha){
        AnaliticasOperacionesServiceImpl impl = new AnaliticasOperacionesServiceImpl();
        return impl.getGlanceVolcado(cdIdenti, pendientes, fecha);
    }
}



8º) Creamos un DataControl de la clase creada, mediante botón derecho en la clase "Create Data
Control":







9º) Ahora el método puede ser accesible desde cualquier taskflow y realizar la llamada al servicio



 





martes, 1 de marzo de 2016

Consulta estado instacias BPM

Muchas veces necesitamos sacar un reporte del estado de las instancias de un proceso de BPM. El EM no facilita mucho esta tarea, por lo que tenemos que recurrir al esquema SOA_INFRA de base de datos donde se almacena esta información.

Con la siguiente querie podemos recuperar la información que necesitamos, customizando por aquellos campos que deseamos obtener:

SELECT (CASE WHEN STATE=1 THEN 'OPEN AND RUNNING'
WHEN STATE=2 THEN 'OPEN AND SUSPENDED'
WHEN STATE=3 THEN 'OPEN AND FAULTED'
WHEN STATE=4 THEN 'CLOSED AND PENDING'
WHEN STATE=5 THEN 'CLOSED AND COMPLETED'
WHEN STATE=6 THEN 'CLOSED AND FAUTED'
WHEN STATE=7 THEN 'CLOSED AND CANCELLED'
WHEN STATE=8 THEN 'CLOSED AND ABORTED'
WHEN STATE=9 THEN 'CLOSED AND STALE'
WHEN STATE=10 THEN 'NON-RECOVERABLE'
ELSE STATE || ''
END) AS STATE, COUNT(*) AS NUM_OF_CUBE_INST from cube_instance where composite_name = 'XXXXXX' and composite_revision = 'X.X' GROUP BY STATE;

martes, 23 de febrero de 2016

Override prepareSession del Module de una aplicación

En ocasiones es necesario preparar la sesión de base de datos antes de realizar cualquier acción sobre la base de datos. Para ello hay que hacer un override del método prepareSession del Module. Para ello hacemos lo siguiente:

1. Creamos otro Module, con las mismas características que nuestro Module, que lo único que hará será en su implementación extender de la clase ApplicationModuleImpl para sobreescribir los métodos que queremos, en este caso el prepareSession.

public class CustomCommonModuleImpl extends ApplicationModuleImpl {

    private static final ADFLogger LOGGER = ADFLogger.createADFLogger(CustomCommonModuleImpl.class);

    public CustomCommonModuleImpl() {
        super();
    }

    protected void beforeDisconnect() {
        CustomTransactionImpl dbTrans = (CustomTransactionImpl) this.getDBTransaction();
        OracleConnection conn = dbTrans.getConnection();

        try {
            conn.close(OracleConnection.PROXY_SESSION);
        } catch (SQLException e) {
            throw new JboException(e);
        }

        super.beforeDisconnect();
    }

    protected void prepareSession(Session session) {
        super.prepareSession(session);

        ...
        }


    }


2. En nuestra implementación del Module, hacemos lo siguiente:

public class xxxImpl extends CustomCommonModuleImpl implements xxxModule {
...
}

3. Importante! Si queremos que se llame al prepareSession antes de cada consulta/update/insert en base de datos, hay que ajustar los siguientes parámetros:

3.1) jbo.doconnectionpooling.- Se ajusta en la siguiente pantalla (luego aparece en properties con 1). 




 3.2) jbo.txn.disconnect_level a 1



Paso variables entre capa View-Controller y Model

Se nos plantea la problemática de necesitar pasar unos parámetros de la capa View-Controller al Model, en concreto para hacer un override del método prepareSession de Model para setear el contexto del usuario logado. A nivel de MVC no está bien visto que la capa VC acceda al M, pero es la única forma que hemos encontrado para hacerlo.

Para ello, en el bean de Session definido en la aplicación, definimos las dos variables que necesitamos pasar al Model:

        //Preparamos en session el cdempresa y cddelega
        ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
        HttpSession userSession = (HttpSession) ectx.getSession(true);
        userSession.setAttribute("cdDelega", cddelega);
        userSession.setAttribute("cdEmpresa", (cdempresa+cdempresa));


 Ahora, en el implement del Module:

        Map sessionScope = ADFContext.getCurrent().getSessionScope();
        if (sessionScope.get("cdDelega") != null && sessionScope.get("cdEmpresa") != null) {
            String cdDelega = (String) sessionScope.get("cdDelega");
            String cdEmpresa = (String) sessionScope.get("cdEmpresa");

            ...

miércoles, 3 de febrero de 2016

Resetear el valor de un input en el ValueChangeListener

Esta post surge por la necesidad de restituir el valor de un componente que ha sido introducido en una LOV, porque por requerimientos se ha hecho una comprobación en el ValueChangeListener y no se tiene que setear el valor buscado en la LOV.

Mediante el parámetro valueChangeEvent del método ValueChangeListener, podemos hacer lo siguiente:

public void method (ValueChangeEvent valueChangeEvent) {

   ...

   ((UIXEditableValue)valueChangeEvent.getComponent()).resetValue();

   ...

}