Inside WSRP
Pages: 1, 2, 3, 4, 5

Submitting a Form

Let's now see what happens when a user fills out and submits the form in the search portlet. Since the portlet is remote, the Consumer does the following to communicate the user's request to the Producer:

  • The Consumer extracts all parameters from the incoming HTTP request. These parameters include all the query parameters and form parameters.
  • The Consumer sends a performBlockingInteraction request to the Producer.

Here is a sample performBlockingInteraction request.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <urn:performBlockingInteraction xmlns:urn="urn:oasis:names:tc:wsrp:v1:types">
         <urn:registrationContext xsi:nil="true" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <urn:portletContext>
            <urn:portletHandle>search</urn:portletHandle>
         </urn:portletContext>
         <urn:runtimeContext>
            <urn:userAuthentication>wsrp:none</urn:userAuthentication>
            <urn:portletInstanceKey>search_1</urn:portletInstanceKey>
            <urn:namespacePrefix>search_1</urn:namespacePrefix>
            <urn:sessionID>
            B9ZVFSbYrxv74C8pnsyspSp2hW1ZnnXkPvzXHxrX3kgTbTQ0Jp4C!-1979539005
            </urn:sessionID>
         </urn:runtimeContext>
         <urn:userContext xsi:nil="true" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <urn:markupParams>
            <urn:secureClientCommunication>false</urn:secureClientCommunication>
            <urn:locales>en-US</urn:locales>
            <urn:mimeTypes>text/html</urn:mimeTypes>
            <urn:mode>wsrp:view</urn:mode>
            <urn:windowState>wsrp:normal</urn:windowState>
            <urn:clientData>
               <urn:userAgent>
               Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 
                  .NET CLR 1.1.4322; FDM)
               </urn:userAgent>
            </urn:clientData>
            <urn:navigationalState/>            
            <urn:markupCharacterSets>UTF-8</urn:markupCharacterSets>
         </urn:markupParams>
        
                        
 <urn:interactionParams>
            <urn:portletStateChange>readOnly</urn:portletStateChange>
            <urn:interactionState>_action=%2FSearch%2Fsearch</urn:interactionState>
            <urn:formParameters name="search_1{actionForm.lastName}">
               <urn:value>Allamaraju</urn:value>
            </urn:formParameters>
            <urn:formParameters name="search_1{actionForm.firstName}">
               <urn:value>Subbu</urn:value>
            </urn:formParameters>
         </urn:interactionParams>
      </urn:performBlockingInteraction>
   </soapenv:Body>
</soapenv:Envelope>
                      

In this request, the most important thing to notice is the interactionParams element. This element encapsulates the user's request for the portlet and contains the following:

  • A portletStateChange element indicates whether the portlet or the Producer is allowed to make changes to the portlet's persistent state. In the case of WebLogic Portal Producer, this value indicates whether the portlet is allowed to change the portlet's preferences. I will discuss using portlets preferences with remote portlets in greater detail later in this article.

  • The interactionState element contains the state of the user interaction. For Page Flow portlets, WebLogic Portal Producer uses this element to encapsulate the Page Flow action that must be executed. If you refer back to the getMarkupResponse message, you will notice that the WebLogic Portal Producer inserted this data in the form's action URL.

  • The formParameters elements include the form parameters submitted by the user.

When the WebLogic Portal Producer receives this request, the producer takes the following steps:

  • Based on the portletHandle, the Producer identifies the corresponding portlet.

  • The Producer decodes the interactionState element to find out the Page Flow action to be executed. In this case, it is the search action.

  • The Producer creates request/response wrappers again to mimic a web container environment and invokes the Page Flow's action. The Page Flow can now access the form parameters from this HTTP request.

  • Upon invoking the Page Flow's action, the Producer obtains the value of the next JSP to be displayed. In this case, it is the results.jsp.

At this time, as per the WSRP protocol, the Producer has two choices:

  • Create a performBlockingInteractionResponse and return.
  • Invoke the portlet's results.jsp and include the markup in the performBlockingResponse.

In the first case, the Producer returns the following response.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <urn:performBlockingInteractionResponse 
       xmlns:urn="urn:oasis:names:tc:wsrp:v1:types">
         <urn:updateResponse>
             
                        
<urn:navigationalState>_action=%2FSearch%2Fsearch&_next=/Search/results.jsp
               &_action=/Search/search&search_1{actionForm.lastName}=Allamaraju
               &search_1{actionForm.firstName}=Subbu</urn:navigationalState>
         </urn:updateResponse>         
      </urn:performBlockingInteractionResponse>
   </soapenv:Body>
</soapenv:Envelope>
                      

In the latter case, the Producer includes a MarkupContext element with the portlet's markup.

It is important to understand these two choices because portlets deployed in a local portal do not necessarily see the difference. To understand why WSRP specifies two requests with regard to getMarkup and performBlockingInteraction and what these requests mean to portlets, let's look into the above performBlockingInteractionResponse.

This response has a navigationalState element whose value includes the state of the portlet after processing the performBlockingInteraction request with the user's input. The actual value of this element varies from Producer to Producer. For Page Flow portlets, WebLogic Portal Producer uses this element to include the action that was executed, the form parameters that were used for the action, and the JSP that must be shown to the user.

Using this navigationalState, the Producer can render the portlet at any time in future. For example, let's assume that the portal page has another portlet. After viewing the search results, the user may start working with the second portlet. While the user is working with the second portlet, as long as that second portlet is not maximized, the user expects that portal to display the search results in the search portlet. To present the search results, the Consumer must be able to ask the Producer to render the portlet with the same content. That is, the Producer must be able to render a portlet without an interaction any number of times, and at any time. This is "interaction-free rendering," and portlets must be prepared for interaction-free rendering.

To allow interaction-free rendering, WSRP defines the following protocol:

  • Consumers use the performBlockingInteraction request to send user interactions to the Producer. The Producer includes the current state of the portlet as navigationalState in the response.

  • Consumers use the getMarkup request to ask the Producer to return a portlet's markup. If the Producer previously returned navigationalState, the Consumer can supply it with the getMarkup request, so that the Producer can render the portlet with that state.

The WSRP 1.0 specification calls this model the two-step protocol. In the current example, this two-protocol translates to the following:

  • The Consumer sends a getMarkup request to the Producer without the navigationalState. The Producer then renders the index.jsp of the search portlet.

  • When the user submits a form, the Consumer sends a performBlockingInteraction request to the Producer. In response, the Producer returns the next page to be displayed as navigationalState.

  • Whenever the Consumer wants to display the portlet, the Consumer sends a getMarkup request with the current navigationalState. Using this state, the Producer renders the results.jsp of the Page Flow portlet.

Of these, the third step can happen any number of times without any user interaction. Here is a getMarkup request with the current navigationalState.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <urn:getMarkup xmlns:urn="urn:oasis:names:tc:wsrp:v1:types">
         <urn:registrationContext xsi:nil="true" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <urn:portletContext>
            <urn:portletHandle>search</urn:portletHandle>
         </urn:portletContext>
         <urn:runtimeContext>
            <!-- Snip -->
         <urn:userContext xsi:nil="true" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
         <urn:markupParams>
            <urn:secureClientCommunication>false</urn:secureClientCommunication>
            <urn:locales>en-US</urn:locales>
            <urn:mimeTypes>text/html</urn:mimeTypes>
            <urn:mode>wsrp:view</urn:mode>
            <urn:windowState>wsrp:normal</urn:windowState>
            <urn:clientData>
               <urn:userAgent>
               Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 
                  .NET CLR 1.1.4322; FDM)
               </urn:userAgent>

            </urn:clientData>
  
                        
           <urn:navigationalState>_action=%2FSearch%2Fsearch&_next=/Search/results.jsp
               &_action=/Search/search&search_1{actionForm.lastName}=Allamaraju
               &search_1{actionForm.firstName}=Subbu</urn:navigationalState>
            <urn:markupCharacterSets>UTF-8</urn:markupCharacterSets>
         </urn:markupParams>
      </urn:getMarkup>
   </soapenv:Body>
</soapenv:Envelope>
                      

The following sequence diagram summarizes this rendering model.

Interaction-free rendering
Figure 2. Interaction-free rendering

This diagram shows the request/response messages from the Consumer to the Producer, and how WebLogic Portal Producer invokes the search portlet. You might wonder why the Consumer should send another getMarkup request to the Producer to get the portlet's markup. As an optimization, WSRP allows Producers to return markup within a performBlockingInteractionResponse message, letting Consumers avoid the extra roundtrip. It is up to the Consumer to decide whether to use the markup returned or send a new getMarkup request. WebLogic Portal Consumer and Producer support this optimization.

This interaction-free rendering is not only reserved for remote portlets. WebLogic Portal uses the same approach for local portlets as well. If you are familiar with the Java Portlet API, you will notice that the javax.portlet.Portlet interface reflects this model. The render parameters in the Java Portlet API correspond to the navigationalState.

What does this interaction-free rendering means for portlets?

  • The Consumer may invoke the portlet at anytime, and the portlet must be prepared to render its content when invoked by the Consumer.

  • The Consumer may not render the portlet immediately after executing an action. So, the portlet cannot assume that the action processing and subsequent rendering occur within the same request. Accordingly, if you add request attributes during action processing, those request attributes may not be available for your portlets during rendering.

Page Flow runtime makes some exceptions for request attributes. When you place a request attribute during an action, the Page Flow runtime stores the attribute in the user's HTTP session and will make it available to the Page Flow while including the next Page Flow JSP. The same is the case for Struts portlets but not for other types of portlets and backing files used on those portlets.

Tip: If you want any state to be carried forward from action processing to rendering, you can place the data in the HTTP session on the Producer side. Alternatively, you can implement a custom data transport.

Note that in the above example, I assumed that caching is not enabled on the remote portlet by the Consumer. If you enable caching on a remote portlet, the WebLogic Portal Consumer will not send a request to get the portlet's markup unless the user directly interacts with the search portlet.

The WSRP protocol places certain restrictions on what can be done during a getMarkup request.

  • During a getMarkup request, the Producer is not allowed to change the portlet's persistent state. For WebLogic Portal Producer, this means that the portlet cannot change its preferences. If you consider the fact that every portal page refresh could cause a getMarkup request, you will quickly notice that changing portlet preferences every time a portlet is rendered can cause undesirable database changes. WSRP allows Producers to change portlet's persistent state (that is, portlet preferences) under certain circumstances as discussed later in this article.

  • During a getMarkup request, the Producer is not allowed to change the portlet's mode or window state. This means that portlets cannot use any WebLogic Portal APIs to change a portlet's mode or window state. WSRP allows Producers to make these changes during performBlockingInteraction.

These restrictions are not specific to WSRP. The Java Portlet API has similar restrictions, and WebLogic Portal enforces these for all portlets, whether local or remote.

In this discussion, I have not included requests/responses from WebLogic Portal Consumer to the WebLogic Portal Producer to support inter-portlet communication. To support inter-portlet communication, WebLogic Portal extends the WSRP 1.0 protocol and uses a handleEvents request to transport events from the Consumer to the Producer. The handleEvents request is similar to the performBlockingInteraction request as far as request/response flow is considered. For example, request attributes added to the request during event handling may not be available to portlets during rendering. For more details on the inter-portlet communication model, refer to WebLogic Portal documentation.

Pages: 1, 2, 3, 4, 5

Next Page ยป