Cooperative Portlets

 


  1. Cooperative portlet samples
  2. Registering properties and actions
  3. Generating property values
  4. Receiving property values
  5. Advanced programmatic APIs for accessing Property Broker
  6. Additional advanced considerations
  7. Packaging and deployment considerations
  8. Additional considerations for compiling
  9. Configure pbshipexample.war

 

Cooperative portlet samples

WebSphere Portal includes some sample portlet applications that interact with each other through the property broker.

  • Shipping demo

    This demonstrates the declarative programming techniques that enable portlet interaction through the property broker. In the case of the IBM portlets only, this includes Click-to-Action. The Shipping demo is composed of five portlets. All five portlets must be placed on the same page to exploit the full cooperative features.

    JSR 168 compliant

    pbjsrshipexample.war Shipping demo using the JSR 168 container
    pbjsrstrutsexample.war Shipping demo using the JSR 168 container and struts

    IBM only

    pbshipexample.war Shipping demo using the IBM container
    pbstrutsexample.war Shipping demo using the IBM container and struts

    Demonstrates the capability to save property transfers as wires between portlets when users use the Ctrl-click combination on the icon or image map.

    pbdestexample.war Destination Guide demo

    Includes the Tourist Information, Weather, and Map portlets. The Map portlet uses the advanced programming features of the property broker to display the Click-to-Action menus through a client-side image map rather than the standard Click-to-Action icon. This example demonstrates programmatic registration rather than using WSDL and also illustrates the use of the PropertyListener interface.

    The samples can be found in the wp_root/installableApps directory. Source is included in the WAR file. Subsequent updates to these samples are available from the portlet catalog by searching for navcode 1WP10004N.

    For more information, see Cooperative portlet samples.

     

    Registering properties and actions

     

    JSR 168 compliant and IBM portlets: Declarative (WSDL)

    The declarative method can be used with either JSR compliant portlets or IBM portlets, and is the only registration implementation supported for JSR compliant portlets. WSDL with some custom extensions is a supported format for registering portlet properties using the declarative method. The syntax used is standard WSDL, with the custom extensions following a syntax permitted by WSDL. Some of the extensions are introduced specifically for cooperative portlets. These extensions follow the extension rules allowed by the base WSDL schema.

    For more information about the cooperative portlet extensions, see WSDL reference for cooperative portlets.

    The WSDL file should be included in your WAR. Action, parameter, and property information is obtained by parsing the WSDL file. All actions, parameters, and properties registered in the WSDL file are owned by the portlet specified in the portlet.xml file.

    If the source portlet does not have any actions to expose as inter-portlet communication targets, but still wishes to register properties, a dummy action may be defined with input and output parameters. The declared input and output parameters cause the corresponding input and output properties to be registered. A potential side-effect of this approach may result in the action associated with input parameters appearing in Click-to-Action menus by default. This action would be invocable through any wires of which it is the target. To prevent this, set the attribute activeOnStartup to false.

    To see an example of a WSDL file for either JSR 168 compliant or IBM portlets, see the Generating property values and Receiving property values sections.

     

    IBM portlets only: Programmatic

    Registration of properties can be done programmatically only for IBM portlets. Properties can be registered programmatically using the registerProperties() method from the PropertyBrokerService interface. The following example shows the registerProperties() method from ClickMapPortlet.java.

    public void beginEventPhase PortletRequest(request) 
      {
        try
        {
          registerPropertiesIfNecessary(request);
        }
        catch (PropertyBrokerServiceException e)
        {
          log.text(Logger.ERROR, "beginEventPhase",
                   "Unable to register properties: nested exception is:",
                   e);
          return;
        }
     
       ...
       
      /*
       * Properties need to be registered only once, and affect all
       * portlet instances sharing the same portlet definition.
       */
      private void registerPropertiesIfNecessary PortletRequest(request) 
      throws PropertyBrokerServiceException {
        PortletSettings settings = request.getPortletSettings();
        Property[] properties = getPropertyBrokerService().getProperties(request, settings);
        if (properties == null || properties.length == 0)
        {
          PortletContext context = getPortletConfig().getContext();
          Locale[] locales = new Locale[] {Locale.US};
    
          //not registered, register now
          properties = new Property[2];
          //an input property
          properties[0] = PropertyFactory.createProperty(settings);
          properties[0].setName("newCity");
          ...
    
          //an output property
          properties[1] = PropertyFactory.createProperty(settings);
          properties[1].setName("outCity");
          ...
    
          getPropertyBrokerService().registerProperties(request, settings, properties);
        }
     
      ... 
      }  
    

     

    Generating property values

    Portlets actions which can accept data transferred using the property broker may be declared in a WSDL file. For IBM portlets only, the alternative is to register the actions programmatically. The syntax used is standard WSDL. A concrete implementation of the abstract operation definitions may be specified using bindings. The binding thus includes the protocol and the data format to be used for invoking the operations - in essence, all the information an invoking program would need to invoke a concrete implementation of the operations.

    Certain restrictions must be followed by the operation declarations for cooperative portlets. At present, only a single input parameter is allowed for each operation. The types associated with parameters must be declared using XSD (see the XSD specification).

    A custom binding section must also be used to specify how to invoke the declared operations on the implementing portlet. The binding section maps each abstract operation to an action on the portlet. For each operation, the portlet action name must be provided. For each operation parameter, the action parameter name must be provided. Further, an attribute may be used to specify where the parameter will be bound. Choices are request parameter, request attribute, session attribute, action attribute (IBM only; The action attribute is deprecated), and and render parameter (JSR compliant only). (The action attribute is deprecated.) Reasonable defaults apply for most attributes.

    • For JSR compliant portlets

      A target portlet's processAction() method is used to receive property change notifications. A WSDL file is provided that enumerates the properties and actions associated with a portlet. The JSR compliant WSDL file must specify the type attribute of the action element with a value of standard. If the portlet is implemented using the struts framework, change the value of the type attribute to standard-struts.

      The code for the target portlet class must meet the following requirements:

      • The action must be implemented either as a portlet action or a Struts action. Portlet actions must accept a single parameter. The parameter may appear as a request parameter, a request attribute, a session attribute, or a render parameter, as specified in the action declaration or registration.

      • The actionNameParameter attribute must be specified for JSR portlet actions, and indicates the name of a request parameter which will be used to carry the name of the action when it is invoked. This is important for JSR portlets as actions in this case are not explicitly associated with names (this is different from the IBM portlet case), and the application must use an additional parameter to identify the actual logic to execute. It is recommended, but not required, that the actionNameParameter value be set to the same value for all actions which a portlet declares.

      The following is a sample of the processAction() method of OrderDetailPortlet.java and portlet's corresponding WSDL file OrderDetail.wsdl. Both of these files can be found in the in the Shipping demo. This portlet accepts the ORDER_ID parameter in its processAction() method. The parameter ORDER_ID corresponds to an input parameter in the binding section of the portlet's WSDL file.

      processAction() example from OrderDetailPortlet.java:

        ...
      
         private static final String PREFIX = "";
         public static final String ACTION_NAME = PREFIX + "actionName";
         public static final String ORDER_DETAILS = PREFIX + "orderDetails";
         public static final String ORDER_ID_ENTRY = PREFIX + "orderIdEntry";
         public static final String ORDER_ID = PREFIX + "orderId";
         public static final String ORDER_DETAIL = PREFIX + "orderDetail";
         public static final String TRACKING_ID = PREFIX + "trackingId";
         public static final String PBSERVICE = PREFIX + "pbService";
            
        ...
      
         public void processAction (ActionRequest request, ActionResponse response) 
         {
                  String actionName = request.getParameter("ACTION_NAME");
                  if (actionName == null) {
                          actionName = "";
                  }
      
                  //An action causes the state to be modified
                  ShippingUtils.setLastModified(request);
      
                  getPortletContext().log("OrderDetail processAction called");
      
                  if (actionName.equals(ORDER_DETAILS)) {
                          request.getPortletSession().setAttribute(ACTION_NAME, ORDER_DETAILS);
                          request.getPortletSession().setAttribute(ORDER_ID, request.getParameter(ORDER_ID));
      
                          //We do this as tracking id is an out param in the init()
                          //We write the tracking id in the request so it can be published by
                          //the broker in the same event cycle
                          String orderId = (String) request.getPortletSession().getAttribute(ORDER_ID);
                          OrderDetail od = ShippingDB.getOrderDetail(request.getParameter(ORDER_ID));
                          if (od != null) {
                                  request.getPortletSession().setAttribute(ORDER_DETAIL, od);
                                  request.setAttribute(TRACKING_ID, od.getTrackingId());
                          }
      
                  } else if (actionName.equals(ORDER_ID_ENTRY)) {
                          request.getPortletSession().setAttribute(ACTION_NAME, ORDER_ID_ENTRY);
                  }
          }
      
        ...
      

      WSDL file example from OrderDetail.wsdl:

      ...
      <definitions name="OrderDetail_Service"
        targetNamespace="http://www.ibm.com/wps/c2a/examples/shipping"
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:portlet="http://www.ibm.com/wps/c2a"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:tns="http://www.ibm.com/wps/c2a/examples/shipping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        
        ...
        
        <types>
        <xsd:schema targetNamespace="http://www.ibm.com/wps/c2a/examples/shipping">
          <xsd:simpleType name="OrderIDType">
            <xsd:restriction base="xsd:string">
            </xsd:restriction>
          </xsd:simpleType>
         ...
        </types>
      
      ...
      <message name="OrderDetailsRequest">
        <part name="order_Id" type="tns:OrderIDType"/>
      </message>
      
      ...
      <binding
          name="OrderDetailBinding"
            type="tns:OrderDetail_Service">
        <portlet:binding/>
        <operation name="order_Detail">
          <portlet:action name="orderDetails" type="standard" caption="Order.Details" description="Get.details.for.specified.order.id"
          actionNameParameter="ACTION_NAME"/>
          <input>
            <portlet:param name="orderId" partname="order_Id" caption="order.id"/>
          </input>
          <output>
            <portlet:param name="trackingId" partname="tracking_Id" boundTo="request-attribute" caption="tracking.id"/>
          </output>
        </operation>
      </binding>
      ...
      

    • For IBM portlets

      The code for the target portlet class must meet the following requirements:

      • The action must be implemented either as a portlet action or a Struts action. For portlet actions, use the simple action Strings rather than the deprecated DefaultPortletAction class.

      • Portlet actions must accept a single parameter. The parameter may appear as a request parameter, a request attribute, a session attribute, or an action attribute (deprecated), as specified in the action declaration or registration.

      The following shows the actionPerformed() method of the OrderDetailPortlet.java and the corresponding WSDL file OrderDetailC2A.wsdl. Both of these files can be found in the in the Shipping demo. This portlet accepts the ORDER_ID parameter in its actionPerformed() method. The parameter ORDER_ID corresponds to an input parameter in the binding section of the portlet's WSDL file.

      actionPerformed() example from OrderDetailPortlet.java:

      
        ...
      
       private static final String PREFIX = "";
          public static final String ACTION_NAME = PREFIX + "actionName";
          public static final String ORDER_DETAILS = PREFIX + "orderDetails";
          public static final String ORDER_ID_ENTRY = PREFIX + "orderIdEntry";
          public static final String ORDER_ID = PREFIX + "orderId";
          public static final String ORDER_DETAIL = PREFIX + "orderDetail";
          public static final String TRACKING_ID = PREFIX + "trackingId";
      
        ...
      
          public void actionPerformed (ActionEvent event) 
          {
       String actionName = event.getActionString();
      
              PortletRequest request = event.getRequest();
      
              //An action causes the state to be modified
              ShippingUtils.setLastModified(request);
      
         if( getPortletLog().isDebugEnabled() ) {
               getPortletLog().debug("OrderDetailActionListener - Action called");
         }
         
              if (actionName.equals(ORDER_DETAILS)) {
                  request.getPortletSession().setAttribute(ACTION_NAME, ORDER_DETAILS);
                  request.getPortletSession().setAttribute(ORDER_ID, request.getParameter(ORDER_ID));
      
           //We do this as tracking id is an out param in the C2A WSDL file
           //We write the tracking id in the request so it can be published by
           //the broker in the same event cycle
                  String orderId = (String) request.getPortletSession().getAttribute(ORDER_ID);
           OrderDetail od = ShippingDB.getOrderDetail(request.getParameter(ORDER_ID));
                  request.getPortletSession().setAttribute(ORDER_DETAIL, od);
           request.setAttribute(TRACKING_ID, od.getTrackingId());
      
              }  else if (actionName.equals(ORDER_ID_ENTRY)) {
                  request.getPortletSession().setAttribute(ACTION_NAME, ORDER_ID_ENTRY);
       }
          }
      ...
      

      WSDL file example from OrderDetail.wsdl:

      This WSDL file is the same as the WSDL file for the JSR 168 compliant example above except for the value of type set in the binding. One of the supported values for type for IBM portlets is simple.

      ...
        <binding
          name="OrderDetailBinding"
            type="tns:OrderDetail_Service">
        <portlet:binding/>
        <operation name="order_Detail">
          <portlet:action name="orderDetails" type="simple" caption="Order.Details" description="Get.details.for.specified.order.id"/>
          <input>
            <portlet:param name="orderId" partname="order_Id" caption="order.id"/>
          </input>
          <output>
            <portlet:param name="trackingId" partname="tracking_Id" boundTo="request-attribute" caption="tracking.id"/>
          </output>
        </operation>
      </binding>
      ...
      
      See the Registering portlet properties section for more information on registering properties.

     

    Receiving property values

    Unlike input parameters, you can declare any number of output parameters for a target portlet. Output parameters are used to allow the target to react to an action by transferring data to other portlets, creating a chained propagation that updates multiple portlets from a single action. (The propagation occurs only if a suitable wire is present.) If the portlet action changes or accesses other state variables as a result of the action, it may be appropriate to declare them as output parameters. The portlet programmer may need to distinguish portions of the data model for the portlet which could be of interest to other portlets. These are often appropriate candidates for output parameters. For example, as a consequence of executing an "Order Detail" action, a portlet may retrieve information which contains an associated tracking ID. Since this is a key which may potentially be of interest to other portlets, it may be declared as an output parameter.

    Instead of delivering property changes through portlet action invocations, changes may also be delivered using the setProperties() method of the PropertyListener interface. This can happen if the target end of the wire connects to a target property, rather than a target parameter. In this event, the property broker may deliver multiple property values in a single invocation of setProperties(). The same property may appear multiple times in the array passed. Also, setProperties() is only invoked during the event phase, and all property changes which the portlet is eligible to receive are guaranteed to be delivered by the end of the event phase (as indicated by the invocation of the endEventPhase() callback in the EventPhaseListener interface).

    The following example shows the setProperties() method from ClickMapPortlet.java. In this example, the input property newCity is received and passed to the ClickMapBean to set the CurrentCity property. However, no action is taken with CurrentCity. Instead, a new output property is created and passed to the broker using changedProperties(). Notice that the class must implement the PropertyListener interface.

    public class ClickMapPortlet extends PortletAdapter
           implements EventPhaseListener,
        PropertyListener
    {
    
    ...
    
      public void setProperties PortletRequest(request, PropertyValue[] properties) 
      {
        PortletSession session = request.getPortletSession();
        PortletSettings settings = request.getPortletSettings();
    
        ClickMapBean bean = (ClickMapBean) session.getAttribute("CLICK_MAP_BEAN");
    
        try
        {
          String newCity = null;
          for (int i = 0; i < properties.length; i++)
          {
            Property p = properties[i].getProperty();
            if (p.getName().equals("newCity"))
            {
              newCity = (String) properties[i].getValue();
            }
          }
          if (newCity != null)
          {
            String[] names =  { "City Name"};
            Object[] values = { newCity};
            if (bean != null)
            {
              bean.setCurrentCity(newCity);         
            }
            //republish so any wires using this portlet at the source
            //are triggered
            publishCity(request, newCity);
          }
        }
        catch (Throwable e)
        {
          log.text(Logger.ERROR, "setProperties",
                   "Unexpected exception", e);
    
        }
      }
    
    ...
    

     

    Advanced programmatic APIs for accessing Property Broker

    Some functionality can be achieved programmatically for JSR compliant and IBM portlets. These functionality is implemented using the methods listed here. For more details on these methods see the latest version of the Portlet API Javadoc available from the WebSphere Portal Product Documentation page.

     

    Programmatic approach available for both JSR compliant and IBM portlets

    Only the names and functions of the following methods are the same for both JSR compliant and IBM portlets. You cannot use a JSR compliant method on an IBM portlet, and you cannot use an IBM method on a JSR compliant portlet. These methods are grouped together only for documentation purposes.

    • Activation/Deactivation of Actions

      • Use activateAction() to explicitly activate an action that has been deactivated. This activates the action for the current session.

      • Use deactivateAction() to explicitly deactivate an action that is active. This deactivates the action for the current session. If actions are inactive, they will not be invoked as a result of wires being activated in the current session.

      Actions which are registered are active by default as soon as the portlet is initialized and is active. Actions may be explicitly specified to be inactive when the portlet is initialized. Such actions may be selectively activated in individual sessions by invoking the activateActions() method on the PropertyBrokerService interface. The corresponding deactivateActions() call may be made to deactivate actions activated earlier for the session. Only target actions which are active for the current session are invoked to receive property values published by source portlets or passed via user triggers. Actions which are active may be deactivated in the current session by issuing the corresponding deactivateActions() method call on the PropertyBrokerService interface. Deactivated actions are not invoked by the property broker and do not appear in Click-to-Action menus.

      Actions may be deactivated if the portlet needs to get into a certain state before activating the actions. In some cases, it may be appropriate to make the default behavior for certain actions to be inactive, so that they may be programmatically activated by the portlet when it reaches a certain state. This may be achieved by using the value "false" on the isActiveOnStartup attribute on the action element in the WSDL description, or by setting the corresponding property on the Action object if programmatic registration is used.

    • Wires
      • Use areWiresActive() to determine if a property is currently wired to active actions.
      • Use isWired() to determine if a property is wired.
      Note: These methods will not create wires. In order to create a wire for either a JSR compliant portlet or an IBM portlet, use the Portlet Wiring tool. You cannot wire a JSR compliant portlet to an IBM portlet. For IBM portlets using Click-to-Action, a wire can also be created within the portlet by holding CTRL while clicking on the Click-to-Action icon. However, the information from these methods may be used by the portlet that owns the property to surface additional visual elements, such as links, in its markup. This can in turn be used by end users to trigger wired actions. For information on configuring a wire see Wiring portlets section in Configure cooperative portlets.

     

    Programmatic approach available for only IBM portlets

    For IBM portlets only, registration of actions and properties can be done programmatically. See the Registering portlet properties section for more information on registering properties. To register actions, use the registerActions() method from the PropertyBrokerService interface. Each action must have a unique name. The actions are made available for invocation as the target of wires from other portlets. At this time, any properties associated with the actions which have not been registered earlier are automatically registered and any action registered earlier will be removed. Actions registered once are stored persistently as long as the portlet remains installed in the portal. To check if actions have already been registered using the getActions() method before invoking registerActions(). Actions registered are applicable for all instances of the calling portlet on all pages.

    For details on all available methods for programmatic implementation of IBM portlets, see the WebSphere Portal Product Documentation page.

     

    Additional advanced considerations

    Here are some advanced options for cooperative portlets.

    • Constant parameters <portlet:constant-param> For JSR 168 compliant portlets, these can only be specified using the WSDL file. For IBM portlets, constant parameters can be specified using WSDL or Java APIs. Use constant parameters to provide more information to the action on how it should execute.

      Use it like this: <portlet:constant-param name="defaultMonth" value="January"/> </portlet:constant-param>

    • Action-name parameter attribute (actionNameParameter="ACTION_NAME"): This action attribute is used by the property broker to define the action. This is important in JSR 168 compliant portlets because processAction() doesn't have any parameters that carry the action name. In JSR 168 compliant portlets, using the action-name parameter is the only way to determine what action was invoked.

      Use it like this: <portlet:action name="SHIPPINGORDERSordersForMonth" type="standard" caption="orders.for.month" description="get.orders.for.specified.month" actionNameParameter="ACTION_NAME">

     

    Packaging and deployment considerations

     

    Create the deployment descriptors

    A WAR must have a web.xml and a portlet.xml file in order to comply with J2EE specifications. For JSR compliant portlets only, web.xml only needs to contain servlet information, not portlet information. If the JSR 168 compliant portlet does not contain servlets, web.xml must still be present, though the content of the file will be empty. However, in an IBM portlet web.xml must contain both servlet and portlet information. The web.xml and portlet.xml files must be modified to enable portlet cooperation. modify web.xml to refer to the property broker classes. The servlet class entry should specify the com.ibm.wps.pb.wrapper.PortletWrapper class in the property broker.

    Sample JSR compliant web.xml file with empty content:

    This sample is from pbjsrsampleshipping.war.

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
      <web-app>
          <display-name>Shipping Portlets - Standard Version</display-name>
           <taglib id="TagLibRef_id">
               <taglib-uri>http://java.sun.com/portlet</taglib-uri>
               <taglib-location>tld/std-portlet.tld</taglib-location>
           </taglib>
      </web-app>
    

    Sample IBM web.xml file:

    This sample is from pbshipexample.war.

         
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
       <web-app id="ShippingPortletsC2ANew">
          <display-name>Shipping Portlets</display-name>
          <servlet id="OrderDetailC2A">
             <servlet-name>Order Detail</servlet-name>
             <servlet-class>com.ibm.wps.pb.wrapper.PortletWrapper</servlet-class>
      <init-param>
                 <param-name>c2a-application-portlet-class</param-name>
                 <param-value>com.ibm.wps.portlets.shipping.OrderDetailPortlet</param-value>
      </init-param>
             <load-on-startup>0</load-on-startup>
          </servlet>
          <servlet id="OrderMonthC2A">
             <servlet-name>Orders</servlet-name>
             <servlet-class>com.ibm.wps.pb.wrapper.PortletWrapper</servlet-class>
      <init-param>
                 <param-name>c2a-application-portlet-class</param-name>
                 <param-value>com.ibm.wps.portlets.shipping.OrderMonthPortlet</param-value>
      </init-param>
             <load-on-startup>0</load-on-startup>
          </servlet>
    
    ...
    
       <servlet-mapping id="OrderDetailMapping">
        <servlet-name>Order Detail</servlet-name>
        <url-pattern>/OrderDetail/*</url-pattern>
     </servlet-mapping>
     <servlet-mapping id="OrderMonthMapping">
             <servlet-name>Orders</servlet-name>
             <url-pattern>/Orders/*</url-pattern>
          </servlet-mapping>
    
    ...
    
      </web-app>
    

    The portlet.xml file must specify the location of the WSDL file associated with each portlet. To achieve this, modify portlet.xml to add a configuration parameter to each concrete portlet that exposes actions to the property broker through the WSDL file. For the IBM example portlet.xml file below, the configuration parameter, c2a-action-descriptor, must specify a URL that points to the WSDL file that declares actions. The configuration parameter, c2a-nls-file, must specify the base name of an NLS resource file containing the translated text corresponding to the captions and descriptions of actions and properties. This file may be packaged in the same WAR file, so a relative path may be used.

    Sample JSR 168 compliant portlet.xml file

    <?xml version="1.0"?>
    <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
    version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
    http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
        <portlet>
            <description xml:lang="en">Displays details for a particular order</description>
            <portlet-name>StandardOrderDetail</portlet-name>
            <display-name xml:lang="en">StandardOrderDetail</display-name>
            <portlet-class>com.ibm.wps.portlets.shipping.OrderDetailPortlet</portlet-class>
            <expiration-cache>3600</expiration-cache>
            <supports>
                <mime-type>text/html</mime-type>
            </supports>
            <supported-locale>en</supported-locale>
            <portlet-info>
                <title>Standard Order Detail</title>
                <short-title>SOD</short-title>
                <keywords>Property Broker, Click-to-Action, C2A, Cooperative Portlets</keywords>
            </portlet-info>
            <portlet-preferences>
                <preference>
                    <name>com.ibm.portal.propertybroker.wsdllocation</name>
                    <value>/wsdl/OrderDetail.wsdl</value>
                </preference>
                </portlet-preferences>
        <resource-bundle>nls.shipping</resource-bundle>
        <security-role-ref>
                <role-name>trustedUser</role-name>
       <role-link>auth-user</role-link>
            </security-role-ref>
        </portlet>
     
     ...
     
    </portlet-app>
    
    

    Sample IBM portlet.xml file

    <?xml version="1.0"?>
    <!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN" "portlet-1.1.dtd">
    <portlet-app-def>
        <portlet-app uid="com.ibm.wps.portlets.shippingc2a">
        <portlet-app-name>Shipping Application Demo - C2A Version</portlet-app-name>
        <portlet id="OrderDetailC2A" href="WEB-INF/web.xml#OrderDetailC2A">
            <portlet-name>OrderDetailC2A</portlet-name>
            <cache>
             <expires>3600</expires>
          <shared>YES</shared>
         </cache>
         <allows>
                <maximized/>
                <minimized/>
            </allows>
            <supports>
                <markup name="html">
                    <view output="fragment"/>
                </markup>
            </supports>
        </portlet>
    
        ...
    
        <concrete-portlet-app uid="concrete.com.ibm.wps.portlets.shippingc2a">
        <portlet-app-name>Shipping Application Demo - C2A Version</portlet-app-name>
        <concrete-portlet href="#OrderDetailC2A">
            <portlet-name>OrderDetailC2A</portlet-name>
            <default-locale>en</default-locale>
          <language locale="en">
             <title>Order Details</title>
             <title-short>OD</title-short>
             <description>Displays details for a particular order</description>
             <keywords>Property Broker, Click-to-Action, C2A, Cooperative Portlets</keywords>
          </language>
            <config-param>
               <param-name>c2a-action-descriptor</param-name>
               <param-value>/wsdl/OrderDetailC2A.wsdl</param-value>
            </config-param>
            <config-param>
               <param-name>c2a-nls-file</param-name>
               <param-value>nls.shippingc2a</param-value>
            </config-param>
        </concrete-portlet>
    
        ...
    
        </concrete-portlet-app>
    </portlet-app-def>
    

     

    WAR file considerations

    Once the code and deployment changes have been made for using the property broker, additional libraries and files must be packaged along with the application. After you package the WAR file, it is ready to be installed. Use the following table to package the files in the correct location.

    Portlet type File name Path Original location
    IBM portlet only pbportlet.jar /WEB-INF/lib wp_root/pb/lib
    IBM and

    JSR 168 compliant

    WSDL file relative to the root of the WAR file or an absolute URL  

     

    Additional considerations for compiling

    If you are using your own development environment, make sure to add the wp.propertybroker.standard.api.jar (for JSR 168 compliant portlets) or wp.propertybroker.legacy.api.jar (for IBM portlets) file to your class path. This JAR file can be found in the wp_root/shared/app directory. For other JAR file requirements, see Compiling java source.

     

    Configure pbshipexample.war

    Install pbshipexample.war

    1. Start WebSphere Portal if not already started

    2. Log into the portal using wpsadmin/wpsadmin

    3. Select the Administration node

    4. Select Portlet Management - > Web Modules from the Navigation menu

    5. Click Install button

    6. Select the browse button and navigate to C:\WebSphere\PortalServer\installableApps\pbshipexample.war file

    7. Click Open

    8. Click Next

    9. Click Next

    10. In the Install Web modules window, Click the Finish button. Make sure you are installing the Shipping Application.

     

    Add portlets to a page

    1. Click to...

      Portal User Interface | Manage Pages

    2. Select Unique Name in the search by: field and search for YourPage

    3. Click Edit Page Layout icon for desired page

    4. Add the following portlets to the page:
      1. Order
      2. Tracking Detail
      3. Customer Detail
      4. Order Detail
      5. Account Detail

    5. Click to...

      My Portal | YourPage

     

    Investigating Cooperative Portlets

    1. Click on the Click-to-Action icon next to an Order ID. Options appear: Account Detail, Order Detail, and Invoke All Actions.

    2. Click on Invoke All Actions

      Note: Lets see the results in Order Detail and Account Detail portlets based on the Order ID selected.

    3. In the Orders Portlet, click on the Click-to-Action icon next to a Status field for an Order ID. A Menu option of Send row to All should be displayed

    4. Click Send row to All. You will see the results in Order Detail, Account Detail, and Customer Detail portlets are shown based on the status of the Order ID selected.

    5. Click on the Click-to-Action icon next to the Tracking ID in the Order Details portlet. You will see a menu of options Routing detail and Tracking Detail.

    6. Click on Routing Detail. You will see the results of Routing Detail in Tracking Detail portlet shown.

      Note: Now we establish a wire connection between the Order Detail portlet and Tracking Detail portlet so that whenever the content displayed in Order Portlet is changed, the information can be propagated to the Tracking Details portlet.

    7. Holding the Ctrl key, Click on the Click-to-Action icon next to the Tracking ID in the Order Details portlet and Select Routing Detail.

    8. Click on Yes button to establish a wire connection between the two portlets.

    9. Now whenever there is a change in the Order Detail portlet the information is propagated to the Tracking Detail portlet.

    10. Click on the Click-to-Action icon next to a Status field for an Order ID. You will see a menu of option Send row to All. Click on Send row to All. You will notice that the information is propagated to all the portlets on the page.

     

    See also

    Home |

     

    WebSphere is a trademark of the IBM Corporation in the United States, other countries, or both.

     

    IBM is a trademark of the IBM Corporation in the United States, other countries, or both.