Preference layers and portlet modes
Get an overview of portlet configuration preference layers and portlet modes to best implement the different layers on which preferences for portlet views can be configured.
Overview of portlet configuration preference layers and portlet modes
Portlets that are written to comply with the Standard Portlet API access their configuration by using the PortletPreferences interface from the standard portlet API. Internally, WebSphere Portal keeps multiple levels of portlet configuration that are aggregated to form the representation of the portlets for the users:
Type of configuration Description Portlet mode Deployment descriptor preferences They are associated with a deployed portlet, represented by a <portlet> tag in portlet.xml. They apply to all occurrences of that portlet on all pages for all users.
Administrator preferences They are associated with a portlet definition, that is a particular copy of a portlet. They apply to all occurrences of that portlet definition on all pages for all users. The administration portlets allow you to create multiple copies of the same portlet with different configurations on the administrator level. config Shared preferences They are associated with a particular occurrence of a portlet definition on a page and apply to all users who view the portlet on that page edit_defaults Personalized preferences They are associated with a single user and apply only to that particular user who views the portlet on the page. edit, view, help
For details about the tag for the edit_defaults mode refer to portal-skin tags under the tag <portal-skin:portletEditDefaults/> .
Access preferences
WebSphere Portal merges the different preference keys and values defined on these levels into a single PortletPreferences object. When the same preference key is defined on multiple levels with different values, the most specific value (from bottom to top in the above list), takes precedence and values on more general levels are not available. This allows you to set up general default values for preferences that can then be customized by individual users. Preference values can be locked for user customization by declaring them read-only in the deployment descriptor. Read-only values can only be modified on the administrator level but can never be overridden in lower levels. An example:
- Administrator A configures a database viewer portlet so that it displays the Fish view in the Animals database and shows 10 lines per page. The database setting is locked (read-only) so that users may customize the portlet but cannot use it to view a different database.
- Editor E places the portlet on a page and decides that the Mammals view is a more interesting default.
- User U1 personalizes the portlet to display the Birds view with 20 lines per page instead of the defaults given by the administrator and the editor.
- User U2 personalizes only the number of displayed lines with a value of 55, so user U2 still sees the Mammals view.
- Other users who view the same page will still see the Mammals view with 10 lines per page as set by the administrator and the editor.
- Editor E now changes the default view to Reptiles. This does not affect U1, but only U2 and other users that have not personalized that particular preference key.
- Finally, U1 resets the personalization of the database view. As a result, the shared default, which is now Reptiles, is shown again. The number of displayed lines still remains at the personalized value of 20.
Modify preferences
A preference is modified by using setValue. This normally occurs at the personalized layer and therefore affects only the current user. WebSphere Portal uses two special custom modes from the set of predefined custom modes in the Java Portlet Specification to allow setting up the more general preference levels:Table 2. Portlet modes and preferences
- The edit_defaults custom portlet mode is used to work directly on the shared preferences. In this case the personalized preferences level is not available.
- Similarly, the config mode is used to read and modify the administrator level of preferences.
- The deployment descriptor level of preferences can only change when the portlet is redeployed with a modified portlet.xml. It cannot be modified by portlet code.
Portlet mode Layer to which preference changes are written config Administrator preferences edit_defaults Shared preferences All other modes: edit, view, help Personalized preferences If a portlet wants to use these custom modes, they must be declared with <custom-portlet-mode> tags in the deployment descriptor. Entering one of these modes requires special access permissions. For details about access permissions refer to the appropriate sections. Portlets can enter these modes using the standard APIs for setting a portlet mode. These APIs are ActionResponse.setPortletMode and PortletURL.setPortletMode. However, normally the portlets do not need to do so, because the portal normally provides buttons in the portlet skin that allow to switch to these modes, if they are supported by the portlet. The administrator level of preferences for a particular portlet can also be modified without actually invoking the portlet itself by using the portlet management portlet.
Each call to PortletPreferences.store persists those values at the current preference level that were set by using setValue. Even if the value that is being set is identical to the currently applicable value, which has been set by the more general level, the new value is now stored at the current level and never inherited. That means, if you want to make use of the preferences hierarchy, so that later changes on a more general level are available (“shine through”) to the more specific levels, take care to set and store only those preferences that should not be inherited from the more general levels. Resetting of preferences as on the example above is done programmatically by using the reset method. This means that the value of the preference key that is reset will now be read from the next more general preference layer.
Notes:
- The reset of a preference is fundamentally different from setValue(null): the latter will hide any default value that was set on a more general level.
- If a preference is reset at all levels and has no value defined in portlet.xml, the default value passed to the getValue call will be returned.
Programming recommendations
The separation of preferences into different layers is mostly transparent to the portlet programmer. In the code, you access the aggregated preferences by using the PortletPreferences object. The portal will automatically select the appropriate values for the current user and portlet mode. The only place where the distinction of the preference layers becomes visible in a portlet is in the configuration views, that is in the portlet modes edit, edit_defaults, and config. The different preferences and the different modes in which they are presented determine which part of the portlet behavior can be customized by users and which part can only customized by editors or administrators.In practice, it is often difficult for the programmer to anticipate how a portlet will be used in a particular environment. In many cases it should rather be decided by an administrator which of the preferences can be customized and at which level they should be customized. Therefore, program portlets in such a way that these decisions are not determined by the code but, as far as possible, by the deployment descriptor. This makes it easier for the administrator later to determine to which extent and on which levels preferences can be customized. This can often be achieved by using the same code (and JSPs) for implementing all three configuration views, edit, edit_defaults, and config, and simply deactivating or hiding those configuration settings that cannot be modified in the current mode. Settings that can only be modified by administrators (config mode) can be determined by the read-only state that is defined in portlet.xml. There is no standard API that can be used to indicate which preferences should only be modified in the shared configuration and which preferences should be locked for users. If this is required, we recommend to keep a special (invisible) preference locked-pref-keys that holds a list of those preference keys that can only be modified in edit_defaults or config mode.
Code examples:As mentioned above, for the normal display of portlet, you do not need to distinguish whether a particular preference value is an administrator or a user setting. The portal will automatically select the appropriate values for the current user and portlet mode. Nevertheless, you need to consider the merging behavior for the different preference levels particularly in two scenarios:
- Define the preference names that should be locked for the user in the portlet.xml:
<preference> <name>locked-pref-keys</name> <value>allowed-folders</value> <value>folder</value> </preference>
- Verify that the preference is writable before allowing the user to change a preference value:
public boolean isWritable(String prefName) { PortletMode mode = request.getPortletMode(); if (mode.equals(CONFIG_MODE)) return true; PortletPreferences prefs = request.getPreferences(); if (prefs.isReadOnly(prefName)) return false; if (! mode.equals(EDIT_DEFAULTS_MODE)) { String [] lockedKeys = prefs.getValues("locked-pref-keys", null); if (lockedKeys != null && Arrays.asList(lockedKeys).contains (prefName)) return false; } return true; }
There are multiple options to resolve the second problem; it depends on the logic of portlet which of them is most appropriate:
- When you use multi-valued preferences, for example to store lists, no merging of values takes place; if the preference is personalized, the shared settings are simply hidden.
Example: To implement a scenario where, for example, an administrator defines a part of a bookmark list that all users must see, and users can personalize the list by adding or removing their own entries, you need to use separate keys for administrator and user preferences and merge the values explicitly in the code.
- When values for multiple preference keys depend on each other, you can run into problems if one of the keys is personalized while another is taken from a shared preference level. If the more general level is now changed, the new combination of shared and personalized values may become invalid. In the example above, the possible values for the database view obviously depend on the selected database. Therefore, if the administrator levels of preferences is changed from the Fish view of the Animals database to a Plants database and a Trees view, all the specializations for the database view become invalid: preferences for user U2 would still indicate the Reptiles view, but now on a Plants database.
- You can always set all the dependent preference keys in a single operation by setting all of them explicitly before the same call to store.
- You can even merge the dependent preference keys into a single string value. This is what you should do for combined values, for example x-y coordinates. This implies that no merging of preference levels can take place, therefore you cannot use this approach if you want to support a use case scenario in which administrator changes can be partially overridden by users.
- In other cases, it is more appropriate to accept the possibility of invalid preference combinations and just provide suitable error handling; for the example above, the portlet should simply be prepared to handle the fact that the specified database view may be invalid and reset that preference key to go back to a - hopefully valid - default that was set on a more general level.
- Another option to resolve this problem is the use of a PreferenceValidator to verify only valid preference combinations are available to the portlet. The following section Preference Validators describes how to do this.
Preference Validators
The Java Portlet Specification defines how a preference validator is defined in a portlet. If it is present, tools can use it to verify only valid preference combinations are saved for a portlet. WebSphere Portal uses a preference validator not only to validate preferences that are stored, but also to verify a change on a more general level has not invalidated the current view. Whenever a portlet retrieves its preferences in a particular context, the available combination of preference levels is validated, if necessary, and preference levels that have become invalid in combination with more general levels are ignored: they are not available to the portlet but are retained in the database. Therefore they can become available again when the conflicting preferences on the more general level are updated to be compatible again. This way you can isolate validation checking and let the portal take care of providing the display logic with valid data. To verify whether the selective hiding of preference levels works as expected, you can enable traces for the following trace string:com.ibm.wps.pe.pc.std.core.impl.WPPreferencesHierarchyImpl=low=enabledThis will generate trace logs for validation exceptions that occur during preference reads. Keep the following restrictions in mind when implementing a preference validator:
- A failed validation on preference access causes the complete conflicting level to be hidden. To be more selective about how preferences are made consistent, you need to use the following approach with self-contained preference validators.
- Preference validators are intended to be used also by standalone tools. Therefore they should be self-contained and not require a portal run time environment, network, or back end access etc. This means that a preference validator would not be suitable for the example above, that is for checking that the specified document really exists in the document database.
Compatibility with portlets that do not support the edit_defaults portlet mode
The Standard Portlet API supports the standard portlet modes edit, view, and help. Generic portlets that are written to comply with the Standard Portlet API support those portlet modes. But as they are not aware of the preference hierarchy implemented in WebSphere Portal, they usually do not support the custom portlet mode edit_defaults. Instead, they only support the standard portlet mode edit for customization. The same applies to portlets that were written to comply with the Standard Portlet API for a previous version of WebSphere Portal, in which the edit_defaults mode was not yet supported. Preference values that are set in any of the standard portlet modes are never shared between users, in accordance with the behavior assumed by the Java Portlet Specification, because they are always stored at the personalized preference level. Unfortunately, this behavior precludes even the required use case where an Editor wants to set up a read-only page for all users with the appropriate shared portlet configuration. Normally this would be done in the edit_defaults mode, but as the portlet does not support that mode, this is not possible.To enable editing of shared preferences on such portlets, WebSphere Portal provides a special compatibility mode, the edit_defaults_compatibility portlet mode. Like any other custom portlet mode, this mode must be explicitly enabled in the portlet deployment descriptor, but other than that, the portlet does not require any special coding. To the portlet, the compatibility mode will just appear as the standard edit mode that it already supports, but the API implementation will read and store the shared preference level instead. As the portlet code does not know about the compatibility mode, entering that mode is only possible from the icon or pull-down menu selection option that is provided on the portlet title bar. As the compatibility mode is mapped to edit mode for the portlet, a portlet that supports this mode must also support edit mode for the same content types in the portlet deployment descriptor. As an example, consider the following code snippet:
<supports> <mime-type>text/html</mime-type> <portlet-mode>edit</portlet-mode> <portlet-mode>edit_defaults_compatibility</portlet-mode> . . . . . </supports>In the standard portlet modes, such as edit, a portlet that supports the compatibility mode will still read and store personalized preferences only, and changes are not visible to other users. There is, however, a slight difference to the normal aggregation of preference layers: When a user personalizes the portlet, the preferences are stored in a private copy and not on a personalized layer. No merging takes place between shared and personalized preferences, and any subsequent changes on the shared preferences are not visible to a user who has personalized the portlet, no matter which preference keys are affected. This arrangement as been made to avoid issues with inconsistencies between dependent preference values, as portlet code might not be prepared to handle unexpected combinations of preference values resulting from the merging of shared and personalized levels (as described under Access preferences ).
As an example, assume that the database viewer portlet mentioned under Access preferences was written without support for config and edit_defaults modes, and allows you to customize all settings in the edit mode only. To set up the portlet on a shared page without requiring each user to customize it, its deployment descriptor has been modified to support the edit_defaults_compatibility mode. Editor E sets up the portlet on a shared page by using the compatibility mode to display the Mammals view from the Animals database with 10 lines per page. User U personalizes the portlet in edit mode to show 20 lines instead. At this point, a private copy of all preference keys is created, so if editor E changes the shared preferences to display the Reptiles view instead, U will continue to see the Mammals view when viewing the page.
This behavior is almost identical to Version 5.1 of WebSphere Portal, where the explicit distinction between shared and personalized preference levels, along with the support for the edit_defaults mode, did not yet exist. The only difference is that E must now explicitly enable and use the edit_defaults_compatibility mode for changing shared preferences, while in Version 5.1 the same behavior was implicitly chosen in edit mode, because E has the necessary access permissions to change the shared configuration visible to all users. The modes edit_defaults and edit_defaults_compatibility mode are mutually exclusive. A portlet can support only one of them at a time.
Related information
Parent
Understand the basics