martes, 14 de febrero de 2012

Integración de Oracle OAM y WebCenter Portal

Al seguir la documentación oficial de Oracle para integrar Oracle OAM y Oracle WebCenter (en su versión PS3) me encontré que la mayoría de problemas surgen a la hora de integrar con una aplicación de WebCenter Portal. Al seguir la documentación suele darse dos casos.
  1. Al integrar con la aplicación de Oracle WebCenter Spaces, la integración con Oracle OAM se realizaba sin ningún tipo de problema alguno.
  2. Al integrar con una aplicación de Oracle WebCenter Portal, la integración con Oracle OAM parece no conseguirse.
Para solucionar el problema con una aplicación de Oracle WebCenter Portal, además de haber seguido los pasos proporcionados por la documentación, se debe de añadir el método de autenticado a nuestro archivo web.xml.

Configuración de login-cert visual (web.xml)

Configuración de login-cert manual (web.xml)
Con ello lograremos que realmente al realizar el login en el popup estándar de Oracle OAM, también estemos identificados en nuestra aplicación de WebCenter Portal.

Popup estándar de Login de Oracle OAM.

Espero que os haya ayudado.

Referencias:
  • Oracle WebCenter PS3.
  • Oracle OAM 11g.
  • Servidor web. Apache.


26 comentarios:

  1. Buenas, tengo un problema al crear un portlet a partir de una web fusion application para luego desplegarla como portlet en un webcenter portal.
    El problema consiste en que en mi portlet debo proporcionar la descargar de un documento pdf. Para producir la descarga del documento debo utilizar la HttpResponse y aquí viene el problema. Cuando despliego el portlet en webcenter y pulso un botón para descargarme el pdf me da un error porque me indica que al hacer getResponse del contexto de adf, lo que me viene es un ActionResponse, no un HttpResponse. Y este ActionResponse no contiene métodos válidos para proporcionar la descarga como el outputStream. Espero que entiendas mi problema y puedas ayudarme. Gracias.

    ResponderEliminar
  2. Hola Barbasco.

    Al estar en un portlet, ahora FacesContext.getExternalContext().getResponse() recibes un ActionResponse en vez de un HttpServletResponse.

    Para poder ayudarte necesito conocer lo siguiente.
    ¿Con qué versión de WebCenter estás trabajando?.

    Si estas con un ADF Portlet, intenta utilizar , tienes un tutorial en http://saumoinak.blogspot.com/2011/04/file-download-in-adf.html .Sin embargo, no recuerdo bien si este componente tenía algún problema a la hora de utilizarlo en un Portlet consumido por WebCenter.

    Si te encuentras en un Portlet con la especificación JSR-286 intenta mirar la novedad que trae para servir recursos (Resource). Puedes empezar mirando por http://developers.sun.com/portalserver/reference/techart/jsr286/jsr286_2.html#Serving_Resources

    Por otro lado comentarte que una solución rápida es la de crearte tu propio Servlet de descargas e invocarlo desde el Portlet.

    De todos modos intentaré realizar una prueba de concepto e intentar compartirte una solución más rapida.

    ResponderEliminar
  3. Muchas gracias Daniel, estoy creando a partir de una aplicación adf estándar, un portlet aplicándole el estándar JSR-168. No se si te sirve con esto, pero de todas formas voy a intentar preguntar a la empresa con la que trabajamos la versión que usan de webcenter.

    Muchas gracias otra vez.

    ResponderEliminar
    Respuestas
    1. Si estas en una versión de Oracle WebCenter PS3 o superior aplica un JSR-286 y utiliza la funcionalidad de servir recursos ue proporciona este estándar.

      En caso de tener un JSR-168 crea un Servlet propio para descargas o intenta utilizar el componente ADF indicado en este Blog http://saumoinak.blogspot.com/2011/04/file-download-in-adf.html

      Un saludo.

      Eliminar
    2. Ya tengo preparado mi servlet, declarado en el web.xml. Pero ahora una pregunta: ¿cómo invoco este servlet desde mi método del managedBean?, cómo obtengo el path+/miservlet??

      Eliminar
    3. Si tienes la necesidad de invocar desde un Manage Bean mejor sigue la vía de :

      - Si tienes ADF http://adfcodebits.blogspot.com/2010/06/bit-19-downloading-file.html

      - Si es JSF: http://stackoverflow.com/questions/1686821/execute-backing-bean-action-on-load Cambiandolo a tus necesidades

      El Servlet es la solución rapida siempre y cuando lo invocaras por URL en la JSPX (también podrías desde Java pero sería "feo"). Lo siento si he podido confundirte.

      Optaría por la opción ADF usando af:fileDownloadActionListener como te indique en los 2 Blog de ADF, es sencillisimo y es basicamente como un Servlet en el que cargas los bytes en un outputStream.

      Eliminar
    4. De todos modos si quieres invocarlo por Java tu Servlet (y no probar af:fileDownloadActionListener) utiliza el estándar de Java para realizar una petición HTTP.

      Eliminar
    5. Pero al objeto httpclient se le puede pasar una uri "/miservlet"?? interpretaría este contexto desde un portlet??

      Eliminar
    6. Una URI no, desde el portlet deberia ser la URL.

      De todos modos porque no migras la solución a af:fileDownloadActionListener?, el código de tu Servlet es reutilizable.

      Eliminar
    7. Ya ya, jeje, perdón. Ya he utilizado la solución del fileDownloadActionListener y funciona. Es solo por documentar posibles caminos.

      Eliminar
    8. Ok me alegro de que te funcionase, para cualquier cosa más aquí estoy :).

      Eliminar
    9. Buenas Daniel, la descarga del pdf funciona perfectamente. El problema es que tengo dos botones en el portlet, cada uno descarga un pdf distinto. Veo en las trazas que apunta en cada descarga a un pdf distinto, pero sigue descargando el primero. Se queda cacheado. Cómo puedo solucionar este tema de la cache desde el método del managedbean que me ha proporcionado el fileDownloadActionListener??

      Muchas gracias.

      Eliminar
    10. Hola.

      ¿Podrías pegar el fragmento de código de los dos botones que invocan el af:fileDownloadActionListener?.

      ¿Estos botones estan en una Page Template?.

      En el código del método asociado al af:fileDownloadActionListener tienes tanto un flush del OutputStream como un context.responseComplete() del contexto de JSF?.

      Eliminar
    11. Este comentario ha sido eliminado por el autor.

      Eliminar
    12. ManagedBean:

      try {
      //// obtain Database Conection from Weblogic Data Source
      InitialContext initialContext = new InitialContext();
      DataSource ds =
      (DataSource)initialContext.lookup("jdbc/EstablecimientosDS"); //definido en el web.xml
      Connection conn = ds.getConnection();



      log.log(Level.SEVERE,
      "RUTA DEL JASPER: " + rutaCarpeta + "RPT-Informe-situacion.jasper");
      InputStream jasper =
      new FileInputStream(rutaCarpeta + "RPT-Informe-situacion.jasper");
      parameters.put("SUBREPORT_DIR", rutaCarpeta);
      log.log(Level.SEVERE, "fillReport...");
      JasperPrint print =
      JasperFillManager.fillReport(jasper, parameters, conn);

      ///// For printing report as PDF file ////////
      ByteArrayOutputStream byteArrayOutputStream =
      new ByteArrayOutputStream();
      JasperExportManager.exportReportToPdfStream(print,
      byteArrayOutputStream);
      log.log(Level.SEVERE, "EXPORTREPORTTOPDFSTREAM...");
      byteArrayOutputStream.writeTo(outputStream);
      byteArrayOutputStream.flush();
      byteArrayOutputStream.close();
      PortletResponse response =(PortletResponse)facesContext.getExternalContext().getResponse();
      response.addProperty("Cache-Control", "no-cache");
      facesContext.getExternalContext().setResponse(response);
      facesContext.getResponseComplete();
      } catch (Exception e) {
      log.log(Level.SEVERE, "Error al generar el informe...", e);
      }finally{
      outputStream.flush();
      outputStream.close();
      }

      Eliminar
    13. En jspx:

      Es un showDetail con un panelGroup, y dentro de éste hay dos botones, cada uno con su FilaDownloadActionListener.

      Cada FileDownloadActionListener apunta a method distinto.

      Eliminar
    14. He intentado reconstruir el escenario que me planteas.

      He desarrollado un ADF Portlet con una view.jspx en la que incluyo un pequeño "layout" con 2 botones que llaman a un af:fileDownloadActionListener

      Consumiendo este Portlet desde una WebCenter Portal Application no he tenido ningún problema para que cada botón descarge su documento asociado.

      ¿Tus botones de descarga se hallan en una Page Template o una Page?.

      ¿Los componentes de Layout de engloban a los botones tienen la propiedad partialSubmit a "false"?.

      Realiza una prueba poniendo antes del af:fileDownloadActionListener un af:resetActionListener a ver si sigue descargandote cada fichero por su lado.

      Un saludo.

      Eliminar
  4. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  5. Buenas Daniel, a ver si me puedes echar un cable. Tengo un portlet desplegado en webcenter. Este portlet ha sido creado con el stándar JSR168. Una vez añadido este Portlet a un portal, ¿cómo puedo recoger de la sessión del portal un objeto de tipo "usuarioInteliturBean" que contiene esta session?.

    Lo que he hecho por ahora es dentro de mi archivo portlet.xml he cambiado en la etiqueta para que instancie mi clase, y será mi clase la que extienda de ADFBridgePortlet.

    He sobreescrito el método render(RenderRequest render, RenderResponse response).

    En este método hago lo siguiente:

    PortletSession ps = request.getPortletSession();
    UsuarioInteliturBean usuarioIntelitur =
    (UsuarioInteliturBean)ps.getAttribute("user");

    Pero me está recuperando un usuarioIntelitur nulo.

    ¿Es correcta la forma de recuperar este objeto de la session?
    ¿Si es correcta, puede ser que la session que estoy recuperando no sea la del navegador y sí la del propio portlet?, si fuera así, como podría acceder a la session del navegador desde el portlet, he probado con ADFContext.getCurrentInstance().getExternalContext().getSession(true) y lo que me pilla es un objeto PortletSession.


    A ver si puedes echarme una mano. Muchas gracias de antemano.

    ResponderEliminar
    Respuestas
    1. Hola Barbasco.

      Los portlets son consumidos mediante WSRP desde WebCenter y no en contenedor como otros gestores de portales.

      Además, como indicas son Portlets JSR-168 por lo que la "inter-portlet communication" no te vale (sería necesario JSR-286).

      Registra parámetros de entrada al portlet y cuando añadas el mismo mediante Oracle Composer, configura los valores que tomarán cada parámetro mediante EL Expressions. No podrás enviar un "bean" entero.

      Un saludo.

      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar
    3. Además, comentarte que la Session que estas recogiendo con ADFContext.getCurrentInstance().getExternalContext().getSession(true) no tiene nada que ver con la sesión del Portal puesto como te comenté son Portlets que se consumen de manera remota

      Eliminar
  6. Buenas Daniel, no sé si recordarás que estuviste ayudándome a realizar descargas de pdf desde un portlet. Al final funcionó utilizando el componente af:fileDownloadActionListener. El problema es que en el mismo portlet tengo una jspx que contiene dos fileDownloadActionListener. Cada uno de ellos provoca la descarga de un pdf distinto, cada uno con un nombre distino (nombre_+hora_min_seg). Cada uno de esto archivos una vez se generan y se descargan son eliminados para evitar cacheos. Pero aquí está el problema: si descargo primero un pdf (pdf1), ya aunque intente descargar el otro(pdf2), siempre se descarga el primero. Se queda como cacheado. En local a mi me funciona correctamente, es cuando despliego la aplicación como portlet y es consumida por webcenter, cuando se produce este problema. Puedes echarme un cable??

    Muchas gracias.

    ResponderEliminar
  7. Actualmente los botones están en un panelTabbed, aquí te adjunto un ejemplo de uno de ellos:

    af:showDetailItem text="Informe Certificado" id="sdi44"
    inlineStyle="width:903px;border-right:solid 1px #CDCDCC;border-left:solid 1px #CDCDCC;border-bottom:solid 1px #CDCDCC;"
    visible="#{!pageFlowScope.permisosBean.noPuedeLeer}"
    shortDesc="Sección dedicada a visualizar informe Certificado."
    af:panelGroupLayout id="pgl84" layout="vertical"
    af:commandButton text="Certificado de participación"
    id="commandLink14"
    disabled="#{pageFlowScope.permisosBean.noPuedeModificar}"
    "

    ResponderEliminar
    Respuestas
    1. Tengo que hacer una prueba de concepto entera para ver que te puede estar pasando. El comportamiento que me cuentas es extraño. En cuanto tenga un ejemplo simple para compartirte lo publicaré en el Blog.

      Eliminar
    2. Gracias Danile, espero tu respuesta. Un saludo.

      Eliminar