If you are on wsrp@lists.oasis-open.org list for committee members, send comments there. If you are not on that list, subscribe to wsrp-comment@lists.oasis-open.org list and send comments there. To subscribe, send an email message to wsrp-comment-request@lists.oasis-open.org with the word "subscribe" as the body of the message.
Copyright © 2004 OASIS Open, Inc. All Rights Reserved.
Web Services for Remote Portlets (WSRP) is a web services protocol for aggregating content and interactive web applications from remote sources. Web Services for Remote Portlets 1.0 Primer is a non-normative document intended to help interpret the WSRP 1.0 Specification [1] with usage scenarios and typical interactions that must happen to achieve such aggregation. There are numerous sources of high-level introductory information about WSRP 1.0, including the introductory section of the specification itself, and the WSRP White Paper [2]. If you are reading about WSRP for the first time, we encourage you to explore these resources before proceeding with the extended examples and explanations contained in this primer.
The guiding perspective on which WSRP specification was built should be of primary interest to potential implementers. This perspective is framed by the question of what problems WSRP is intended to solve. The specification's procedural approach addresses the following main areas:
WSRP builds on a few fundamental standards, most notably XML, SOAP and WSDL, while allowing for the implementation of evolving standards, to deliver a protocol rich in abstractions and operations that web service implementers and portlet Consumers require.
The WSRP specification uses the terms Producer and Consumer to describe parties implementing the specification.
The Producer is a web service that offers one or more portlets and implements various WSRP interfaces/operations. Depending on the implementation, a producer may offer just one portlet, or may provide a runtime (or a container) for deploying and managing several portlets.
The Consumer is a web service client that invokes producer-offered WSRP web services and provides an environment for users to interact with portlets offered by one or more such Producers.
You can use WSRP to implement a very broad range of portlet Producers and Consumers. However, in this primer, for the sake of simplicity, we use simpler examples. It is not our intention to address the entire range of problems that WSRP can solve, or to replace the material already in the specification. Therefore, when you uncover your own questions, and discover that any particular question is not discussed here, we suggest that you have a copy of the specification available for quick reference.
In this Primer, we use interactions between two parties, viz., P Inc (a WSRP Producer), and C Inc (a WSRP Consumer) to discuss various WSRP interfaces.
In the examples we will use, P Inc is a financial services company, providing services online to their customers and partners. C Inc is on online portal company, providing personalized collaboration, banking, and financial services. C Inc offers these services to end-users by subscription.
P Inc would like to host a number of applications including a web based portfolio management application. C Inc would like to offer this application to its end users via its portal pages.
In order to offer this portfolio management application to end users, C Inc and P Inc agree on the following:
This scenario captures some of the essentials of the WSRP 1.0 Specification. Instead of developing a proprietary application protocol to accomplish the above steps, P Inc and C Inc can agree to use WSRP as the protocol. In this scenario, P Inc is a WSRP Producer offering portlets, and C Inc is a WSRP Consumer consuming portlets and aggregating portlets for users to access aggregated portlet pages. The portfolio management application is a Portlet offered by the Producer.
Note: This version of the Primer will not address how C Inc may discover the web service end-point offered by P Inc.
To implement this scenario, P Inc and C Inc can use WSRP to define various interactions, with P Inc implementing the following required WSRP interfaces and operations:
getServiceDescription operation of this interface
to obtain this metadata in step (a) of the above scenario. getMarkup operation of this interface to obtain
the portlet's markup in steps (c) and (i), and invokes the performBlockingInteraction operation to
propagate user's interactions to P Inc in step (g). By implementing these interfaces, and agreeing to conform to WSRP, both P Inc and C Inc can use a standard mechanism to offer and consume portlets. In addition, P Inc can offer the same portlet to X Inc as long as X Inc adheres to WSRP, and C Inc can consume portlets offered by Y Inc provided Y Inc also implements WSRP interfaces.
The Service Description and Markup interfaces are the two required interfaces that any WSRP Producer must implement. In addition, WSRP specifies the following optional interfaces:
In the following sections, we will discuss these interfaces in detail by considering each aspect of the above scenario. To keep the discussions focused on the purpose and usage of these interfaces, we postpone any discussion on faults to Section 8.1. Refer to the WSRP specification for the list of faults that various operations in each of the interfaces may return. Also, note that the data structures used in the messages through out this Primer do not necessarily include all optional elements.
You can find the normative WSDL of all WSRP interfaces in [3], and the data types in [4]. We encourage you to refer to these documents for more complete descriptions of various messages presented in this Primer.
If you have questions about implementing WSRP, post your questions to the wsrp-dev@lists.oasis-open.org mailing list.
During the development of WSRP, the WSRP technical committee experimented with various well-known web services stacks such as .NET, JAX-RPC reference implementation, Apache Axis etc. For a discussion of stack related issues considered during the development of WSRL WSDL and data types, refer to [5].
To verify that your implementation conforms to the WSRP Specification, you can use the conformance test kit [6]. You can also review the conformance requirements at [7].
Throughout this Primer, we use illustrative scenarios, sample SOAP message fragments, and highlight implementation choices that Producers and Consumers could make. We use the following formatting conventions to aide readability:
fixed-width font to indicate XML elements and
attributes used in running text. In order to set up a Consumer to aggregate portlets offered by a Producer, the Consumer must first obtain a description of the Producer, and the list of portlets that the Producer offers. Based this information, the Consumer will be able determine if it can successfully aggregate those portlets, and setup its environment (for example, a page aggregating portlets) for such aggregation.
The getServiceDescription operation of the service description interface provides the Producer’s
metadata including the list of offered portlets and their properties.
All portlet Producers are required to implement this operation. Usually, the first request a Consumer ever sends to
a Producer is the getServiceDescription request. This operation returns the following:
Consider the following scenario.
Scenario 1: Discover Portlets
In order to get P Inc's service description, C Inc must first send a getServiceDescription request to P
Inc. Here is the most basic form of a getServiceDescription request that a consumer could send to a
producer.
Message 1: Service Description Request
To this request, P Inc responds with a getServiceDescriptionResponse document that includes the
following:
en and en-US locales. This does not necessarily mean
that portlets offered by this Producer are limited to generating markup in these locales, but simply that the
Producer's metadata is available in these locales. portletHandle
"portfolioManager". The portletHandle is an opaque reference assigned by the Producer, and both the
Consumer and the Producer use this handle to refer to this portlet in all interactions text/html. As with
locales, this portlet is not limited to generating markup in this MIME type. wsrp:view mode, and wsrp:normal,
wsrp:minimized, and wsrp:maximized window states. Here is the response message from P Inc. containing the above data:
Message 2: Service Description Response
C Inc can now use this response to setup a page to aggregate this portlet, and offer that page to its users.
The portlets described in the getServiceDescriptionResponse are &qout;producer-offered" portlets. In
Section 5.2.3 and 6.2.4, we will see how
Consumers can cause cloning of these portlets to create consumer-configured portlets. This distinction is important
because all Consumers are allowed to access/use producer-offered portlets and therefore no Consumer is allowed to
customize them.
Producers’ capabilities as well as the metadata of portlets offered by a Producer may change over time. When such changes happen, it is very likely that Consumers/portlets may not function correctly. To prevent such failures, and since WSRP does not provide a mechanism for Producers to notify Consumers of such changes automatically, we recommend that Producers keep such metadata unchanged, or notify Consumers of changes. In general, the guiding principle is that Producers must treat service descriptions and portlet descriptions as a published contract with all the Consumers.
Secondly, a Producer offering a fixed set of portlets with the same behavior to all Consumers without requiring any knowledge of the Consumer may follow the style of service description response described in this section. However, in most cases, Producers and Consumers may find it necessary to customize their behavior based on certain properties of the other party. For example, P Inc may want to offer the portfolio manager portlet only to those Consumers that enter into a service contract. Another Producer may want to customize its responses depending on the capabilities of the Consumer. As discussed in Section 4, Consumers and Producers may use the notion of registration to deal with such scenarios.
The purpose of the registration interface is to provide a means within the WSRP protocol for a Consumer to register with a Producer. Registration allows the Producer to associate portlets and any portlet customization data with the Consumer that is interacting with it. The Producer can also use the registration context to scope the artifacts offered/created during interactions to Consumers that caused those interactions. Note that the purpose of registration is not to uniquely identify a Consumer, but to establish a scope for a Consumer’s use of a Producer.
The WSRP specification does not specify/restrict any possible application of registration. Here are some possible applications:
Depending on the nature of services offered by the Producer and the nature of the business, the registration process may be as simple as sending a registration request to a Producer using the Registration interface, or may be as complex as fulfilling legal, billing and other contractual obligations to establish registration. Keeping this in mind, the WSRP 1.0 specification considers two forms of registration:
By following one of these forms of registration, the Consumer obtains a registrationContext from the
Producer. The registrationContext includes a registrationHandle, and optionally some
registrationState. Of these, the registrationHandle is a unique handle assigned by the Producer
to the Consumer and remains unchanged during the lifetime of a Consumer’s registration with a Producer. The optional
registrationState contains any persistent state for the registration which the Producer requires the
Consumer to store and resupply on future invocations.
The registration interface specifies the following operations:
register: This operation lets a Consumer register with a Producer. The Consumer may have to supply
certain producer-specified registration properties for registration. Upon registration, the Producer assigns a
unique registrationContext for the Consumer. The Consumer must then supply this
registrationContext with each request it makes to the Producer. modifyRegistration: This operation lets a Consumer modify an existing registration. If required,
the Consumer may supply registration properties with this request. The Producer may not assign a new
registrationHandle to the Consumer, but may return new registrationState. deregister: This operation lets a Consumer terminate a registration.
A Producer indicates that registration is required and that certain data is required for registration via its
response to a getServiceDescription request.
Let us now consider the following variation to Scenario 1 to see some of the details of registration.
Scenario 2: Registration
Since P Inc now requires registration, P Inc sends the following response to the previous simple
getServiceDescription request from C Inc.
Message 3: Service Description Response from Producer Requiring Registration
The first point to note from this response is that P Inc now requires registration, and that it requires Consumers to supply two registration properties for registration.
stringValue in the
urn:oasis:names:tc:wsrp:v1:types namespace. Producers can use either the stringValue type or
any arbitrary schema type (other than those defined in the urn:oasis:names:tc:wsrp:v1:types
namespace) to describe a registration property.
Other than these requirements, this service description response does not provide much information about P Inc. Specifically P Inc chose to omit portlet metadata in its response.
C Inc then sends the following request to P Inc supplying the DUNS number and service ID that P Inc. assigned.
Message 4: Registration Request
In addition to the registration properties, the Consumer sends some additional metadata of itself:
However, as any web developer would be familiar with, HTML forms using GET as the method type cannot include
query parameters in action URLs. To support such forms, Consumers will have to use hidden parameters or cookies,
or some other technique to embed implementation-specific data. If a given Consumer is not capable of supporting
such forms, it can indicate so to the Producer by supplying false for the methodGetSupported
element. The Producer can then avoid offering portlets that generate forms with method GET to the Consumer.
Refer to the WSRP specification for a list of other optional data that the Consumer can supply during registration.
The Producer P Inc validates this request for registration, creates a registration context, and returns the following response:
Message 5: Registration Response
In this response, the registrationContext represents a registration relationship between the P Inc
and C Inc, and contains a registrationHandle assigned to C Inc by P Inc. Once a Consumer obtains a
registrationContext, the Consumer must supply the registrationContext with all
subsequent requests to the Producer. For this reason, the Consumer must persistently maintain the
registrationContext for all future invocations.
registrationHandle and returns this handle via a RegistrationContext.
If the Producer is not capable of managing persistent storage of registration data, the Producer can choose to
return all such data to be persisted as registrationState to the Consumer. The Consumer would then
be responsible for storing the registrationState along with the registrationHandle and
return these to the Producer in future invocations.
Having completed the registration process, C Inc can now send another service description request to P Inc, this
time supplying the registrationContext.
Message 6: Service Description Request after Registration
The registrationContext in this request helps P Inc to tailor its response. Upon validating the
registrationContext, P Inc sends a response that includes portlets it offers.
Message 7: Service Description Response after Registration
Note that this message is similar to the response shown in Message 2, but has only been received after C Inc fulfilled P Inc’s registration requirements.
Once a Consumer establishes a registration relationship with a Producer, in some conditions, Consumers may have to modify an existing registration relationship either to be able to continue to use a Producer or alter certain properties of the registration. Here are some possible situations that may warrant such an operation:
Consider the following scenario.
Scenario 3: Modify Registration
To implement this scenario, P Inc has the following options:
OperationFailed faults until C Inc. supplies the new property (email address).
In the former case, C Inc will have to send getServiceDescription request (without the
registrationContext) to discover the current set of registration properties. Upon discovering the new
registration property, C Inc sends the following modifyRegistration request to P Inc.
Message 8: Request to Modify Registration with an Additional Registration Property
This request is similar to the registration request in Message 4 except for a new value for a registration property.
P Inc validates the new values for registration properties, modifies registration, and responds with the following message:
Message 9: Modify Registration Response
The response simply indicates that P Inc. has accepted the request for modification of registration.
registrationState in the modifyRegistrationResponse.
After modifying the registration relationship, C Inc can continue to use the registrationHandle.
Registration relationships are not permanent. Either the Consumer or the Producer may terminate a registration relationship. Here are some scenarios that could prompt for a termination:
In cases (a) and (c) above, the Consumer can send a deregister request to the Producer to terminate
the current registration relationship. Note that, Consumer is not required to deregister always.
However, by formally deregistering, Consumer lets the Producer cleanup any persistent data maintained for that
registration.
Consider that C Inc now wants to terminate its registration with P Inc. In order to do so, C Inc sends a
deregister request with its registrationHandle to P Inc as shown below.
Message 10: Deregister Request
P Inc then deregisters C Inc and cleans up any resources/state created (including any cloned portlets) for C Inc, and returns the following response.
Message 11: Deregister Response
After this step, C Inc can no longer use the registrationHandle “CIncRegnHandle” for its requests
to P Inc.
Terminating a registration has some consequences for both the Producer and the Consumer:
Figure 2 shows possible interactions between C Inc and P Inc and the registration life cycle.
Once you establish a registration between a Producer and a Consumer, the registration becomes long lasting. This is because the registration relationship is tied to any persistent data stored on both the Producer and Consumer. Deregistering a Consumer from a Producer will invalidate such persistent data, and your users will not be able to use their portlet settings.
Due to the reasons discussed in Section 4.2.2, if a Consumer modifies an existing registration, we recommend that the Consumer obtain the service description from the Producer again. This is because Producers may use registration data to tailor service description to each Consumer.
Note that registration does not address the question of Consumer identity in the security sense. You may need other means of trust to address the question of Consumer identity.
In order for a Consumer to generate a page that aggregates portlets offered by one or more Producers, the Consumer must first obtain the markup of each portlet from each Producer. As users interact with the portlet (e.g. by submitting a form from the portlet’s markup), the Consumer must be able to send such interaction requests to the Producer, and then receive markup reflecting the user interaction. The Markup interface specifies operations for achieving these tasks. All Producers are required to support this interface.
The markup interface includes the following operations:
getMarkup: The purpose of this operation is let the Consumer collect markup fragment for for a
given portlet. performBlockingInteraction: Consumers use this operation to dispatch each user interaction to
the Producer hosting the portlet that sourced the markup the user is interacting with. initCookie: The purpose of this operation is to let the Producer initialize any cookies, and
set those cookies to the Consumer. As we shall discuss shortly, using this operation Producers may return
cookies to Consumers for load-balancing or other implementation specific purposes. releaseSessions: As we shall see shortly, during a getMarkup or a
performBlockingInteraction, portlets can initialize sessions. When a portlet creates a session, the
Producer returns a sessionID for the session to the Consumer in its response to the getMarkup
or performBlockingInteraction response. Consumers can use the releaseSessions
operation to let the Producer release those sessions. Collecting markup and aggregating it into a page poses several challenges such as creating correct links in the markup, managing transient state, propagating user interactions etc. In this section, before reviewing the operations in this interface, let us discuss some of the most important issues that the markup interface addresses.
One of the primary goals of WSRP 1.0 was to allow the aggregation of multiple content units, portlets, from different sources on the same web page. HTML 4.01 and XHTML 1.1 treat pages as separate documents and disallow multiple BODY Elements, represented as <body> tags, in a single document. Therefore, the Consumer cannot aggregate individual documents with individual BODY elements from individual portlets into a single page. Portlets are therefore required to generate markup fragments.
The Consumer is most likely to aggregate the portlet’s markup fragment (such as HTML or XHTML) into a page that also includes markup from other portlets. For rules on what differentiates full markup from markup fragments, refer to Section 10.5 of the WSRP 1.0 specification. Along with the markup fragment, the Producer also returns certain properties of the markup fragment, such as the content type, character encoding, locale etc.
With WSRP, the Consumer aggregates markup from different portlets hosted on Producers, and users interact with those portlets via the Consumer. The Consumer is therefore responsible for presenting portlets’ markup as well as receiving user interactions from portlets. Moreover, a user’s interaction with one portlet may affect the markup for another portlet due to any shared state between portlets.
When a user interacts with a web page, you can process the input and generate new markup (e.g., by forwarding to a new page) in a single step. However, such a single step process is not adequate for processing interactions with a page aggregating multiple portlets. During such an interaction, it is most likely that only one portlet processes the request, while all the portlets (including the one that processed the request) on the page regenerate their markup taking into account any state shared between those portlets. In an aggregated page, each portlet should be able to generate markup without any user interaction. This will allow the user to interact with one portlet, and yet see markup of all portlets on the aggregated page.
When a user interacts with a portlet’s markup (e.g. by submitting a form), the Consumer forwards the interaction to the Producer identifying the portlet that generated the markup. This allows the portlet to process the user interaction (e.g. by performing queries/updates in some backend system, or updating some persistent state). During this process, the portlet processing the interaction can also update some shared state that other portlets rely on. Once this process is complete, the Consumer can get markup for each portlet from each Producer, and regenerate the aggregated page. In order to approach this sequence, WSRP specifies a two-step protocol.
The first step of the protocol is to process user interactions, as specified by the
performBlockingInteraction operation of the WSRP protocol. The purpose of this operation is to let a
portlet process the user interaction, update any transient and persistent state, and possibly return the new
state to the Consumer.
The second step of the protocol is to get markup from the Producer, as specified by the getMarkup
operation of the WSRP protocol. This operation returns the portlet’s markup (a fragment), and properties of the
markup (such as a preferred title, character encoding, locale and content type of the markup).
The Consumer can get markup for each portlet from each Producer even in the absence of a user interaction. This can happen, e.g. when a user visits the aggregated page for the first time, or when the user refreshes the page. The two-step protocol allows for such interaction-free rendering and using this protocol, Producers can generate markup for portlets with their current state even in the absence of any interaction for any given portlet.
As the name implies, the performBlockingInteraction operation is a blocking operation. That is, the
Consumer waits for this operation to complete before sending getMarkup requests. Due to the
blocking nature of this operation, Producers can allow changes made to a portlet’s state during a blocking
interaction visible to other portlets during their markup generation. For example, the portlet processing the
blocking interaction can store some data in a relational database, and other portlets can read that data during
markup generation.
During various getMarkup and performBlockingInteraction requests, Producers and/or
portlets can return state to Consumers. Consumers are required to supply such state in future interactions for
the portlet to the Producer. The markup interface accounts for the following kinds of state:
performBlockingInteraction requests. Portlets can also embed navigational state in each URL in the
markup. In either case, Consumer returns this navigational state to the Producer with subsequent
getMarkup requests. Navigational state typically encapsulates data required by Producers to generate
markup for a given portlet several times without having to keep track of the interaction that caused the
current state of the portlet. sessionID for the session, and returns it to the Consumer.
Consumers return this sessionID in future requests to that portlet. This mechanism is similar to
HTTP state management as specified in RFC 2965 [8]. The difference between navigational state and session state is that navigational state allows the Producer to free itself from holding transient state locally and makes that state of the portlet bookmarkable by the user.
With WSRP, the Consumer is the intermediary between the Producer and the end user. Here are some advantages of the Consumer being the intermediary:
URLs in the markup presented to the end user should therefore refer to the Consumer and not to the Producer. Either the Producer or the Consumer must take the responsibility of creating or converting URLs in the markup to refer to the Consumer. The markup interface accounts for such URL generation.
WSRP specifies two kinds of URL generation, viz. Consumer URL rewriting and Producer URL writing. Of these, the former approach requires the Consumer to rewrite URLs in the markup to refer to the Consumer. On the other hand, the latter approach lets the Producer generate URLs using Consumer supplied URL templates. We shall discuss these techniques briefly in Section 5.2.1.
Although the performBlockingInteraction operation is the first step in the two-step protocol, let
us first discuss the getMarkup operation as it lets us probe the issues in a more natural order.
The purpose of the getMarkup operation is to obtain a portlet’s markup. In order to discuss the
semantics of this operation, consider the following scenario.
Scenario 4: Get Initial Markup
In addition to the information about the Consumer and the portlet, the Producer needs some more data about the
user (for personalizing the markup), user’s device (e.g. browser), type of connection (e.g. secure or normal),
and what kind of markup is acceptable to the Consumer and to the end user. The getMarkup request
encapsulates all such information.
For the current scenario, C Inc. sends a getMarkup request the producer, P Inc. with the
following data:
RegistrationContext: This element carries the registrationHandle assigned by P
Inc during registration. PortletContext: This element includes the portletHandle, which the Consumer uses
to identify the portlet to the Producer. RuntimeContext: This element includes the authentication mechanism (represented by
userAuthetication) C Inc used to authenticate the user along with optional elements such as the
sessionID, URL templates, etc. UserContext: This element carries a userContextKey the Consumer assigns to the
user. In the current scenario, C Inc sends a nil UserContext as C Inc has not
assigned any userContextKey to the user. MarkupParams: This element carries information about the request from the user to C Inc, such
as whether the user used a secure communication channel (represented as boolean value for
secureClientCommunication), an array for accepted locales for the markup (represented as locale
elements), an array of accepted MIME types (represented as mimeTypes elements), the mode and
window state for the portlet markup, accepted character sets for the markup (represented with
markupCharacterSets elements). Here is the request from C Inc to P Inc.
Message 12: Get Markup Request
Note the following from this request:
RegistrationContext: The registrationHandle is CIncRegnHandle assigned by P Inc
during registration. PortletContext: The portletHandle is portfolioManager. RuntimeContext: The userAuthentication is wsrp:password. This value
indicates the user supplied a username and password to authenticate with C Inc. UserContext: The userContext is nil. When supplied, the UserContext
includes a userContextKey. This key is an arbitrary reference assigned by C Inc for the user.
Producers typically use this key for personalizing the portlets markup and behavior. In addition to this key,
C Inc can also include a profile of the user (such as the name, gender, home/work information etc) and an
array of userCategories with the UserContext. The purpose of these items is to allow the Producer
to personalize the behavior and/or markup of the portlet. Refer to Section 6.17 and 6.10 of the WSRP 1.0
Specification for more details. MarkupParams: The Boolean for secureClientCommunication is false indicating that
the user did not user a secure connection (such as SSL) to C Inc. This element also specifies that the
accepted locale is en, the accepted MIME type for markup is “text/html”, the accepted character set for the
markup is UTF-8, the mode is wsrp:view, the windowState is wsrp:normal (modes and
window states to be discussed later in this section). This element also includes the clientData
element with a value for userAgent identifying the browser and operating system of the user.
This is a basic form of a getMarkup request that a Consumer could send to a Producer. To this
request, P Inc responds with a getMarkupResponse that includes:
MarkupContext, which contains the markup for the portlet, a title, locale and MIME type of
the markup. SessionContext (optional) with a sessionID, and an expiry time interval (in
seconds) for the sessionID. The Producer returns the SessionContext element when it
establishes new session. The Consumer should supply this sessionID on future invocations in order
to not lose state the Producer is storing for the user’s interactions. If a Consumer does not invoke this
portlet before this interval, the Producer may terminate the session associated with the sessionID.
Here is the response from P Inc.
Message 13: Get Markup Response
Note in our example:
markupContext with a markup fragment, a preferred title “Portfolio Manager”,
locale “en-US” and MIME type “text/html; charset=UTF-8”. C Inc can use the preferred title to render a title
bar with the portlet’s markup. getMarkup and performBlockingInteraction
requests for this portlet.
In this response, P Inc returned the markup as a markupString. This is an XML-escaped string with
XML entities such as < individually escaped as < or escaped in bulk by the use of
a CDATA block as per this example.
Producers can also return the markup as Base64-encoded binary data via a markupBinary element in
the markupContext.
wsrp_rewrite token and suffixed
with a /wsrp_rewrite token. The URL itself between these tokens is not a complete URL. When C Inc
encounters these tokens, C Inc rewrites the URL to a string that refers to C Inc. The tokens contained between
these markers are instructions on what the Consumer is to do to invoke the Producer when an end-user activates
the resulting URL. wsrp-urlType: This is the first parameter in the URL and indicates the type of
the URL. WSRP specifies three kinds of URL types – blockingAction, render, and
resource. When the value of this parameter is blockingAction, C Inc converts the URL into
a URL that when activated, causes a user interaction (i.e., a performBlockingInteraction
request). When the URL type is render, C Inc simply needs the URL to request that it invoke
getMarkup without an additional performBlockingInteraction invocation. The URL type
resource is used for generating links to resources such as images, files etc. Refer to Section 10.2.1
of the WSRP 1.0 Specification for more details. wsrp_rewrite_ token. This
is an indication to C Inc that it must rewrite the value stockForm such that it is unique within
the generated page. Since the portlet is not aware whether names such as this are unique within an aggregated
page, portlets use this token to let the Consumer generate a unique name. In this example, the Consumer rewrote the action URL to refer to a finance page containing the portfolio manager portlet. The actual values of the URL and names in the above markup depend on the Consumer’s implementation. Another Consumer interacting with P Inc may rewrite the URLs and names differently.
The WSRP specification specifies an alternative form of URL generation called as “producer-writing”. Producer writing involves URL templates and a namespace prefix that the Consumer sends to the Producer. Instead of using tokens, Producer uses the templates and the namespace prefix to create URLs and names in the markup. For more details of this approach, refer to Section 10.2.2 of the WSRP 1.0 Specification.
performBlockingInteraction operation to send user interactions to the
Producer. During this operation, portlets can process user interactions while letting the Producer affect
their state. Note that the scope of the getMarkup operation is limited to generating markup for a
portlet without affecting the current state of the portlet.
performBlockingInteraction to send the submitted data to the Producer. During the course of this
operation, any/all of the following may happen. performBlockingInteraction request.
Let us extend Scenario 4 to let the user cause an interaction affecting the portlet’s state.
Scenario 5: Blocking Interaction
After the user submits the form, C Inc sends a performBlockingInteraction request to P Inc so
that the portfolio manager portlet can process the user interaction. The performBlockingInteraction
request contains all the data elements contained in the earlier getMarkup request, plus an
additional InteractionParams element. This element includes the form data submitted by the
user.
In this example, this portlet is capable of processing only one user interaction. However, if this portlet
is capable of processing more interactions, it may add an interactionState parameter to the
action URL. This parameter can describe the kind of user interaction associated with the request. For
example, if this portlet can also delete a stock symbol from the list of symbols, it could add an
interactionState parameter such as “deleteSymbol”. The actual value of the state is opaque and is
implementation specific.
Producers or portlets can embed arbitrary state within URLs as interaction state. When a user activates a
URL with interaction state, Consumers extract the interaction state from the HTTP request, and include it in
the performBlockingInteraction request to process the interaction. Interaction state is similar
to form parameters except for the difference that Producers or portlets pre-populate interaction state in
URLs.
The following message shows a performBlockingInteraction request message as it would be
generated if the form from our preceding getMarkup is submitted by the user to the Consumer
requesting the PINC stock symbol. Note that the portletStateChange field has been set to
readOnly to indicate that a state change is not acceptable to the Consumer. We will discuss the
purpose of this field later in this section.
The runtimeContext element of this request also includes the sessionID previously
returned by C Inc.
Message 14: Blocking Interaction Request
To this request, P Inc responds with the message shown below.
Message 15: Blocking Interaction Response
The UpdateResponse element of this response contains new navigationalState created
by P Inc. This navigational state represents state that P Inc expects C Inc to return with subsequent
getMarkup requests. In this specific example, P Inc created a string that contains the name of the
stock symbol and returned it as the navigational state. When C Inc returns this state with a future
getMarkup request, P Inc extracts the name of the stock symbol from the navigational state, looks up
for the value of the stock symbol, and generates a markup fragment that shows the name and value of the
stock symbol. As far as the Consumer is concerned, the navigationalState is completely opaque.
Navigational state is similar to a query string on a standard URL. Producers can express the result of
processing the interaction as the navigationalState and use this state to generate markup as
many times as requested by the Consumer. For instance, if a Consumer sends a
performBlockingInteraction request with the data necessary to create a purchase order in a database,
the Producer could return a reference to the primary key of the purchase order created as navigational
state, and use that state in subsequent getMarkup requests to show pertinent information of the
purchase order created.
navigationalState (or a reference to the navigationalState)
in portlet URLs so that users can bookmark pages including the navigational state of each portlet. When a
user activates such a bookmarked URL, the Consumer extracts the navigationalState and sends it
to the Producer to get similar markup as was obtained at the time of book marking.
Depending on the results of processing the performBlockingInteraction request, the
performBlockingInteractionResponse could include the following:
portletContext with a portletHandle and/or portletState
element. In this case, the Consumer prevented this by setting the portletStateChange element to
a value of readOnly. sessionID. Consumer is required to send this sessionID
with future getMarkup or performBlockingInteraction requests. updateResponse element. The value of this element is an
absolute URL that the Consumer is required to direct the user to. markupContext element with the portlet markup. Note that to let the Producer generate
this, the performBlockingInteraction includes the full MarkupParams structure.
When a Producer returns markupContext in the performBlockingInteractionResponse,
Consumers can avoid calling getMarkup and use this markup instead, presuming it honored any
requested changes in mode or window state. Consumers can also discard this markupContext, and
send a usual getMarkup request for the markup.
The following figure shows the overall sequence of getMarkup and
performBlockingInteraction requests.
In this two-step protocol, the following key differences between getMarkup and
performBlockingInteraction are worth noting.
performBlockingInteraction requests only when a user interacts with a
portlet URL specifying a value for url-type of blockingAction or secureBlockingAction. On the
other hand, Consumers send getMarkup requests only whenever the portlet’s markup is required or
when the url-type is render or secureRender. For example, a simple browser reload of a Consumer’s aggregated
page or user interactions with other portlets on aggregated page may cause getMarkup
invocations without any performBlockingInteraction invocation.
getMarkup request. However, in the case of performBlockingInteraction requests,
Producers can return such changes to the Consumer. getMarkup requests without negative effects. In particular, a portlet making transient and/or
persistent changes to its state during markup generation must be prepared to generate markup any number of
times.
While processing a performBlockingInteraction request, if allowed by the Consumer, the Producer
can clone the portlet, and return a portletContext with a new portletHandle and/or
portletState. This is often called implicit cloning because the Consumer did not directly ask
the Producer to clone the portlet, rather the Consumer indicated that under certain circumstances the
Producer was to generate a clone and return it. For the Consumer, the new portletContext
replaces the current portletContext for this user.
To illustrate how such implicit cloning may occur, consider the following variation to Scenario 5.
Scenario 6: Perform Interaction with Implicit Cloning
The portlet can use its portletHandle as a primary key for storing the list of symbols.
However, before letting the portlet add the stock symbol to the list of preferred symbols, P Inc should
ensure that the portletHandle of this portlet is specific to the current user and is not
shared with other users accessing the same portlet. Since P Inc offered this portlet with a
portletHandle portfolioManager via its service description, there may be several Consumers (or
several users from the same Consumer) using this portlet with the same portletHandle. In
order to avoid sharing the list with other users, P Inc must first create a new portletHandle
and let the portlet store the list against the new portletHandle.
However, P Inc does not know whether C Inc allows several users to access the same portlet or not. That is, without the Consumer supplying additional information, P Inc cannot determine if it must clone the portlet before letting the portlet store the list of symbols. C Inc must therefore inform P Inc that, in case the portlet is trying to make state changes, P Inc must first clone the portlet.
This scenario illustrates one of the ways implicit cloning may occur. Other possibilities depend on how a Producer associates persistent state with portlets.
When a Producer implicitly clones a portlet, it returns the new portletHandle (along with
portletState, if it is not capable of storing state persistently) to the Consumer. However,
Consumers may not always be ready to accept a new a portletHandle or portletState.
For instance, the Consumer may not have persistent storage capabilities. Or, the Consumer may not want to
allow a given user affect the persistent state of a portlet as the user lacks adequate privileges. To
account for these situations, WSRP specifies a portletStateChange element in the
performBlockingInteraction request. Consumer can supply one of the following values for this
element:
readOnly: This value indicates that the Producer is not allowed to return a new
portletHandle and/or portletState. If the portlet tries to update persistent state
that may cause a new portletHandle or portletState, the Producer will return a
PortletStateChangeRequired fault to the Consumer. cloneBeforeWrite: This value indicates that the Producer must first clone the portlet
before attempting to make persistent state changes. readWrite: This value indicates that the Producer can make persistent state changes
without cloning the portlet.
Typically, Consumers capable of accepting implicit cloning initially send a value of
cloneBeforeWrite, and replace it with readWrite once implicit cloning occurs.
Producers are required to depend on the Consumer to properly indicate whether or not the user is allowed
to update the persistent state for the current portletHandle.
The following figure illustrates the persistent lifecycle of a portlet caused by implicit cloning.
In this figure, rounded rectangles show two of the states in the persistent lifecycle of a portlet. The arrows between these states show transitions between states.
getServiceDescriptionResponse (e.g. as in Message 2).
In our sample scenario, the portfolio manager portlet with portfolioManager as the portletHandle
is a producer-offered portlet. cloneBeforeWrite for portletStateChange with the
performBlockingInteraction request. In Section 6, we will discuss an explicit method of cloning and destroying portlets.
Between typical browser-server interactions, web servers use cookies to set state to the browser, which the browser returns with subsequent requests. RFC 2965 [8] describes the rules governing cookies.
In the case of WSRP, Producers may set cookies on responses to Consumers, requiring the Consumers to
return those cookies with future getMarkup and performBlockingInteraction
requests. Here is a sample scenario that motivates the use of cookies.
Scenario 7: Initializing Cookies
P Inc can use the requiresInitCookie element in its service description (refer to Section
5.1.18 of the WSRP 1.0 Specification for the allowed values) to inform Consumers of this need and C Inc
then uses the initCookie operation of the markup interface to implement the scenario.
When C Inc sends an initCookie request, P Inc can set HTTP cookies with the response, and
require C Inc return those cookies with getMarkup and performBlockingInteraction
requests.
For example, consider that P Inc sets the value of requiresInitCookie to any value other
than none in its service description. C Inc then sends the following initCookie
request to P Inc.
Message 16: Init Cookie Request
In return, P Inc sends the following response along with Set-Cookie headers (at the HTTP
transport level). In the current scenario, the value of the cookie may contain some information to let
the load-balancing mechanism identity the Producer instance in the cluster.
Message 17: Init Cookie Response
C Inc collects these cookies, and resends them with subsequent getMarkup and
performBlockingInteraction requests.
In Message 13, we saw that the Producer, P Inc. initialized a
session for the portfolio manager portlet, and returned a reference to that session as a sessionID
in its response. The Producer and/or the portlet may also be managing in-memory state in those sessions.
As a Consumer interacts with a Producer for different portlets on behalf of a given user, the Producer
may initialize sessions for these portlets, and return session IDs of those sessions. Since the Consumer
is required to supply these IDs to the Producer on subsequent invocations, the Consumer will have to
store those temporarily, for example, in the user’s session on the Consumer itself.
What happens if the user stops interacting with the Consumer, or the user’s session on the Consumer has
timed out? In these cases, the sessions on the Producer will remain alive until they timeout naturally.
To let the Producer reclaim storage consumed by such sessions in a timely manner, the Consumer can send
a releaseSessions request to the Producer to inform it that those sessions will not be
referenced by future invocations.
In our scenario, C Inc can send the following request to P Inc to release the session created for the portfolio manager portlet.
Message 18: Release Sessions Request
The Consumer can add several session IDs in this request. To this request, P Inc terminates the session, and returns the following response. The response merely indicates that the Producer has released the session, and the Consumer can no longer use those session IDs.
Message 19: Release Sessions Response
While Producers are required to support the releaseSessions operation, Consumers may or may
not send a releaseSessions request to the Producer. Therefore, we recommend that Producers
expire sessions after meaningful time interval or inactivity interval, and not depend on the
releaseSessions operation alone.
Consumers can use modes and window states to influence the behavior and markup of a portlet.
Portlets can expose their functionality with different modes, with each mode catering to a particular
function. For example, a portlet can provide its default functionality in one mode (e.g. wsrp:view
mode) and provide customization functionality under a different mode (e.g. wsrp:edit mode).
WSRP 1.0 Specification specifies wsrp:view , wsrp:edit , wsrp:help
, and wsrp:preview modes as standard modes that portlets can support.
Window states, on the other hand, let Consumers indicate how much markup a portlet should generate. WSRP
1.0 Specification specifies wsrp:normal , wsrp:minimized ,
wsrp:maximized , and wsrp:solo as standard window states. Portlets could generate
different length/style of markup in each of these window states. For example, a portlet could generate
its complete view (with more markup, images etc) in wsrp:maximized window state, while
generating no displayable markup in wsrp:minimized state.
In addition to these standard modes and window states, portlets could offer markup in additional modes
(known as custom modes) and window states (known as custom window states). Producers advertise the modes
supported by a portlet in the description of the portlet. Consumers typically provide decorations (such
as a title bar with buttons) to let users request portlet markup in various modes and window states.
WSRP 1.0 Specification requires that portlets support wsrp:view mode and wsrp:normal
window state so that Consumers are able to obtain markup in at least one mode and window state they
support.
Portlets could request a change to the current mode and/or window state while processing a
performBlockingInteraction by returning the requested new values within the
performBlockingInteractionResponse . Consumers are expected (although, not required) to honor
such mode and window state changes. If a Consumer does not understand a portlet’s mode or window state
(including custom modes and custom window states), the Consumer is unlikely to request markup using that
mode or window state. In such cases, the Consumer can request for markup in one of the known modes and
window states.
A Consumer could have its own set of custom modes and window states, and attempt to request a portlet render in one of these. If the portlet does not comprehend the requested mode or window state, the Producer returns an appropriate fault message.
HTML 4.01 states: “Since style sheets are now the preferred way to specify a document's presentation, the presentational attributes of BODY have been deprecated.” Accordingly, WSRP 1.0 has adopted an initial basic set of CSS classes designed to provide a standard set of display options for portlets. For a list with tables of these portlet classes, see Section 10.6 of WSRP 1.0 specification. Use of CSS portlet classes are optional and only appropriate for those markup types supporting CSS.
WSRP allows the Consumer to cache markup fragments returned by the Producer. This enables the Consumer
to avoid calling getMarkup again to obtain the same markup fragments that the Producer had
returned previously and had indicated as cacheable. In addition to improved performance at the Consumer,
caching makes the Producer more efficient since the Producer does not have to regenerate identical
markup fragments across a series of requests. Note that the Consumer must take into account the
MarkupParams structure that the Consumer sent to compute any key used to locate cached markup
fragments in the Consumer’s caching mechanism.
The presence of a valid (i.e., non-null) CacheControl in the MarkupContext
sent by the Producer when returning markup is the hint given by the Producer to the Consumer that it may
choose to cache the returned markup for subsequent invocations. The CacheControl structure
includes information such as the duration that the cached markup is valid for, the user scope of the
markup (e.g. whether the Consumer can share the markup for other users as well), as well as a tag that
the Consumer can use to send to the Producer to validate if the cached markup can still be used by the
Consumer even after the expiry of the cache.
To illustrate how caching works, let us revisit Scenario 4, wherein C Inc made a request to P Inc for the initial markup of the portfolio manager portlet.
Here is the response from P Inc.
Message 20: Get Markup response that includes caching information
This message is similar to Message 13, except for the parts shown
in bold. In this response, P Inc returned a CacheControl element as part of the
MarkupContext that indicates to C Inc that the markup fragment returned is cacheable.
In this particular response, the CacheControl structure includes the following elements:
expires: This field indicates that the markup fragment referenced by this cache control
is valid for 60 seconds (counting from point in time when the markup was returned). userScope: A value of wsrp:perUser specifies that the markup is specific
to the userContext for which it was generated. validateTag: The value portfolioManagerPValidateTag is for the purpose of
the Consumer to verify with the Producer if this particular cached markup fragment is still valid even
after it has expired (i.e. in the situation whereby, even though the cache had expired, calling
getMarkup would result in the same markup fragment being returned).
Next, let us suppose that the user at C Inc refreshed the page in the browser. In the absence of any
caching, this would have caused the Consumer to get the markup for the portlet from the Producer again.
However, since the markup that was just returned did contain a valid CacheControl, the
Consumer can use the cached markup.
Now let us explore the scenario whereby the user refreshed the page after the expiry of the cached
markup (i.e., after 60 seconds). Since the Producer returned a validateTag element as part of the
CacheControl, the Consumer has the option of sending the value of that element back to the
Producer to determine if it can still reuse that cached markup.
Here is the new getMarkup request from C Inc to P Inc.
Message 21: Get Markup Request with a validate tag
The above request from the C Inc to P Inc is similar to Message 12
except for the line shown in bold. The MarkupParams structure now also contains a
validateTag element with the value portfolioManagerPValidateTag that P Inc returned earlier
as part of the CacheControl structure. The Consumer is supplying this as a means for the
portfolio manager portlet to avoid generating new markup if it can valid this tag.
Let us assume that the markup is indeed still valid. P Inc responds to the getMarkup
request as shown below.
Message 22: Get Markup Response that includes a CacheControl structure
In the response above, the Producer indicates that the cached markup fragment is still valid for this
request by setting the useCachedMarkup to true. Note that the Producer
intentionally omits the markupString field from the response. Also, note that it is
mandatory for the Producer to send back a new cacheControl structure to the Consumer to
indicate a new expiry field for the given markup fragment. The Consumer should replace this with any
other value it had stored earlier.
Lastly, with respect to caching invalidation, we recommend Consumers discard any cached markup for the
given portlet once they invoke performBlockingInteraction since the operation may result in
the cached markup becoming invalid. Future versions of WSRP may provide a means for a portlet to
indicate that the markup cached by the Consumer is no longer valid.
The markup interface deals with markup, user interactions, and the state associated. Due to the complexities associated with these, Producer and Consumer implementers must take into account a variety of issues and choices. During the lifetime of a portlet, the markup interface gets more heavily used than other interfaces, and hence implementers must take into account performance and scalability issues as well. In addition, Producers invoke portlet(s) during this interface, portlet developers must also be aware of certain intricacies. In this section, we present some guidelines for implementers and portlet developers.
The first thing to note about the markup interface is the two-phase protocol. Producers must capture the result of an interaction as navigational state or some other form transient/persistent state and be prepared to generate markup any number of times with the help of that state.
Producers can use navigationalState or sessions (or both) to manage transient state.
However, navigationalState has some advantages over using sessions. In particular,
Producers/Consumers can embed navigationalState in URLs in markup returned to end users.
Users can therefore bookmark URLs and be able to view the same/similar content at a future time. Since
sessions usually have limited lifetime, after the Producer terminates a session, users may not be able
to view same/similar content at a future time.
Use of navigationalState to represent transient state also improves cacheability of markup
by Consumers. Consumers can use the navigationalState as part of the cache key for caching
the markup, and serve cached markup whenever the same navigationalState is found for a
given getMarkup request.
Another point to consider is the network traffic. In order to reduce network overhead, we recommend the following practices:
performBlockingInteraction,
Consumers can avoid invoking the getMarkup request for the same portlet on the same
Producer, saving one network roundtrip. getMarkup requests concurrently instead of serially. Provided the Consumer has
sufficient network bandwidth, this approach will help improve responsiveness of the Consumer as far as
end users are concerned. Another issue for consideration is URL generation. Producers must carefully evaluate their portlets and usage to support one of the forms of URL generation. In general, URL template based URL generation offers better performance when the markup is personalized for each user and the Consumer is able to supply URL templates and not post-process the markup returned from the Producer. On the other hand, Consumer URL rewriting has the advantage of cacheability. With Consumer URL rewriting, the markup returned by the Producer does not include references to the Consumer, and therefore the Producer can cache the markup and serve the cached markup to several Consumers.
Although Producers can choose to support either Producer writing or Consumer rewriting, Consumers must be prepared to support both so that the Consumer can easily work with diverse Producer implementations.
The purpose of the portlet management interface is to let Consumers manage the persistent state and lifecycle of portlets explicitly.
In addition to the transient state (such as navigational state) of portlets we discussed in the previous section, portlets can have persistent state as well. WSRP allows Producers to expose a transparent view on such persistent state as properties. Portlet properties are data associated with a portlet. Using the portlet management interface, Consumers can access and change those properties.
An example of a portlet property is the list of stock symbols for the portfolio manager portlet. While this portlet encapsul