Saturday, June 25, 2011

JSF inter-portlet communication with Oracle WebCenter

Author: Alexander Rudat

Info: This article was migrated from the old blog!

Introduction
One of the most mysterious topics of the portal world is inter-portlet communication.
In the first portlet standard (
JSR 168), it was not specified how portlets communicate with each other. Every portal vendor had to implement his own solution.

Now with
WSRP 2.0 and JSR 286 (second portlet standard), there is a standard based mechanism for inter-portlet communication.

This blog entry shows how to communicate with ADF task flows in a portal environment like Oracle WebCenter.


Overview of the technologies / products used in the article:

Lets have a first look at the JSF Portlet Bridge:
The Oracle JSF Portlet Bridge enables application developers to expose their existing JSF applications, and Oracle ADF applications and task flows as JSR 168 portlets. The Bridge is based on and conforms to JSR 301. JSR 301 is the standards effort to define the functionality for the Portlet 1.0 Bridge for JavaServer Faces. More information is available at:
http://www.jcp.org/en/jsr/detail?id=301

Implementation of the portlets:

  1. Create a new Fusion Web Application (ADF) and name it PortletBridgeApplication
  2. Create the following Java Classes (package hr) in the ViewController:
    Department.java

    DepartmentBean.java

    Employee.java

    EmployeesBean.java

  3. In the Application Navigator, right-click DepartmentBean.java and choose Create Data Control
  4. The same with EmployeesBean.java (right-click choose Create Data Control)
  5. Create a Bounded Task Flow (with Page Fragments) and name it department
  6. In the Component Palette, select View from the list of activities, drag it onto department.xml and name it depart.
  7. Create a JSF Page Fragment named department.jsff when double-click the view.
  8. Drag the deptno from DepartmentBean data control into the department.jsff and create a ADF Input Field w/Label
  9. Drag the selectDepartmentString() from DepartmentBean data control under the ADF Input Filed Lable and create a ADF Button from the context menu.
  10. Go to Page Definition of department.jsff and into the selectDepartmentString() in the structure windows
  11. Insert a new component "events" in selectDepartmentString()
  12. Inside the events, create a new event from context menu and name it DepartmentSelectedEvent
  13. Create a new Bounded Task Flow (with Page Fragments) and name it employees
  14. In the Component Palette, select View from the list of activities, drag it onto department.xml and name it emp.
  15. Create a JSF Page Fragment named employees.jsff when double-click the view.
  16. Drag the getEmployees(String) method from EmployeesBean data control into the employees.jsff and create a ADF Button
    Note: Adding the button to the page is a simple way of creating a methodAction binding. As it is not required, you can remove the button from the code after the binding has been created.
  17. Remove the created Button in the source code view. It was only create for the method action binding!
  18. Drag the getEmployees(String) method from EmployeesBean data control into the employees.jsff and create a ADF Read-only Table
  19. Add a managed-bean entry in the
    employees.xml
  20. Create an input-parameter-definition entry and map the value of the parameter to the appropriate EmployeesBean method to store this value.
    Note: This is needed so that the task flow can consume WSRP navigational parameters when it is exposed as a portlet. When you turn this task flow into a portlet, the task flow parameter is converted into a portlet parameter.
  21. Now let's create the portlets from the the task flows:
    In the Application Navigator, under the Page Flows node, right-click the department task flow and choose Create Portlet Entry.
  22. In the Create Portlet Entry dialog, you can accept the default values for the name, title, and description fields, but ensure that you select the "Create navigation parameters for events"
  23. Right-click the employees task flow and choose also Create Portlet Entry and accept default as in step 22.
  24. On the created portlet.xml in the WEB-INF folder choose Run (Right-click)
    The default browser will show the following WSRP Producer Test Page
    (URL: http://127.0.0.1:7101/PortletBridgeApplication/info)

    WSRPPortletProducer

Consuming the JSF portlets:


  1. Create a new WebCenter Application and name it PortletBridgeConsumerApplication
  2. Create an new JSF page and name it PortletsRaisingEvents.jspx.
  3. Register the new WSRP Producer in the Application Resources panel and name it PortletBridgeTestProducer. On the Specify Connection Details page, in the WSDL URL field, enter the URL from Step 24 (http://127.0.0.1:7101/PortletBridgeApplication/info).
  4. Select the department portlet and drag it onto the PortletsRaisingEvents page.
  5. Select the employees portlet and drag it onto the page, just below the department portlet.
  6. Go to the page definition of the
    PortletsRaisingEventsPageDef.xml

    In the source code you can see an entry for department portlet that includes the event that you defined for the task flow. This event is raised whenever the underlying task flow raises the event.
    You can also see an entry for the employees portlet that includes the parameter that you defined for the task flow. This is used to pass data from anywhere on the page back through the portlet to the task flow.
    The page definition also includes a variable iterator that defines a page variable that was created because a portlet with navigational parameters was placed on the page. Portlets or components on the page that do not create ADFm events can pass context to portlets using this page variable.
  7. Add a default value for the page variable:
    <variableIterator id="variables">
       <variable Name="EmployeesPortlet1_1_deptno" Type="java.lang.Object
                 DefaultValue="${'20'}"/>
    </variableIterator>
  8. In the Structure panel, right-click PortletsRaisingEventsPageDef and choose Edit Event Map.
  9. In the Event Map Editor dialog, click the Add a New Event Entry icon.
  10. In the Add New EventMap Entry dialog, in the Producer field, drill down to select DepartmentPortlet1_1.
  11. In the Event Name field, make sure DepartmentSelectedEvent is selected.
  12. In the Consumer field, drill down to select EmployeesPortlet1_1.
  13. In the Consumer Params section, click the Add Consumer Parameter icon.
  14. In the Param Name field, enter deptno.
  15. In the Param Value field, enter ${payLoad}.
    Note: No payload or a null payload is propagated across the wire from the event producer portlet to the event consumer as an empty string. If the consumer must differentiate between an empty string and null payload, you can encode the null value in the payload in the event producer. The event consumer must also look for this custom encoding to detect the null payload.

    EventMapEntry.jpg


  16. In the PortletsRaisingEvents page, select the employees portlet.
  17. In the Property Inspector, expand the Common tab if necessary, and in the PartialTriggers field, enter portlet1 (the ID of the department portlet).
  18. This makes sure that the employees portlet refreshes to reflect any changes made in the department portlet (portlet1).
  19. Run the PortletsRaisingEvents.jspx and test the inter-portlet communication

Resources:

Download the full application:

oracle-jsf-inter-portlet.7z

2 comments:

  1. hi,

    i downloaded the code. I am getting this error.

    oracle.portlet.producer.container.ContainerObjectNotFoundException: Object named "registration" could not be found in the persistent store.

    what is problem

    ReplyDelete
  2. Hi there,

    this article was written with WebCenter 11.1.1.2 version. Since then a lot changed in WebCenter. I never tried this with the current 11.1.1.6 version maybe is time to do it. So unfortunately I cannot give you answer now but when I have some time I will have a look with up to date version.

    ReplyDelete