Oracle® Fusion Middleware Developer's Guide for Oracle WebCenter Ensemble 10g Release 3 (10.3.0.1.0) E14115-02 |
|
![]() Previous |
![]() Next |
The following sections provide general information about Oracle WebCenter Ensemble pagelet development and configuration.
Oracle WebCenter Interaction Development Kit (IDK) Proxy API: The bea.alui.proxy package provides access to information about the environment in which the pagelet is displayed and the user currently accessing the pagelet, including session preferences associated with that user. This package also includes methods to implement security and access XML payloads.
The IDK includes a collection of Remote APIs that provide access to functionality within Oracle WebCenter Interaction, Oracle WebCenter Collaboration, and the portal Search Service. These APIs are supported by Oracle WebCenter Ensemble, and can be used by any pagelet deployed in an environment with access to these applications. For details, see Using Programmable Remote Client (PRC) Remote APIs.
Adaptive Pagelets: Adaptive pagelets allow you to create a coordinated page with dynamic, interactive functionality comprised of cross-platform services that talk to multiple back-ends.
Adaptive pagelet tools include the following:
Adaptive Tags: Adaptive Tags are used to display contextual data and control Oracle WebCenter Ensemble from remote pagelets. Unlike the Oracle WebCenter Interaction Development Kit (IDK), Adaptive Tags use XML in pagelet content instead of code, which avoids a network round trip. Tags can be included in the markup returned by any proxied page (HTML, JSP or ASP.Net). Using the attributes defined in the tag, the Oracle WebCenter Ensemble proxy transforms the XML and replaces it with standard HTML and/or executes the relevant operations. The Adaptive Tag collection currently includes libraries for use in both Oracle WebCenter Interaction and Oracle WebCenter Ensemble, as well as libraries that are specific to each environment. For details, see Adaptive Tags
Oracle WebCenter Interaction Scripting Framework: The Oracle WebCenter Interaction Scripting Framework is a client-side JavaScript library that provides services to pagelets and proxied pages. For details, see Oracle WebCenter Interaction Scripting Framework.
Session Preferences: Pagelets can use preferences to communicate with each other, but accessing preferences usually requires a round trip to a database. Session preferences provide a way to store and share settings in the user's session within the client browser.
Pagelet Caching: Caching is the functionality that allows Oracle WebCenter Ensemble to request pagelet content, save the content, and return the saved content to users when appropriate. The importance of caching cannot be overstated.
Pagelet Internationalization: These tips and best practices apply to all pagelets that will be translated into multiple languages.
Pagelet Configuration in Oracle WebCenter Ensemble: To deploy a pagelet in Oracle WebCenter Ensemble, you must configure Resource and Pagelet objects and configure security settings.
This section provides an introduction to the Oracle WebCenter Interaction Development Kit (IDK) Proxy API. For more details on objects and methods, see the API documentation. For details on Oracle WebCenter Interaction-specific portlet interfaces, see the Oracle Fusion Middleware Web Service Developer's Guide for Oracle WebCenter Interaction.
The bea.alui.proxy package/namespace includes the following interfaces:
IProxyContext
IProxyRequest
IProxyResponse
IProxyUser
In general, these interfaces are called in the following order:
A pagelet uses ProxyContextFactory.getInstance().createProxyContext
to initiate a connection for communicating with Oracle WebCenter Ensemble.
The IProxyContext
object returned allows the pagelet to access information about the request and response, the current user, and the session. The pagelet uses this information as needed, in arbitrary order, to generate a proper response. Using IProxyContext
, the pagelet can access IProxyRequest
, IProxyUser
, IRemoteSession
and IProxyResponse
.
The pagelet retrieves parameters from the request using IProxyRequest
.
The pagelet retrieves user information and preferences from IProxyUser
.
The pagelet can access functionality in Oracle WebCenter Interaction applications using IRemoteSession
. For details, see Adaptive Pagelet Design Patterns.
The pagelet constructs a response using IProxyResponse
. The response includes content to be displayed and any settings to be stored or removed.
For examples of using IProxy interfaces in a pagelet, see Creating a Custom Pagelet with the Java Oracle WebCenter Interaction Development Kit (IDK) Proxy API and Creating a Custom Pagelet with the .NET Oracle WebCenter Interaction Development Kit (IDK) Proxy API.
This example creates a simple pagelet that displays information from the proxy, including setting values.
Before writing any code, create a new Oracle WebCenter Interaction Development Kit (IDK) project as described in Java: Setting Up a Custom Oracle WebCenter Interaction Development Kit (IDK) Project in Eclipse.
In the new project, create a new JSP page for the pagelet (pagelet.jsp).
Implement your code. The pagelet code shown below instantiates the Oracle WebCenter Interaction Development Kit (IDK) and uses the IProxyContext
interface to retrieve IProxyRequest
and IProxyUser
objects to access information about the user and the settings associated with the pagelet.
Note: There is no need to include html, head and body tags; the display is handled by the Consumer resource. |
<%@ page language='java' import='com.bea.alui.proxy.*' %> <% String Att1 = 'no setting'; String Att2 = 'no setting'; String sessionVariable = 'no setting'; //get the idk IProxyContext proxyContext = ProxyContextFactory.getInstance().createProxyContext(request, response); IProxyRequest proxyRequest = proxyContext.getProxyRequest() IProxyUser proxyUser = proxyRequest.getUser(); String userName = proxyUser.getUserName(); int userID = proxyUser.getUserID(); Att1 = proxyRequest.getSetting('Att1') Att2 = proxyRequest.getSetting('Att2'); sessionVariable = proxyRequest.getSetting('sessionVar'); byte[] payload = proxyRequest.getPayload().getText(); String payloadStr = new String(payload) %> <p>User name: <%=userName%><br/> User ID: <%=userID%><br/> Attribute 1: <%=Att1%><br/> Attribute 2: <%=Att2%><br/> Session variable: <%=sessionVariable%><br/> Payload: <textarea name=xml cols=80 rows=6> <%=payloadStr%> </textarea> </p>
This example creates a simple pagelet that displays information from the proxy, including setting values. .NET pagelets use a code-behind page (.aspx.cs) to retrieve settings and a Web form (.aspx) to display the pagelet content.
Before writing any code, create a new Oracle WebCenter Interaction Development Kit (IDK) project as described in .NET: Setting Up a Custom Oracle WebCenter Interaction Development Kit (IDK) Project in Visual Studio.
In the new project, implement your code. The example below uses a code-behind page and a web form.
The code-behind page (IDKPagelet.aspx.cs) instantiates the Oracle WebCenter Interaction Development Kit (IDK) and uses the IProxyContext
interface to retrieve IProxyRequest
and IProxyUser
objects to access information about the user and the settings associated with the pagelet.
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using Plumtree.Remote.Portlet; using System.Xml; using System.Text; using Bea.Alui.Proxy; namespace IDKProxyWS { /// <summary> /// Hello World Pagelet /// </summary> public class IDKPagelet : System.Web.UI.Page { public String name; public bool isGuest; public int userID; public String envType; public String payload; public String Att1,Att2; public String SessionVar; private void Page_Load(object sender, System.EventArgs e { // Put user code to initialize the page here InitializeCSP(); } private void InitializeCSP() { IProxyRequest proxyRequest; IProxyResponse proxyResponse; IProxyUser proxyUser; IProxyContext proxyContext; ProxyContextFactory factory; HttpRequest request = HttpContext.Current.Request; HttpResponse response = HttpContext.Current.Response; try { factory = ProxyContextFactory.getInstance(); proxyContext = factory.CreateProxyContext(request, response); proxyRequest = proxyContext.GetProxyRequest(); proxyResponse = proxyContext.GetProxyResponse(); envType = proxyRequest.GetEnvironment().GetType().ToString(); proxyUser = proxyRequest.GetUser(); isGuest = proxyUser.IsAnonymous(); name= proxyUser.GetUserName(); userID = proxyUser.GetUserID(); Att1 = (String)proxyRequest.GetSetting('attr1'); Att2 = (String)proxyRequest.GetSetting('attr2'); Att2 = (String)proxyRequest.GetSetting('SessionVar'); byte[] bpayload = proxyRequest.GetPayload().GetText() System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding() payload = enc.GetString(bpayload) } catch(Bea.Alui.Proxy.NotGatewayedException e) { } } } #region Web Form Designer generated code ... #endregion }
The Web form that displays the pagelet (IDKPagelet.aspx) displays the information retrieved by the code-behind page above.
<%@ Page Language='c#' runat='server' CodeBehind='IDKPagelet.aspx.cs' AutoEventWireup='false' inherits='IDKProxyWS.IDKPagelet' %> <%@ import Namespace='System.Collections' %> <%@ import Namespace='System.Web' %> <%@ import Namespace='System.Web.UI' %> <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN' > <html> <head> <title>IDKPagelet</title> <meta name='GENERATOR' Content='Microsoft Visual Studio .NET 7.1'> <meta name='CODE_LANGUAGE' Content='C#'> <meta name='vs_defaultClientScript' content='JavaScript'> <meta name='vs_targetSchema' content='http://schemas.microsoft.com/intellisense/ie5'> </head> <body MS_POSITIONING='GridLayout'> <span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> Proxy Pagelet <BR> <% Response.Write('IDK Proxy Pagelet<BR>'); Response.Write('Environment Type ' + envType + '<BR>'); Response.Write('Guest User? ' + isGuest + '<BR>'); Response.Write('User Name: ' + name + '<BR>'); Response.Write('User ID: ' + userID + '<BR>'); Response.Write('<P>'); Response.Write('Pagelet Attributes:<BR>'); Response.Write('Attribute1: ' + Att1 + '<BR>'); Response.Write('Attribute2: ' + Att2 + '<BR>') Response.Write('SessionVar: ' + SessionVar + '<BR>') Response.Write('<P>') Response.Write('Pagelet XML Payload:<BR>'); Response.Write('<textarea name=xml cols=80 rows=6>' + payload + '</textarea>'); Response.Write('<P>'); %> </span> </body> </html>
The plumtree.remote.prc package includes a collection of APIs that provide access to functionality within Oracle WebCenter Interaction, Oracle WebCenter Collaboration, and the portal Search Service. These APIs are supported by Oracle WebCenter Ensemble, and can be used by any pagelet deployed in an environment with access to these applications.
PRC APIs free you from serializing SOAP messages and minimize the amount of data that travels between the portal and other servers, improving performance.
The PRC is included with both the Java and .NET versions of the Oracle WebCenter Interaction Development Kit (IDK). The Java version includes Apache AXIS 1.0; the .NET version uses the platform-native SOAP client stack. Java clients can call .NET portals and vice-versa; the PRC takes care of the communication between AXIS and .NET. Pagelets that use the PRC can be deployed in either Oracle WebCenter Interaction or Oracle WebCenter Ensemble. For details on using the PRC, see the Oracle Fusion Middleware Web Service Developer's Guide for Oracle WebCenter Interaction.
Adaptive pagelets allow you to create a coordinated page with dynamic, interactive functionality comprised of cross-platform services that talk to multiple back-ends. For detailed examples, see Adaptive Pagelet Design Patterns.
Adaptive pagelet tools include the following:
Adaptive Tags: Oracle WebCenter Ensemble provides a collection of useful XML tags that can be included in the markup returned by any proxied page, including pagelets. For details, see Adaptive Tags
Oracle WebCenter Interaction Scripting Framework: The Oracle WebCenter Interaction Scripting Framework is a client-side JavaScript library that provides services to pagelets and proxied pages. For details, see Oracle WebCenter Interaction Scripting Framework.
For additional information on adaptive pagelets, see Adaptive Pagelet Development Tips.
Adaptive pagelet design patterns provide solutions for broad classes of problems, and provide the base for a range of cross-platform services.
The Master-Detail design pattern uses two pagelets; users select an item from a list in one, and the details for that item are retrieved from the external resource and displayed in another. For example, a set of customers could be listed by name in the "master" pagelet. When the user clicks a name in this pagelet, the "detail" pagelet presents details about the item. The detail pagelet for a customer list could list all the important information about that customer, such as name, address, and phone number. This pattern assumes a tight coupling between the two pagelets; both the master pagelet and detail pagelet must be displayed on the same page. For details and sample code, see Session Preferences. For a looser coupling, use the Broadcast-Listener pattern.
The Broadcast-Listener design pattern is similar to the Master-Detail pattern, but assumes a loose coupling between pagelets. Users can select an item or perform some other action in a "broadcast" pagelet, which causes the content in other related "listener" pagelets to be redrawn. The major difference is that the Broadcast-Listener pattern relies on the Oracle WebCenter Interaction Scripting Framework to raise an event when an action is performed in the "broadcast" pagelet. One or more "listener" pagelets can respond to this event and update their content accordingly. For details and sample code, see Using Oracle WebCenter Interaction Scripting Framework Event Notification.
In Place Refresh allows you to refresh the content in a pagelet without refreshing the page. For details and sample code, see Using In-Place Refresh.
The Structured Response design pattern handles structured HTTP responses, typically encoded as XML. In many cases it can be expensive and inefficient to send large amounts of HTML back in response to some HTTP request, if only a small part of the user interface needs to be changed. This is especially true with more complex user interfaces. In these cases, the response can be encoded in XML. The client-side response handler can then parse the XML, and update the user interface (or perform some other action) based on that response. Use the Structured Response design pattern to redraw a small area of the user interface after making an HTTP request, or to access a simple HTTP/URI type web service from a pagelet. The example code below (structuredresponse_portlet.html) accesses an RSS feed from a selection of news sites.
<!-- jsxml includes --> <a id="imgServerHref" href="pt://images/plumtree" style="display:none"></a> <script type="text/javascript" src="pt://images/plumtree/common/private/js/PTLoader.js"></script> <script type="text/javascript"> var oImgServer = new Object(); oImgServer.location = document.getElementById('imgServerHref').href; var imageServerURL = document.getElementById('imgServerHref').href; var imageServerConnectionURL = oImgServer.location; new PTLoader(imageServerURL, imageServerConnectionURL).include('jsxml','en'); </script> <!-- jscontrols includes --> <link rel="stylesheet" type="text/css" href="/portal-remote-server/js/jscontrols/styles/css/PTMenu.css"/> <link rel="stylesheet" type="text/css" href="/portal-remote-server/js/jscontrols/styles/css/PTRichTextEditor.css"/> <script type="text/javascript" src="/portal-remote-server/js/jscontrols/strings/PTControls-en.js"></script> <script type="text/javascript" src="/portal-remote-server/js/jscontrols/PTControls.js"></script> <!-- Inline JS helper functions --> <!-- NOTE: It is standard practice to use namespace tokens (e.g., <pt:nameSpace pt:token="$$TOKEN$$" xmlns:pt="http://www.plumtree.com/xmlschemas/ptui/"/>) to ensure unique global JavaScript function and object names. For simplicity, we do not do that here. --> <script defer type="text/javascript" id="structured-response-portlet-A-script"> // Function that gets the RSS XML feed found at the specified url getRSSFeed = function(url) { // First clear out any existing rows in the table channelTable.clearRows(); // Force the transformer to fix up the url var oURL = new Object(); oURL.location = url; // Do the http get var get = new PTHTTPGETRequest(oURL.location, handleRSSResponse); get.invoke(); } // Function that handles the RSS XML response and updates the table based on the RSS items handleRSSResponse = function(response) { // Get the rss xml var xml = response.responseText; if (!xml || xml.indexOf('<?xml') == -1) { return; } // Parse into a dom, and get the channel node var xmlDOM = new PTXMLParser(xml); var rssNode = xmlDOM.selectSingleNode('rss'); var channelNode = rssNode.selectSingleNode('channel'); // Get the channel title and set the status bar text in the table var channelTitle = channelNode.selectSingleNode('title').getNodeValue(); channelTable.statusBarText = '<b>Loaded Channel</b>: ' + channelTitle; // Get channel item nodes var itemNodes = channelNode.selectNodes('item'); // Build table rows channelTable.rows = new Array(); for (var i=0; i<itemNodes.length; i++) { var itemNode = itemNodes[i]; // Get channel item properties var itemTitle = itemNode.selectSingleNode('title').getNodeValue(); var itemLink = itemNode.selectSingleNode('link').getNodeValue(); var itemDescription = itemNode.selectSingleNode('description').getNodeValue(); if (itemNode.selectSingleNode('author')) var itemAuthor = itemNode.selectSingleNode('author').getNodeValue(); if (itemNode.selectSingleNode('category')) var itemCategory = itemNode.selectSingleNode('category').getNodeValue(); if (itemNode.selectSingleNode('pubDate')) var itemPubDate = itemNode.selectSingleNode('pubDate').getNodeValue(); // Create a row and add it to the table var row = new PTRow(); row.parent = channelTable; row.id = i; row.uid = i; row.previewText = itemDescription; row.link = itemLink; row.columnValues[0] = new PTTextColumnValue(itemTitle); row.columnValues[1] = new PTTextColumnValue(itemCategory); row.columnValues[2] = new PTTextColumnValue(itemAuthor); row.columnValues[3] = new PTTextColumnValue(itemPubDate); channelTable.rows[channelTable.rows.length] = row; } // Redraw the table channelTable.draw(); } </script> <b>Select RSS Feed:</b> <a href="#" onclick="getRSSFeed('http://www.wired.com/news/feeds/rss2/0,2610,,00.xml'); return false;">Wired News</a> <a href="#" onclick="getRSSFeed('http://news.com.com/2547-1_3-0-5.xml'); return false;">CNET News.com</a> <a href="#" onclick="getRSSFeed('http://partners.userland.com/nytRss/nytHomepage.xml'); return false;">NY Times</a> <br><br> <!-- Set up a table control to display channel items --> <div id="channelTableContainer"></div> <script defer type="text/javascript"> var channelTable = new PTTableControl(); channelTable.locale = 'en_US'; channelTable.objName = 'channelTable'; channelTable.container = 'channelTableContainer'; channelTable.baseURL = '/imageserver/plumtree/common/private/portal-remote-server/js/jscontrols/1/'; channelTable.statusBarText = 'No RSS Feed Selected'; channelTable.rowDetailAction = new PTJavaScriptAction('window.open(\'${ROW.link}\');'); channelTable.columns[0] = new PTColumn(); channelTable.columns[0].name = 'Title'; channelTable.columns[0].width = '40%'; channelTable.columns[1] = new PTColumn(); channelTable.columns[1].name = 'Category'; channelTable.columns[1].width = '20%'; channelTable.columns[2] = new PTColumn(); channelTable.columns[2].name = 'Author'; channelTable.columns[2].width = '20%'; channelTable.columns[3] = new PTColumn(); channelTable.columns[3].name = 'Publication Date'; channelTable.columns[3].width = '20%'; channelTable.areColumnsResizable = true; channelTable.clientSortEnabled = true; channelTable.scrollHeight = 250; channelTable.init(); channelTable.draw(); </script> </div>
Oracle WebCenter Ensemble provides a collection of useful XML tags that can be included in the markup returned by any proxied page, including pagelets.
Using the attributes defined in the tag, the proxy transforms the XML and replaces it with standard HTML to be displayed in a browser. For example, when used in a pagelet, the following code is replaced with the date and time in the current user's locale.
<pt:standard.currenttime xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/>
The adaptive tag libraries provide access to a wide range of components.
The core tag library provides two basic tags to support core tag functionality.
pt:core.debugmode
toggles debug mode.
pt:core.html
allows you to use HTML tags within JavaScript, and supports attribute replacement.
The tags in the constants library provide access to useful URLs, including the stylesheet, Image Service, and the correct return URL for the current user.
Table 2-1 Tags in the constants Library
Tag | Replaced with | Example |
---|---|---|
The stylesheet URL in proxied pages and pagelets |
|
|
The URL to the Image Service |
|
|
A URL that returns users to the page from which they came (the page on which the pagelet that launched the page is hosted) |
|
|
The common tag library provides access to useful functionality, including URL transformation and namespace definition. This library also allows you to insert error information in the page, and CSS and JavaScript references in the Head element in a proxied HTML page. For details, see Common Adaptive Tag Library (pt:common).
The tags in the logic library handle basic logic, including creating data objects and collections, setting shared variables, and looping over a data collection. For details, see Logic Adaptive Tag Library (pt:logic).
In addition to the tags above, platform-specific tags are available to access additional information and functionality in Oracle WebCenter Ensemble. For details, see Oracle WebCenter Ensemble Adaptive Tag Library (pt:ensemble).
For important information about using tags, see the following sections:
For information on how Oracle WebCenter Ensemble processes tags, see About Adaptive Tag Control Flow.
You can also create custom tags; for details, see Creating Custom Adaptive Tags.
For a full list of tags and attributes, see the tagdocs.
These syntax rules and tips apply to all adaptive tags.
All tags are XML compliant. For example, only strings are allowed; you cannot use a tag within an attribute of another tag (<legal a=<illegal/>/>
).
All adaptive tags belong to the namespace http://www.plumtree.com/xmlschemas/ptui/. The namespace prefix must be "pt" (xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/). To avoid including the namespace in every tag, enclose all tags in a span that defines the namespace.
All adaptive tag attributes require the "pt:" prefix. If you do not include the pt prefix, Oracle WebCenter Ensemble will not return an error, but will replace the attribute with the default value when the tag is processed.
The adaptive tag framework displays tag errors as HTML comments. If you suspect that a tag error has occurred, simply view the HTML source for the page. If there was a problem, there should be an HTML comment where the adaptive tag would have been.
Adaptive tags adhere to XHTML specifications. These specifications are not handled correctly by all HTML editors and IDEs. Some editors do not display tags correctly because of the required "pt:" prefix before tags.
Use tag debug mode for additional insight into tag errors. Turning on Debug Mode causes the adaptive tag framework to output HTML comments declaring the start and end of each tag. This can be useful for determining whether a tag ran and did not output the expected result, or did not run at all, for example. Note: Standard HTML tags are not wrapped in HTML comments.
Adaptive tag attribute value replacement allows you to display localized content based on the current user's locale.
Oracle WebCenter Ensemble stores internationalized strings in localized string files with different files for each supported language. Oracle WebCenter Ensemble knows the locale of the current user and retrieves strings from the correct language folder automatically. To internationalize a pagelet, move all strings into custom string files and translate them.
To display content in the pagelet, reference the strings using the value tag from the Logic tag library. As noted above, Oracle WebCenter Ensemble retrieves the string from the correct language folder automatically. For example, the HTML below retrieves the first string from a XML language file called my_message_file.xml.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:logic.value pt:value="$#1.my_message_file"/> </span>
For details on tags in the Logic tag library, see Logic Adaptive Tag Library (pt:logic).
Adaptive tag attribute value replacement allows you to access data stored in memory.
The following simple example uses the variable and value tags from the Logic tag library to store a value in memory and then display it in HTML.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:logic.variable pt:key="test" pt:value="example text"/> <pt:logic.value pt:value="$test"/> </span>
Attribute value replacement can also be used to display more complicated memory structures. Data objects can contain multiple name value pairs. The following example creates a data object with the name and URL of a link, and then displays the name.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:logic.data pt:key="testdata" url="http://www.myco.com" name="My company"/> <pt:logic.value pt:value="$testdata.name"/> </span>
Attribute value replacement cannot be used with tags outside the adaptive tag libraries. However, the pt.core.html tag supports attribute replacement within a tag and allows you to generate any HTML tag. Use the pt:tag attribute to specify the HTML tag and list the necessary HTML attributes as XML attributes. All non-adaptive tag attributes (attributes not prefixed with "pt:") are included automatically in the outputted HTML tag. For example, the following code creates an HTML anchor tag using an in-memory value for the "href" attribute.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:core.html pt:tag="a" href="$myurl" title="My title">My link</pt:core.html> </span>
This code would be transformed to the following HTML: <a href="[data stored in the $myurl attribute]" title="My title">My link</a>
.
The example below combines several different techniques and tags to show how to loop over a data collection and output HTML. This code outputs several HTML links with lines in between them.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:logic.collection pt:key="testcollection"> <pt:logic.data url="http://www.myco.com" name="My company"/> <pt:logic.data url="http://www.otherco.com" name="Other company"/> </pt:logic.collection> <pt:logic.foreach pt:data="testcollection" pt:var="link"> <pt:core.html pt:tag="a" href="$link.url"> <pt:logic.value pt:value="$link.name"/> </pt:core.html> <pt:logic.separator><br><br></pt:logic.separator> </pt:logic.foreach> </span>
For details on Logic tags, see Logic Adaptive Tag Library (pt:logic). For details on using localized strings in tags, see Using Internationalized Strings in Adaptive Tags.
The Oracle WebCenter Ensemble tag library (pt:ensemble) provides tags to insert pagelets in Oracle WebCenter Ensemble consumer pages and access authentication and role information for Oracle WebCenter Ensemble resources.
Table 2-2 Tags in the Oracle WebCenter Ensemble Adaptive Tag Library
Tag | Function | More Information |
---|---|---|
|
Injects the output of the specified pagelet into the page. |
Inserting Pagelets Using Oracle WebCenter Ensemble Adaptive Tags |
|
Stores data for a specific Oracle WebCenter Ensemble resource, if available, in memory as a data object containing information about the resource. |
Accessing Resource Data Using Oracle WebCenter Ensemble Adaptive Tags |
|
Stores a list of available authentication sources for the currently requested resource in memory. |
Accessing Authentication Data Using Oracle WebCenter Ensemble Adaptive Tags |
|
Stores the URL prefix for the login page in memory using the given key and scope. |
Accessing the Login URL Using Oracle WebCenter Ensemble Adaptive Tags |
|
Evaluates a role expression and stores the result as a boolean in memory. Designed to work with the |
Accessing User Roles Using Oracle WebCenter Ensemble Adaptive Tags |
|
Stores a list of the roles for the current user in memory. |
Accessing User Roles Using Oracle WebCenter Ensemble Adaptive Tags |
|
Notifies Oracle WebCenter Ensemble that the current user should be logged out of all resources. Used as singleton only (does not display the contents of the tag). |
The pt:ensemble.inject
tag injects the output of the specified pagelet into the page.
The pagelet is referenced by the fully qualified name of the pagelet as defined in Oracle WebCenter Ensemble, in the form libraryname:pageletname
. Any non-Oracle WebCenter Ensemble attributes (not prefixed with "pt:") will be passed on to the pagelet. Any HTML content inside the pagelet tag will be passed to the pagelet as an XML payload.
<pt:ensemble.inject pt:name="mylibrary:mypagelet" pagelet-attribute="A pagelet attribute"> <?xml version="1.0" encoding="utf-8"?> <doc>This is an XML payload.</doc> </pt:ensemble.inject>
To forward query string parameters from the resource request to the pagelet, set the optional parameter pt:forwardparams to 'true' as shown in the example below.
<pt:ensemble.inject pt:name="lib:pagelet" pt:forwardparams="true"/>
Note: Some internal Oracle WebCenter Ensemble parameters are not forwarded, including SSO cookes and login redirects. Query string parameters that attempt to override any registered pagelet parameters are not forwarded. |
When a pagelet request results in a 403, 404 or any other error code, Oracle WebCenter Ensemble can forward the error code and the error page itself to the browser for display to the user. To enable this option, set the attribute pt:onhttperror to one of the following values:
comment (default)
inline
fullpage
For an example of using this code, see Creating a Custom Pagelet with the Java Oracle WebCenter Interaction Development Kit (IDK) Proxy API or Creating a Custom Pagelet with the .NET Oracle WebCenter Interaction Development Kit (IDK) Proxy API.You can also insert pagelets into non-proxied pages; for details, see Inserting Pagelets into Non-Proxied Pages.
The pt:ensemble.authsourcedata
tag stores a list of available authentication sources for the currently requested resource in memory.
The data is stored as a collection, and each item in the collection is a data object containing information about the authentication source (prefix, name, description) accessible through the data object dot notation ($curauth.name
).
<pt:ensemble.authsourcedata pt:key="sources"/> <pt:logic.foreach pt:data="sources" pt:var="source"> <pt:logic.value pt:value="$source.prefix"/> <pt:logic.value pt:value="$source.name"/> <pt:logic.value pt:value="$source.description"/> <pt:logic.separator><br>-----<br></pt:logic.separator> </pt:logic.foreach>
This example uses logic tags to display information about each authentication source. For details on logic tags, see Logic Adaptive Tag Library (pt:logic).
The pt:ensemble.loginlink
tag stores the URL prefix for the login page in memory using the given key and scope.
The login prefix will end with a forward slash. This login prefix should be followed by the page suffix for the page that should be displayed after login. For example, if the external URL prefix of the resource is http://www.ensemble.com/app/ and the desired page after login is http://www.ensemble.com/app/pages/mainpage.html, then the full login link would be made by adding pages/mainpage.html to the login link prefix.
<pt:ensemble.loginlink pt:level="4" pt:key="loginurlprefix"/> var loginLink = "<pt:logic.value pt:value="$loginurlprefix"/>" + "pages/mainpage.html";
The pt:ensemble.resourcedata
tag stores data for a specific Oracle WebCenter Ensemble resource, if available, in memory as a data object.
The data object contains information about the resource (name, description, urlprefix, secureurlprefix) accessible through the data object dot notation ($resource.name
). If the resource does not have a description, urlprefix, or secureurlprefix, the data will not be available.
<pt:ensemble.resourcedata pt:name="Welcome Resource" pt:key="resource"/> <pt:logic.value pt:value="$resource.name"/> <pt:logic.value pt:value="$resource.description"/> <pt:logic.value pt:value="$resource.urlprefix"/> <pt:logic.value pt:value="$resource.secureurlprefix"/>
The role*
tags in the Oracle WebCenter Ensemble tag library allow pagelets to modify content based on the role of the current user.
For details on roles, see About Oracle WebCenter Ensemble Security.
The pt:ensemble.roleexpr
tag evaluates a role expression and stores the result as a boolean in memory. This tag is designed to work with the pt:logic.if
tag as shown below.
<pt:ensemble.roleexpr pt:expr="hasRole Default Role from Seed State" pt:key="boolvalue"/> <pt:logic.if pt:expr="$boolvalue"> <pt:logic.iftrue> <!-- This is displayed if expr evaluates to true. --> </pt:logic.iftrue> <pt:logic.iffalse> <!-- This is displayed if expr evaluates to false. --> </pt:logic.iffalse> </pt:logic.if>
The pt:ensemble.rolelist
tag stores a list of the roles for the current user in memory. The data is stored as a collection, and each item in the collection is a variable containing the role name. This can be used with the logic.foreach
tag to iterate over role data as shown below.
<pt:ensemble.rolelist pt:key="roles"/> <pt:logic.foreach pt:data="roles" pt:var="role"> <pt:logic.value pt:value="$role"/> <pt:logic.separator></pt:logic.separator> </pt:logic.foreach>
For details on logic tags, see Logic Adaptive Tag Library (pt:logic).
The Common tag library (pt:common) provides access to useful functionality, including URL transformation and namespace definition. This library also allows you to insert error information in the page, and CSS and JavaScript references in the Head element in a proxied HTML page.
The Common tag library is a cross-platform tag library that can be used in both Oracle WebCenter Interaction and Oracle WebCenter Ensemble.
For a full list of tags and attributes, see the tagdocs.
Table 2-3 Tags in the Common Adaptive Tag Library
Tag | Function | More Information |
---|---|---|
|
Defines a token for use in JavaScript functions and HTML elements to ensure unique names in an aggregated page. |
Defining a Unique Namespace Token Using Adaptive Tags |
|
Transforms URLs that should be proxied. |
Transforming URLs Using Adaptive Tags |
|
Disables and enables transformation on a proxied page. |
Transforming URLs Using Adaptive Tags |
|
Displays errors on the page so that they can be placed and formatted as desired. |
Displaying Errors Using Adaptive Tags |
|
Stores a collection of the current error codes in memory. |
Displaying Errors Using Adaptive Tags |
|
Displays the current error text on the page so that it can be placed and formatted as desired. Only the first error message will be displayed. Used as singleton only (does not display the contents of the tag). |
Displaying Errors Using Adaptive Tags |
|
Allows JavaScript and Style Sheet include information to be added to a specific point in the Head element of an HTML page, as required by the XHTML specification. |
Adding Header Content Using Adaptive Tags |
|
Marks JavaScript and CSS information to be included in the Head element of the HTML page by the pt:common.headincludes tag. |
Adding Header Content Using Adaptive Tags |
|
Displays a specific user information setting. |
Accessing User Information Using Adaptive Tags |
You can use the pt:common.userinfo t
ag to access specific user information settings.
The pt:common.userinfo
tag is replaced with the value of the User Information setting specified in the pt:info
attribute. The name attribute is case sensitive.
<pt:common.userinfo pt:info="FullName" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/>
Note: You must configure the Resource to send the appropriate user information settings to the pagelet. |
The pt:common.includeinhead
and headincludes
tags allow you to include custom JavaScript and CSS information in the Head element of the HTML page.
The pt:common.includeinhead
tag marks the JavaScript and CSS information to be included in the Head element of the HTML page by the pt:common.headincludes
tag. If a .js or .css file is marked for inclusion multiple times, it will only be included once. JavaScript generated by tags will also be included.
Note: This tag will be ignored during automatic in-place refresh requests. Custom in-place refresh solutions must ensure that JavaScript gets included correctly. |
<pt:common.includeinhead> <script type="text/javascript"><!-- JavaScript --></script> <script type="text/javascript" src="http://test.com/test.js"></script> <link type="text/css" rel="stylesheet" href="http://test.com/test.css"></link> </pt:common.includeinhead>
The pt:common.headincludes
tag adds JavaScript and stylesheet include information defined by the pt:common.includeinhead
tag to the Head element of the HTML page, as required by the XHTML specification. If no pt:common.headincludes
tag is present, JavaScript will be included at the bottom of the Head element, and a Head element will be inserted if one does not exist.
<head> <script type="text/javascript" src="http://test.com/main.js"></script> </head>
It is an established best practice to include the pagelet ID in the name of any JavaScript functions and HTML elements to ensure unique names when the code is combined with markup from other pagelets on an aggregated page.
The pt:common.namespace
tag allows you to define your own token, which is replaced with the pagelet ID. The token must follow these specifications:
Valid values for the token must be in the ASCII range 0x21 to 0x7E, excluding "<" (0x3C).
The scope of the token runs from the tag defining it to the end of the file; you cannot use a token prior to defining it.
A second pt:namespace tag with a different token redefines it; two tokens cannot be defined at the same time.
<pt:common.namespace pt:token="$$TOKEN$$" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/> <a onclick="doStuff$$TOKEN$$();" href="#">do stuff</a> <script> function doStuff$$TOKEN$$() { alert("hello"); } </script>
The error* tags in the Common library allow you to insert and format error messages within the page that contains the tag(s).
The pt:common.error
tag displays errors on the page, placed and formatted as desired. If the pt:common.errortext
tag is included inside this tag, the contents of the tag will only be processed if there is an error. If the child tag is not present, any error messages will be formatted and displayed from this tag in the standard style.If the pt:common.errortext
tag is included, only the first error message will be displayed. Other errors, as well as exception stack traces and extended error messages, will be ignored. The pt:common.errorcodes
tag stores a collection of the current error codes in memory. If the error has already been displayed, no error codes will be available. These error codes can be accessed using the pt:logic.foreach
tag as shown below.
Note: If these tags are displayed on a page, errors will no longer be displayed in the normal error location and will not be available after the tag has been displayed. |
<pt:common.errorcode pt:key="errorcodes"/> <pt:logic.foreach pt:data="errorcodes" pt:var="code"> <pt:common.errortext/>
The pt:common.url
and pt:common.transformer
tags allow you to create and manipulate proxiedURLs.
The pt:common.url
tag is used to transform URLs that should be proxied. If the URL in the pt:href
attribute is outside the proxied Resource, it will be transformed to an absolute URL. This feature does not generate a link in HTML; it obtains the URL as a string and passes it to a client-side function, as shown in the following example.
<script> function myFunction() { document.write("<pt:common.url pt:href="myURL" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/>"); }
The pt:common.transformer
tag allows you to turn off JavaScript URL transformation in a proxied page. Set the pt:fixurl
attribute to "off" as shown below.
<pt:common.transformer pt:fixurl="off" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/>
The transformer will not insert calls to the JavaScript URL transformation function for the rest of the file, unless you switch the feature back on in a subsequent directive (with a pt:fixurl
attribute of "on").
Logic tags handle basic logic, including creating data objects and collections, setting shared variables, evaluating expressions, and looping over a data collection.
The pt:logic tag library is a cross-platform tag library that can be used in both Oracle WebCenter Interaction and Oracle WebCenter Ensemble.
Note: Many logic tags have apt:scope attribute. The valid scope values are: tag, portlet request (pagelet request), http request, session, persistent session, and application. The default is portlet request scope. |
For a full list of tags and attributes, see the tagdocs.
Table 2-4 Tags in the Logic Adaptive Tag Library
Tag | Function | More Information |
---|---|---|
|
Creates a data object (collection of name=value pairs) and stores it in a shared variable using the key supplied. |
Using Shared Variables in Adaptive Tags |
|
Concatenates two values into one and sets the new value in a variable with a specified name. |
Using Shared Variables in Adaptive Tags |
|
Stores a shared variable using the key and value supplied. Designed for use with attribute replacement or with the |
Using Shared Variables in Adaptive Tags |
|
Creates a collection of data objects and stores it in a shared variable using the key supplied. |
Using Shared Variables in Adaptive Tags |
|
Evaluates the length of a collection and stores the result in memory. |
Using Shared Variables in Adaptive Tags |
|
Evaluates an attribute and displays the referenced value. Used as singleton only (does not display the contents of the tag). |
Using Shared Variables in Adaptive Tags |
|
Evaluates a boolean expression and stores the result as a boolean in memory. Designed to work with the |
Evaluating Expressions Using Adaptive Tags |
|
Evaluates an integer expression and stores the result as a boolean in memory. Designed to work with the |
Evaluating Expressions Using Adaptive Tags |
|
Evaluates whether or not two strings are equal and stores the result as a boolean in memory. The case must match. Designed to work with the |
Evaluating Expressions Using Adaptive Tags |
|
Checks if a collection contains a specific data element and sets a specified variable to true or false. Designed to work with the |
Evaluating Expressions Using Adaptive Tags |
|
Evaluates an expression and displays either the |
Evaluating Expressions Using Adaptive Tags |
|
Displayed if the surrounding |
Evaluating Expressions Using Adaptive Tags |
|
Displayed if the surrounding |
Evaluating Expressions Using Adaptive Tags |
|
Allows looping over a data collection. Supports tag and portlet request scope only. |
Looping Over Data Collections Using Adaptive Tags |
|
Inserts a separator between the elements of a for each loop. |
Looping Over Data Collections Using Adaptive Tags |
The pt:logic.boolexpr,
intexpr
, stringexpr
and containsexpr
tags work with the pt:logic.if
tag to evaluate a range of expressions.
The sample code below determines whether the current value for the variable "title" is set to "Administrator". Variables can be set using the pt:logic.data
or pt:logic.variable
tags.
<pt:logic.stringexpr pt:expr="($title) == Administrator" pt:key="boolvalue"/> <pt:logic.if pt:expr="$boolvalue"> <pt:logic.iftrue> This is displayed if expr evaluates to true. </pt:logic.iftrue> <pt:logic.iffalse> This is displayed if expr evaluates to false. </pt:logic.iffalse> </pt:logic.if>
For details on using shared variables, see Using Shared Variables in Adaptive Tags.
The pt:logic.foreach
tag allows you to loop over collections of data.
The sample code below creates a table to store links for a navigation menu.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <table cellpadding="5" cellspacing="0" width="100%" border="0"> <!-- loop starts here --> <pt:logic.foreach pt:data="directorymenu" pt:var="temp"> <tr> <td height="25" colspan="3" class="navSidebarText"> <pt:core.html pt:tag="img" src="$temp.img" alt="" border="0" align="absmiddle" height="20" width="20" /> <pt:core.html pt:tag="a" href="$temp.url"> <pt:logic.value pt:value="$temp.title" /> </pt:core.html> </td> </tr> </pt:logic.foreach> </table> </span>
This table can then be populated with links.
The pt:logic.data
, variable
, and collection
tags allow you to store editable shared variables, which can be used in attribute value replacement or with the pt:logic.value
tag.
The pt:logic.data
tag stores a data object (a name=value pair) as an editable shared variable using the key passed in. The pt:logic.variable
tag stores an editable shared variable using the key and value passed in. If either tag is used inside the pt:logic.collection
tag, the variables are stored directly in the parent collection. If the tag is used alone, the key attribute is required. The variable is only stored after the tag is finished processing all its contents. A collection can only contain a single type of variable, such as string variables or data objects.
Note: If a variable or collection with the same name already exists, it will be overwritten. If the preexisting variable is not editable, the tag will fail. Variable names cannot contain the reserved character '.'. |
<pt:logic.variable pt:key="title" pt:value="Administrator"/> <pt:logic.data pt:key="myurl" name="Home" url="http://edocs.bea.com"/> <pt:logic.collection pt:key="testcollection"> <pt:logic.data url="http://www.myco.com" name="My company"/> <pt:logic.data url="http://www.otherco.com" name="Other company"/> </pt:logic.collection> <pt:logic.collection pt:key="teststringcollection"> <pt:logic.variable pt:value="my string data"/> <pt:logic.variable pt:value="my other string data"/> </pt:logic.collection>
The pt:logic.value
tag displays the value of the variable referenced by the pt:value
attribute. Variables can be set using the pt:logic.data
or pt:logic.variable
tags as explained in the previous section. This tag can be used to reference localized strings in message files.
<pt:logic.value pt:value="$title"/> <pt:logic.value pt:value="$myurl.Home"/>
For details on referencing localized strings using tags, see Using Internationalized Strings in Adaptive Tags.
This page describes the control flow of a typical request that makes use of adaptive tags.
First, the proxied page requests pagelet data from the transformer.
The transformer retrieves the requested pagelets from the external resources. Native UI tags, such as JSP Tags or .NET Web controls, are processed on the external resource before the HTML is returned to the transformer.
The transformer converts the HTML into markup data including both HTML and adaptive tags. This markup data is passed to the Tag Transformation Engine, which processes the tags and converts them into standard HTML.
Finally, the HTML is returned to the page where it is displayed to the end user.
The Tag Transformation Engine converts markup data from the transformer into a tree of HTML and adaptive tags. The Engine moves through the tree and outputs HTML and processes the tags. When a tag is processed, it can cause all of its child nodes to be processed, or it can skip that entire section of the tree.
The figure below shows an example of a tree. In this example, when the choose
tag is executed, it determines whether or not the current user matches the conditions in the choose clause. If it does, the when
tag will display the HTML inside the tag. If not, the otherwise
tag will display its HTML
Figure 2-2 Tag Transformation Engine Tree
For details on these tags, see Logic Adaptive Tag Library (pt:logic).
The Adaptive Tag Framework allows you to create custom tags for use in pagelets and proxied pages.
The ATag
class is the base class used to write custom tags. To implement a custom tag, follow the steps below.
To implement a new tag, you must have a tag library. A tag library is simply a .jar or .dll file with exactly one class that implements ITagLibraryMetaData
.
Java
public static final TagLibraryMetaData LIBRARY = new TagLibraryMetaData ("Sample Tags", "sample", "This library provides sample tags.", 1.0);
.NET
public static readonly TagLibraryMetaData LIBRARY = new TagLibraryMetaData ("Sample Tags", "sample", "This library provides sample tags.", 1.0);
Create one public static final ITagMetaData
member variable that provides the name and description of the tag. Create a public static final RequiredTagAttribute
or OptionalTagAttribute
member variable for every attribute that the tag supports. You can also use standard HTML and XML attributes; see Using Variables in Adaptive Tags.
Java
public static final ITagMetaData TAG; public static final RequiredTagAttribute MESSAGEATTRIBUTE; public static final OptionalTagAttribute LOCATIONATTRIBUTE; static { TAG = new TagMetaData("hellolocation", "This tag displays a hello message for the given location."); MESSAGEATTRIBUTE = new RequiredTagAttribute( "message", "The message to display for hellolocation tag", AttributeType.STRING); LOCATIONATTRIBUTE = new OptionalTagAttribute("location", "The sample location attribute for hellolocation tag", AttributeType.STRING, "World"); }
.NET
public static readonly ITagMetaData TAG; public static readonly RequiredTagAttribute MESSAGEATTRIBUTE; public static readonly OptionalTagAttribute LOCATIONATTRIBUTE; static HelloLocationTag() { TAG = new TagMetaData("hellolocation", "This tag displays a hello message for the given location."); MESSAGEATTRIBUTE = new RequiredTagAttribute( "message", "The message to display for hellolocation tag", AttributeType.STRING); LOCATIONATTRIBUTE = new OptionalTagAttribute("location", "The sample location attribute for hellolocation tag", AttributeType.STRING, "World"); }
Type validation is performed by the tag framework automatically. If an optional attribute is not present in the HTML, the tag framework will use the default value. In the same code below, the optional attribute has a default value of "World.".
Implement the DisplayTag
abstract method. Use this method to create and display HTML. To display any HTML and tags defined within the tag, call ProcessTagBody
and return the resulting HTML. The sample code below adds the "Hello" string with a user-specified location to an HTMLElement
and returns it to be displayed.
Java
public HTMLElement DisplayTag() { String strLocation = GetTagAttributeAsString(LOCATIONATTRIBUTE); String strMessage = GetTagAttributeAsString(MESSAGEATTRIBUTE); HTMLElementCollection result = new HTMLElementCollection(); result.AddInnerHTMLString(strMessage + strLocation + "!"); return result; }
.NET
public override HTMLElement DisplayTag() { String strLocation = GetTagAttributeAsString(LOCATIONATTRIBUTE); String strMessage = GetTagAttributeAsString(MESSAGEATTRIBUTE); HTMLElementCollection result = new HTMLElementCollection(); result.ddInnerHTMLString(strMessage + strLocation + "!"); return result; }
If the tag should not display any HTML contained within the tag, use the GetTagType
method to return TagType.NO_BODY.
Java
public TagType GetTagType() { return TagType.NO_BODY; }
.NET
public override TagType GetTagType() { return TagType.NO_BODY; }
Implement the Create
abstract method to return a new instance of the tag.
Java
public ATag Create() { return new HelloLocationTag(); }
.NET
public override ATag Create() { return new HelloLocationTag(); }
The ATag
class allows you to include a wide range of functionality in custom tags. For a full list of interfaces and methods, see the tagdocs. For details on deploying your custom tag, see Deploying Custom Adaptive Tags.
To access browser session information from a custom adaptive tag, use the IEnvironment
class.
The IEnvironment
class provides access to information about the current request and user, including the following:
HTTP Request and Response: Retrieve the Request or Response objects, or the Request URL. For example: IXPRequest request = GetEnvironment().GetCurrentHTTPRequest();
User information: Retrieve the user's session, or key information including language, locale, time zone, and access style (standard, 508, or low bandwidth). For example: String strTZ = GetEnvironment().GetTimeZone();
VarPacks: Retrieve any VarPacks associated with the application in which the tag is executed.
To access attributes used in a custom tag, use one of the GetTagAttribute*
methods.
All basic data types are supported as attributes (defined in the AttributeType
class), including boolean, char, double, int, long and string. The "pt:" attributes specify the logic for the tag, while any non-pt attributes specify the behavior of the resulting HTML tag. Non-pt attributes are only applicable in tags that output a simple HTML tag.
To access pt attributes, use the appropriate GetTagAttributeAs*
method using the attribute name. A method is provided for each supported attribute type, e.g., GetTagAttributeAsLong
. The GetTagAttribute
method is provided for backwards compatibility and should not be used.
First, define the attribute: MODE = new OptionalTagAttribute("mode", "Turns debug mode on and off.", AttributeType.BOOLEAN, "true");
Then, access the attribute in the DisplayTag
method:boolean bNewDebugMode = GetTagAttributeAsBoolean(MODE);
To access non-pt (XML/HTML) attributes, use the GetXMLTagAttribute
method using the attribute name, or GetXMLTagAttributesAsString
to retrieve all non-pt attributes. result.AddInnerHTMLElement(new HTMLGenericElement("<a href=\"" + GetHREF() + "\" " + GetXMLTagAttributesAsString() + ">"));
The ITagMetaData
, RequiredTagAttribute
, and OptionalTagAttribute
objects pre-process tag attributes (presence, correct type, and default values). If the required attributes are not correct, an error is logged and the tag and its children are skipped. An HTML comment describing the tag and error is displayed instead.
To store custom data as member variables using a custom tag, use the SetStateVariable
or SetStateSharedVariable
methods. To retrieve it, use GetStateVariable
or GetStateSharedVariable
.
Standard variables (stored with SetStateVariable
) can only be accessed by tags in the same library. Shared variables (stored with SetStateSharedVariable
) can be accessed by tags from any library. To prevent tags from other libraries from editing a shared variable, set bOwnerEditOnly
to true when the shared variable is stored (tags in other libraries will still be able to read the variable).The Scope
parameter determines who can see the data and how long it stays in memory. The following options are defined in the Scope
class:
Table 2-5 Options Defined in Scope Class
Option | Description |
---|---|
Application Scope |
Data is visible to all tags and all users, and is only removed when the application is restarted. Therefore, care should be used when storing data on the application to make sure it does not become cluttered with large amounts of data. |
HTTP Request Scope |
Data will be visible to all tags in the same HTTP Request as the current tag, and is removed from memory when the HTTP Request is finished. |
Session Scope |
Data is visible to all tags for the current user, and is cleared from memory when a user logs out and logs in again. |
Persistent Session Scope |
Data is visible to all tags in the same HTTP session, and is only removed from memory when the browser is closed or the browser session times out. Note: Data is not cleared on user logout, so do not cache anything on this scope that could be considered a security risk if it was leaked to another user. Most tags should use Session Scope for HTTP Session data storage (as described above). |
Portlet Request Scope |
Data is visible to all tags in the same pagelet as the current tag, and is removed from memory when the pagelet is finished displaying. Tags in other pagelets on the same page will not be able to see the data. |
Tag Scope |
Data can only be seen by children of the current tag and is removed from memory when the tag is finished. (For example, in the following tags: |
If data is stored directly in the tag in member variables (not recommended), override the ReleaseTag
method to release the data stored on the tag.
/** * @see com.plumtree.portaluiinfrastructure.tags.ATag#ReleaseTag() */ public void ReleaseTag() { // Release all member variables. m_strPreviousRequestURL = null; }
Note: Displaying anHTMLElement in a tag and caching it so another tag can add more HTML is not supported. HTMLElement trees can be generated and stored for later use as long as they are self-contained trees and used in a read-only way. It is safest to clone a cached HTMLElement tree before trying to display it again to make sure there are no threading problems. |
Note: It is a best practice not to use static fields for data storage in tags. Each tag instance is guaranteed to be accessed by only a single thread at a time, but there may be multiple threads accessing different instances of the same tag class at the same time, either from the same user or a different user. This means that any static fields must be accessed using synchronized methods. Since there can be multiple instances of the same tag running at the same time, state variables set in shared scopes (Session, Persistent Session and Application) could change values during the execution of a single tag. |
To include JavaScript in a tag, use the AddJavaScript
method inside the DisplayTag
method.
For example:
HTMLScriptCollection scriptCollection = new HTMLScriptCollection(); HTMLScript script = new HTMLScript("text/javascript"); scriptCollection.AddInnerHTMLElement(script); script.AddInnerHTMLString("function myTest() { alert('test'); }"); AddJavaScript(scriptCollection);
To include common JavaScript that can be shared between multiple instances of a tag (i.e. JavaScript that is displayed once per page, regardless of how many tags of a certain type there are), override the DisplaySharedJavaScript
method. DisplaySharedJavaScript
is called automatically by the framework.
/** * Adds the PTIncluder object to the client. This object is used for * retrieving JSComponent client classes from a page. */ public HTMLScriptCollection DisplaySharedJavaScript() { HTMLScriptCollection result = new HTMLScriptCollection(); HTMLScript script = new HTMLScript("text/javascript"); result.AddInnerHTMLElement(script); script.SetSrc("/myjsfile.js"); return result; }
If there are errors in the tag and the JavaScript cannot be displayed properly, the tag should throw an XPException
with an error message, and the tag framework will log the error and add the message and stack trace to the HTML as an HTML comment. The message contents will be HTML encoded before being added to the comment.
Note: JavaScript is not displayed in 508 mode for either method, since section 508 compliant browsers do not support JavaScript. |
Tags can be used within other tags. To implement nested tags, use the RequiredParentTag
, RequiredChildTag
and RelatedChildTag
member variables.
The outer tag is referred to as the "parent" tag. Any tags within a parent tag are referred to as "child" tags of that tag. If the tag is only intended for use within a particular parent tag, create a public static final RequiredParentTag
member variable. If there are multiple RequiredParentTag
members, at least one of the parent tags must be present for the child tag to function. If the tag must include a particular child tag to function, create a public static final RequiredChildTag
member variable for each tag that is required inside the parent tag. If the child tag is not required for the parent tag to function, but is still related to that tag, create a public static final RelatedChildTag
member variable instead.
public static final RequiredChildTag DATA_OBJECT; static { ... DATA_OBJECT = new RequiredChildTag(DataObjectTag.TAG); }
Note: If required parent or child tags are missing when a tag is displayed, the tag framework will not process the incorrect tag and will add an error message to the HTML as an HTML comment. |
To implement non-standard tag types in custom adaptive tags, including 508-accessible, looping or singleton tags, override the associated method.
To display a custom tag in non-standard access styles (508 or low bandwidth), override the SupportsAccessStyle
method. The default implementation of the SupportsAccessStyle
method will cause the tag to be skipped in 508 and low-bandwidth mode. Make sure that tags that support 508 mode can function without JavaScript, since JavaScript will not be displayed in 508 mode.
If the tag displays the tag body more than once (looping tag), override the GetTagType()
method and return TagType.LOOPING.
If the tag never displays the tag body (singleton tag), override GetTagType()
and return TagType.NO_BODY.
To deploy custom adaptive tags, follow these steps.
Navigate to PORTAL_HOME\settings\portal and open CustomTags.xml in a text editor (you might need to make the file writable).
Find the <AppLibFiles>
tag and add a new entry using the name of the .jar/.dll file used to define the custom tag library (e.g., mytags).
<AppLibFiles> <libfile name="sampletags"/> </AppLibFiles>
Add the custom implementation (.jar/.dll) to Oracle WebCenter Ensemble hierarchy:
Java: Copy the custom .jar file to ENSEMBLE_HOME\lib\java and add it to the .war file in ENSEMBLE_HOME\webapp. (You must stop Oracle WebCenter Ensemble while modifying portal.war because it will be locked while Oracle WebCenter Ensemble is running.)
.NET: Copy the custom .dll file to ENSEMBLE_HOME\webapp\portal\bin.
Run a clean build of Oracle WebCenter Ensemble to refresh all the jar files associated with Oracle WebCenter Ensemble.
Once you have deployed your code, create a pagelet that contains the tag. Custom adaptive tags must either include the correct XML namespace or be contained within another tag that does. The simplest way is to put the HTML inside a span. Custom adaptive tags must use the pt:libraryname.tagname and pt:attributename format. The sample code below references the custom tag from Creating Custom Adaptive Tags.
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'> <pt:sample.hellolocation pt:message="Hello" pt:location="San Francisco"/> </span>
Add the pagelet to a page and view the page. Test all custom tags.
The Oracle WebCenter Interaction Scripting Framework is a client-side JavaScript library that provides services to pagelets and proxied pages. The Portlet Communication Component (PCC) is contained within the Scripting Framework.
The Oracle WebCenter Interaction Scripting Framework allows pagelets to:
Store and share session state through browser level variables. Browser-level variables can be stored and shared among pagelets, even if they are not on the same page. For example, a value entered by the user in one pagelet can be retrieved by another. The Scripting Framework acts as an intermediary, allowing all pagelets access to all values stored in a common session. For details, see Session Preferences.
Leverage page-level events. A pagelet can respond when specific events happen, such as when the page loads or when the browser focus changes. For details, see Using Oracle WebCenter Interaction Scripting Framework Event Notification.
Refresh pagelet content without reloading the page. pagelets can reload their internal content without refreshing the page. For details, see Using In-Place Refresh.
For a full list of classes and methods, see the JSPortlet API documentation.
These tips and best practices apply to all code that utilizes the Oracle WebCenter Interaction Scripting Framework.
Use unique names for all forms and functions. Use the GUID of a pagelet to form unique names and values to avoid name collisions with other code on the page. You can append the pagelet ID using the pt:namespace
and pt:token
tags, as shown in the code below.
<pt:namespace pt:token="$$TOKEN$$" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/> <a onclick="doStuff$$TOKEN$$();" href="#">do stuffa onclick="doStuff$$TOKEN$$();" href="#">do stuff</a> <script> function doStuff$$TOKEN$$() { alert("hello"); } </script>
Valid values for the token are in the ASCII range 0x21 to 0x7E, excluding "<" (0x3C). The scope of the token runs from the tag defining it to the end of the file; you cannot use a token prior to defining it. A second pt:namespace
tag with a different token redefines it; two tokens cannot be defined at the same time.
Proxy all URLs. You cannot make a request to a URL whose host/port differs from that of the calling page. All URLs requested through JavaScript must be proxied. For details, see About Server Communication and the Proxy.
Check for Scripting Framework support. It is good practice to include code that determines whether or not the component is present. Ideally, your pagelet should be able to handle either situation. The simplest solution is to precede your code with an If statement that alerts the user if the Scripting Framework is not supported.
<script> if (PTPortlet == null) { if (document.PCC == null) { alert("This portlet only works in portals that support the JSPortlet API or Portlet Communication Component (PCC). The portlet will be displayed with severely reduced functionality. Contact your Administrator."); } } else { [scripting code here] } </script>
Close all popup windows opened by a pagelet when the window closes. The Scripting Framework can be used to close popup windows using the onunload
event.
Do not assume that browsers will process script blocks/includes added through the innerHTML property. Add all required JavaScript to the page in advance:
Microsoft Internet Explorer: Add the defer attribute to the script tag.
Netscape: Use RegExp to parse the response and look for the script, then evaluate it.
The Oracle WebCenter Interaction Scripting Framework allows pagelets to respond to both page-level events and custom events raised by other pagelets.
The registerForWindowEvent
and registerOnceForWindowEvent
methods in the Oracle WebCenter Interaction Scripting Framework provide pagelets with access to page-level events. For a complete list, see Page-Level Events for Use with the Oracle WebCenter Interaction Scripting Framework. To register for notification of these events, pass in the name of the event and the name of the method that should be called when it occurs. When a page-level event is raised, the JavaScript event object is passed to the event handler as an argument. The Oracle WebCenter Interaction Scripting Framework also allows pagelets to raise and respond to custom events using raiseEvent
and registerForEvent
. The Broadcast-Listener design pattern illustrates an important example of using notification services with session preferences. Users can select an item or perform some other action in a "broadcast" pagelet, which causes the content in other related "listener" pagelets to be redrawn. In the following example, the broadcast pagelet displays a form that allows you to enter a number in a text box.
Description of the illustration csapi_broadcast.gif
When the user enters a number in the text box, the values in the listener pagelets change. The first listener pagelet displays the square root of the number entered in the broadcast pagelet.
Description of the illustration csapi_listener1.gif
The second listener pagelet displays the cube root of the number entered in the broadcast pagelet.
Description of the illustration csapi_listener2.gif
The following steps summarize how the pagelets work:
On load, each listener pagelet calls its own instance method (registerForEvent
) to register for events of type 'onBroadcastUpdate'.
On each onkeyup event that occurs in the "Enter number" text box, the broadcast pagelet sets a session preference to the value entered in the text box, and calls its own instance method (raiseEvent
) to raise an event of type 'onBroadcastUpdate'.
When the onBroadcastUpdate event is raised or the page is reloaded, each listener pagelet retrieves the session preference set by the broadcast pagelet and computes a new value to display based on the value of the preference.
Broadcast Pagelet
<div style="padding:10px;" align="center"> <p><b>Enter number:</b> <input type="text" style="font-size:22px;font-weight:bold;text-align:center;" id="broadcast_prefName" value="4" size="7" onkeyup="broadcast_setPrefs(this.value)"></p> <br> </div> <script type="text/javascript"> function broadcast_setPrefs(val) { var prefName = 'broadcastNumber'; var prefValue = val; PTPortlet.setSessionPref(prefName,prefValue); var broadcastPortlet = PTPortlet.getPortletByGUID('{D9DFF3F4-EAE7-5478-0F4C-2DBD94444000}'); if (!broadcastPortlet) { broadcast_debug('Could not locate PTPortlet object which corresponds to <b>Broadcast Portlet</b> on page.'); return; } broadcast_debug('<b>Broadcast Portlet</b> raising onBroadcastUpdate event.'); broadcastPortlet.raiseEvent('onBroadcastUpdate',false); } function broadcast_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } </script>
Listener Pagelet #1
<div style="padding:10px;" align="center"> <p><b>Square root:</b> <div style="height:21px;border:2px solid black;padding:2px;overflow:visible;font-size:14px;"id="listener1-swatch"> </div> </div> <script> function listener1_update() { var broadcastNumber = parseFloat(PTPortlet.getSessionPref('broadcastNumber')); if (isNaN(broadcastNumber)) { listener1_error('<b>Listener-1 Portlet</b> cannot parse number from session pref broadcastNumber'); return; } listener1_debug('<b>Listener-1 Portlet</b> computing square root of ' + broadcastNumber); var swatch = document.getElementById('listener1-swatch'); swatch.innerHTML = Math.sqrt(broadcastNumber); } function listener1_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } function listener1_error(str) { if (window.PTDebugUtil) { PTDebugUtil.error(str); } } function listener1_getPortlet() { var portletGUID = '{D9DFF3F4-EAE7-5478-0F4C-2DBDB4F4A000}'; var listener1Portlet = PTPortlet.getPortletByGUID(portletGUID); return listener1Portlet; } var listener1Portlet = listener1_getPortlet(); if (listener1Portlet) { listener1Portlet.registerForEvent('onBroadcastUpdate','listener1_update'); listener1_debug('<b>Listener-1 Portlet</b> registered refreshOnEvent for event onBroadcastUpdate'); listener1Portlet.registerForEvent('onload','listener1_update'); } </script>
Listener Pagelet #2
<div style="padding:10px;" align="center"> <p><b>Cube root:</b> <div style="height:21px;border:2px solid black;padding:2px;overflow:visible;font-size:14px;"id="listener2-swatch"> </div> </div> <script> var listener2_oneThird = (1/3); function listener2_update() { var broadcastNumber = parseFloat(PTPortlet.getSessionPref('broadcastNumber')); if (isNaN(broadcastNumber)) { listener2_error('<b>Listener-2 Portlet</b> cannot parse number from session pref broadcastNumber'); return; } listener2_debug('<b>Listener-2 Portlet</b> computing square root of ' + broadcastNumber); var swatch = document.getElementById('listener2-swatch'); swatch.innerHTML = Math.pow(broadcastNumber,listener2_oneThird); } function listener2_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } function listener2_error(str) { if (window.PTDebugUtil) { PTDebugUtil.error(str); } } function listener2_getPortlet() { var portletGUID = '{D9DFF3F4-EAE7-5478-0F4C-2DBDCA1C7000}'; var listener2Portlet = PTPortlet.getPortletByGUID(portletGUID); return listener2Portlet; } var listener2Portlet = listener2_getPortlet(); if (listener2Portlet) { listener2Portlet.registerForEvent('onBroadcastUpdate','listener2_update'); listener2_debug('<b>Listener-2 Portlet</b> registered refreshOnEvent for event onBroadcastUpdate'); listener2Portlet.registerForEvent('onload','listener2_update'); } </script>
The Oracle WebCenter Interaction Scripting Framework automatically has access to the following page-level events.
Table 2-6 Page-Level Events
Event | Triggered: |
---|---|
onload |
immediately after the browser loads the page |
onbeforeunload |
prior to a page being unloaded (browser window closes or navigates to different location) |
onunload |
immediately before the page is unloaded (browser window closes or navigates to different location) |
onactivate |
the page is set as the active element (receives focus) |
onbeforeactivate |
immediately before the page is set as the active element (receives focus) |
ondeactivate |
when the active element is changed from the current page to another page in the parent document |
onfocus |
when the page receives focus |
onblur |
when the page loses focus |
oncontrolselect |
when the user is about to make a control selection of the page |
onresize |
when the size of the page is about to change |
onresizestart |
when the user begins to change the dimensions of the page in a control selection |
onresizeend |
when the user finishes changing the dimensions of the page in a control selection |
onhelp |
when the user presses the F1 key while the browser is the active window |
onerror |
when an error occurs during page loading |
onafterprint |
immediately after an associated document prints or previews for printing |
To refresh pagelet content in place, without affecting other content on the page, use the Oracle WebCenter Interaction Scripting Framework to implement in-place refresh.
Many pagelets display data that is time sensitive. In some cases, users should be able to navigate across links within a pagelet without changing or refreshing the rest of the page. You can refresh pagelet content on command, associate the refresh action with an event (refreshOnEvent
), or program the pagelet to refresh at a set interval (setRefreshInterval
). The Oracle WebCenter Interaction Scripting Framework also contains methods for expanding and collapsing pagelets. In the simplified example below, the refresh pagelet displays a "Refresh Portlet" button. Clicking the button updates the date and time displayed in the pagelet. (The refresh button in the header is an optional feature available in Oracle WebCenter Interaction only, configured on the Advanced Settings page of the Web Service editor.)
Description of the illustration csapi_refresh.gif
The in-place refresh is executed by calling the refresh()
method on the pagelet object instance. The pagelet reference can be retrieved by GUID, ID or name, available via the Oracle WebCenter Interaction Development Kit (IDK) IPortletRequest
interface. You can also set a new URL to be displayed within the pagelet upon refresh by using setRefreshURL
or passing in a new URL when you call refresh
. (The title bar cannot be altered on refresh.)
<div style="padding:10px;" align="center"> <p><button onclick="refresh_portlet()">Refresh Portlet</button></p> <p><b>Current time is:</b><br> <span id="refreshTimeSpan"></span></p> </div> <pt:namespace pt:token="$PORTLET_ID$" xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'/> <script type="text/javascript"> function refresh_portlet() { var refreshPortlet = PTPortlet.getPortletByID($PORTLET_ID$); if (!refreshPortlet) { refresh_debug('Could not locate PTPortlet object which corresponds to <b>Refresh Portlet</b> on page.'); return; } refresh_debug('<b>Refresh Portlet</b> calling refresh() method.'); refreshPortlet.refresh(); } function refresh_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } var t = new Date(); document.getElementById('refreshTimeSpan').innerHTML = t; </script>
These tips apply to most adaptive pagelets.
Proxt all URLs. You cannot make request to a URL whose host/port differs from that of the calling page. All URLs requested through JavaScript must be proxied. For details, see . About Server Communication and the Proxy.
Add all required JavaScript to the page in advance. Browsers might not process script blocks/includes added to the page through the innerHTML
property.
Microsoft Internet Explorer: Add the defer attribute to the script tag.
Netscape: Use RegExp to parse the response and look for the script, then eval it.
JavaScript HTTP and proxied HTTP must use the same authentication credentials. JavaScript brokered HTTP requests send the same authentication token (cookie) as when you make a normal gatewayed HTTP request.
To store and share settings within the client browser, use session preferences.
Pagelets can use preferences to communicate with each other, but accessing preferences usually requires a round trip to a database. Session preferences provide a way to store and share settings in the user's session within the client browser. The Master-Detail design pattern illustrates the most basic usage of session preferences. This design pattern splits control and display between two pagelets. For example, the "master" pagelet could summarize data in list form, and the "detail" pagelet could display details on each data item in response to user selection. In the example below, the master pagelet displays a form that allows you to enter a color code in a text box.
Description of the illustration csapi_master.gif
When the user enters a color code in the text box, the color in the detail pagelet changes.
Description of the illustration csapi_detail.gif
For each onkeyup event that occurs in the "Enter color" text box in the master pagelet, the following steps are executed:
The master pagelet sets the session preference using the current value of the text box.
The master pagelet calls an update method on the detail pagelet.
The detail pagelet retrieves the session preference to get the color value.
The detail pagelet redraws its color swatch area to reflect the new color value.
Pagelets can manipulate session preferences using the Oracle WebCenter Interaction Development Kit (IDK) or the Oracle WebCenter Interaction Scripting Framework. Sample code for both options is provided below.
Note: Shared session preferences must be specified by name on the Preferences page of the associated Web Service editor or they will not be sent to the pagelet. |
Always use the Oracle WebCenter Interaction Development Kit (IDK) to read session preferences, as shown in the example code below. (In most cases, reading session preferences via the Oracle WebCenter Interaction Scripting Framework is inefficient and insecure.)
Java
<%@ page language="java" import="com.plumtree.remote.portlet.*,java.util.Date" %> IPortletContext portletContext = PortletContextFactory.createPortletContext(request,response); IPortletResponse portletResponse = portletContext.getResponse(); IPortletUser portletUser = portletContext.getUser(); IPortletRequest portletRequest = portletContext.getRequest(); masterColor = portletRequest.getSettingValue(SettingType.Session, "masterColor");
.NET
... Dim portletContext As IPortletContext portletContext = PortletContextFactory.CreatePortletContext(Request, Response) Dim portletRequest As IPortletRequest portletRequest = PortletContext.GetRequest Dim portletUser As IPortletUser portletUser = PortletContext.GetUser Dim portletResponse As IPortletResponse portletResponse = PortletContext.GetResponse Dim masterColor As String masterColor = portletRequest.GetSettingValue(SettingType.Session "masterColor") ...
As noted above, it is usually better to use the Oracle WebCenter Interaction Development Kit (IDK) to read session preferences; reading session preferences via the Oracle WebCenter Interaction Scripting Framework is inefficient and insecure.
This example is oversimplified; the master pagelet makes a direct call to a JavaScript method of the detail pagelet. Unless the master pagelet takes extra measures to ensure that the detail pagelet is actually present on the same page, calls from master to detail could generate errors. The Oracle WebCenter Interaction Scripting Framework provides an easy way to detach the relationship between pagelets and use a common event interface for communication. For more information on the Oracle WebCenter Interaction Scripting Framework, see Oracle WebCenter Interaction Scripting Framework.
Master Pagelet
<div style="padding:10px;" align="center"> <p><b>Enter color:</b> <input type="text" style="font-size:22px;font-weight:bold;text-align:center;" id="master_prefName" value="#FFFFFF" size="8" onkeyup="master_setPrefs(this.value)"></p><br> </div> <script type="text/javascript"> function master_setPrefs(val) { var prefName = 'masterColor'; var prefValue = val; PTPortlet.setSessionPref(prefName,prefValue); master_debug('<b>Master Portlet</b> called PTPortlet.setSessionPref(\'masterColor\',\'' + prefValue + '\').'); if (window.detail_update) { master_debug('<b>Master Portlet</b> calling detail_update().'); detail_update(); } else { master_debug('Could not locate portlet <b>Detail Portlet</b> on page.'); } } function master_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } </script>
Detail Pagelet
<div style="padding:10px;" align="center"> <p><b>Color swatch</b> <div style="width:100px;height:100px;border:2px solid black;padding:2px;"id="detail-swatch"></div> <script> function detail_update() { var color = PTPortlet.getSessionPref('masterColor'); detail_debug('<b>Detail Portlet</b> received value="' + color + '" for PTPortlet.getSessionPref(\'masterColor\')'); var swatch = document.getElementById('detail-swatch'); if (swatch) { swatch.innerHTML = '<div style="background-color:' + color + ';width:100%;height:100%;"></div>'; } else { detail_debug('<b>Detail Portlet</b> cannot find \'detail-swatch\' DIV element.'); } } function detail_debug(str) { if (window.PTDebugUtil) { PTDebugUtil.debug(str); } } </script>
Caching is the functionality that allows Oracle WebCenter Ensemble to request pagelet content, save the content, and return the saved content to users when appropriate. The importance of caching cannot be overstated.
Efficient caching makes every web application faster and less expensive. The only time content should not be cached is if the data must be continuously updated. If every pagelet had to be freshly generated for each request, performance could become unacceptably slow. Oracle WebCenter Ensemble relies on caching to improve performance. pagelet content is cached and returned when later requests match the cache's existing settings.
Caching is indexed on the settings sent by the pagelet. When the Oracle WebCenter Ensemble proxy server processes a request for a page, it looks individually at each pagelet on the page and checks it against the cache. The process can be summarized as follows:
The proxy server assembles a cache key used to uniquely identify each pagelet in the cache.
The proxy server checks the cache for a matching cache key entry:
If the proxy erver finds a match that is not expired, it returns the content in the cache and does not make a request to the external resource.
If there is no matching cache key for the pagelet or if the cache key has expired, the proxy server makes a request to the external resource. If the matching cache entry uses ETag or Last-Modified caching, it also sends the appropriate caching header to the external resource in the request.
The response comes back from the external resource; the proxy server checks for caching headers:
If the headers include an Expires header, the proxy server stores the new pagelet content (along with a new expiration date) in its cache.
If the headers use ETag or Last-Modified caching, the existing cache entry might be revalidated (in the case of '304-Not Modified') or new pagelet content might be stored in the cache.
Oracle WebCenter Ensemble caches proxied content to complement, not replace, browser caching. Public content is accessible to multiple users without any user-specific information (based on HTTP headers). The proxy server calculates the cache headers sent to the browser to ensure that the content is properly cached on the client side.
Oracle WebCenter Ensemble caches all text (i.e., nonbinary) content returned by GET requests. Even if proxy caching is disabled (via PTSpy), pagelet caching still takes place. Proxied content can be cached by an external proxy server or by the user's browser. Beware browser caching of proxied content; it is a good idea to clear your browser cache often during development. An incorrectly set Expires header can cause browsers to cache proxied content.
The pagelet cache contains sections of finished markup and sections of markup that require further transformation. Post-cache processing means content can be more timely and personalized. Adaptive tags enable certain pagelets (for example, Community banners) to be cached publicly for extended periods of time and yet contain user specific and page-specific information, as well as the current date and time.
For details, see the following sections:
For a full explanation of HTTP caching, see RFC 2616 (http://www.w3.org/Protocols/rfc2616/rfc2616.html
).
Pagelet caching is controlled both by the programmer and by the administrator who registers the pagelet in Oracle WebCenter Ensemble. Each and every pagelet needs a tailored caching strategy to fit its specific functionality.
A pagelet's caching strategy should take all possibilities into account and use the most efficient combination for its specific functionality. A pagelet that takes too long to generate can degrade the performance of every page that displays it. These questions can help you determine the appropriate caching strategy:
Will the content accessed by the pagelet change? How often?
How time-critical is the content?
What processes are involved in producing pagelet content? How expensive are they in terms of server time and impact?
Is the pagelet the only client with access to the back-end application?
Is the content different for specific users?
Can users share cached content?
Determine how often pagelet content must be updated, dependent on data update frequency and business needs. Find the longest time interval between data refreshes that will not negatively affect the validity of the content or the business goals of the pagelet.
Since caching is indexed on the settings used by a pagelet, new content is always requested when settings change (assuming that no cached content exists for that combination of settings).
There are two common situations in which you might mistakenly decide that a pagelet cannot be cached:
In-place refresh: You might think that caching would "break" a pagelet that uses in-place refresh because the pagelet would be redirected to the original (cached) content. This can be avoided if a unique setting is updated on every action that causes a redraw, effectively "flushing" the cache. (In-place refresh renews the pagelet display by causing the browser to refresh page at a set interval.)
Invisible preferences: If the content of the pagelet is dependent on something other than preferences (for example, the pagelet keys off the User ID to display a name or uses portal security to filter a list), caching can still be implemented with "invisible preferences" (in this case, User ID). As with in-place refresh, invisible preferences are set solely for the purpose of creating a different cache entry. They are set programmatically, without the user's knowledge.
For details on implementing caching, see the following sections:
The cache key for a pagelet entry in Oracle WebCenter Ensemble consists of the values in the table below.
Type | Value |
---|---|
Pagelet ID | The unique ID for the pagelet, defined by Oracle WebCenter Ensemble. |
Content Mode | The content mode of the pagelet. |
Settings | Any settings stored in Oracle WebCenter Ensemble. |
User Interface | The type of device used to access the pagelet. |
LocaleID | The ID for the locale associated with the current user, defined by Oracle WebCenter Ensemble. |
UserID | The unique ID for the current user. Included only if private caching is used. |
URI | The URL to the current page on the external resource. |
Last-modified date | The last modified date of the pagelet. |
The data below is deliberately not included in the cache key:
Type | Value |
---|---|
StyleSheetURI | Stylesheets are applied at runtime, depending on the user preference. Pagelet content does not depend on the particular stylesheet that the user has selected. |
HostpageURI | All parts of the Hostpage URI value are covered separately. The User ID is added if private caching is used. |
The Cache-Control header can be used to expire content immediately or disable caching altogether. The value of this header determines whether cached pagelet content can be shared among different users.
The Cache-Control header can contain the following values:
Value | Description |
---|---|
public | Allows any cached content to be shared across users with identical sets of preferences using the same Oracle WebCenter Ensemble server. This value should be used whenever possible. |
private | Tells Oracle WebCenter Ensemble not to share cached content. The User ID is added to the cache key so that a separate copy is retained in the cache for each individual user. This value should only be used to protect sensitive information, for example, an e-mail inbox portlet. (User settings can also make public content effectively private.) |
max-age=[seconds] | Specifies the maximum amount of time that an object is considered fresh. Similar to the Expires header, this directive allows more flexibility. [seconds] is the number of seconds from the time of the request that the object should remain fresh. |
must-revalidate | Tells the cache that it must obey any freshness information it receives about an object. HTTP allows caches to take liberties with the freshness of objects; specifying this header tells the cache to strictly follow your rules. |
no-cache | Disables caching completely and overrides Oracle WebCenter Ensemble settings. Neither the client nor Oracle WebCenter Ensemble responds to subsequent requests with a cached version. |
In JSP, use the setHeader
method to configure the Cache-Control header:
<% response.setHeader("Cache-Control","public"); %>
The JSP example below expires the content immediately using the maximum age header.
<% response.setHeader("Cache-Control","max-age=0"); %>
In .NET, the Cache-Control header is accessed through the System.Web.HttpCachePolicy
class. To set the header to public, private or no-cache, use the Response.Cache.SetCacheability
method.
Response.Cache.SetCacheability(HttpCacheability.Public);
To set a maximum age for content in .NET, use the Response.Cache.SetMaxAge
method. The example below expires the content immediately.
TimeSpan ts = new TimeSpan(0,0,0); Response.Cache.SetMaxAge(ts);
To set the header to must-revalidate in .NET, use the Response.Cache.SetRevalidation
method.
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
The Expires header specifies when content will expire, or how long content is "fresh." After this time, Oracle WebCenter Ensemble will always check back with the resource to see if the content has changed.
Most web servers allow setting an absolute time to expire, a time based on the last time that the client saw the object (last access time), or a time based on the last time the document changed on your server (last modification time).In JSP, setting caching to forever using the Expires header is as simple as using the code that follows:
<% response.setDateHeader("Expires",Long.MAX_VALUE); %>
The .NET System.Web.HttpCachePolicy
class provides a range of methods to handle caching, but it can also be used to set HTTP headers explicitly (see MSDN for API documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttpcachepolicyclasssetexpirestopic.asp
). The Response.Cache.SetExpires
method allows you to set the Expires header in a number of ways. The following code snippet sets it to forever:
Response.Cache.SetExpires(DateTime.Now.AddYears(100000000));
In .NET, the Web Form page (.aspx) can also use standard ASP methods to set HTTP headers.
Note: Never use Expires = 0 to prevent caching. The Expires header is sent by the external resource and passed through to the browser by Oracle WebCenter Ensemble. Unless the time on all three machines is synchronized, an Expires=0 header can mistakenly return cached content. To solve this problem, set the Expires header to a fixed date that is definitely in the past. |
The Last-Modified response header specifies the last time a change was made in the returned content, in the form of a time stamp. ETag values are unique identifiers generated by the server and changed every time the object is modified. Either can be used to determine if cached content is up to date.
When an object stored in the cache includes a Last-Modified or ETag header, Oracle WebCenter Ensemble can use this value to ask the resource if the object has changed since the last time it was seen.
Oracle WebCenter Ensemble sends the value from the Last-Modified header to the resource in the If-Modified-Since Request header.
The resource sends the ETag header to Oracle WebCenter Ensemble with pagelet content. When another request is made for the same content, Oracle WebCenter Ensemble sends the value in the ETag header back to the resource in the If-None-Match header.
The pagelet code on the resource uses the header value to determine if the content being requested has changed since the last request, and responds with either fresh content or a 304 Not Modified Response. If Oracle WebCenter Ensemble receives the latter, it displays the cached content.JSP pagelets can access the value in the If-Modified-Since request header using the getLastModified(HttpServletRequest req)
method provided by the Java class HttpServlet.In .NET, the Response.Cache.SetLastModified
method allows you to set the Last-Modified header to the date of your choice. Alternately, the SetLastModifiedFromFileDependencies
method sets the header based on the time stamps of the handler's file dependencies.
Response.Cache.SetLastModified(DateTime.Now);
To use ETag in .NET, use the Response.Cache.SetETag
method to pass in the string to be used as the ETag. The SetETagFromFileDependencies
method creates an ETag by combining the file names and last modified timestamps for all files on which the handler is dependent.
These tips and best practices apply to all pagelets that will be translated into multiple languages.
Identify ALL culturally dependent data. Text messages are the most obvious example of locale-specific data, but there are many other parts of a service that can vary with language or location. These include: images, UI labels and buttons, icons, sounds, graphics, dates, times, measurements, honorifics and titles, phone numbers, and postal addresses.
Do not use compound messages (concatenated strings) to create text. Compound messages contain variable data. For example, in the text string "You have XX credits," only the integer "XX" will vary. However, the position of the integer in the sentence is not the same in all languages. If the message is coded as a concatenated string, it cannot be translated without rewriting the code.
Use the IDK to avoid encoding issues. All content is stored in the database in Unicode. The Oracle WebCenter Interaction Development Kit (IDK) handles encoding for international characters.
For details on implementing internationalization, see Using Internationalized Strings in Adaptive Tags.
To deploy a pagelet in Oracle WebCenter Ensemble, you must configure Resource and Pagelet objects.
To deploy a pagelet, you must create and configure the following objects:
Resource (producer): For details, see Configuring an Oracle WebCenter Ensemble Resource.
Pagelet: For details, see Configuring an Oracle WebCenter Ensemble Pagelet.
Resource (consumer): For details, see Configuring an Oracle WebCenter Ensemble Resource.
You must also configure security settings for Oracle WebCenter Ensemble objects. For details, see About Oracle WebCenter Ensemble Security.
To insert pagelets into a page, use one of the following methods:
To insert a pagelet into a proxied page, see Inserting Pagelets Using Oracle WebCenter Ensemble Adaptive Tags.
To insert a pagelet into a non-proxied page, see Inserting Pagelets into Non-Proxied Pages.
Producer and consumer resources are both configured through the same editor.
The producer resource defines the location of the web application that implements the pagelet code and how it is accessed. In most cases, a single producer resource is used for multiple pagelets.
The consumer resource defines the location of the web application that displays the pagelet code and how it is accessed.
To create a new resource, go to the Applications section of the Ensemble Console, click the Resources sub-tab, and click Create New.
To edit an existing resource, navigate to the Resources sub-tab and click the resource name.
The resource configuration editor includes the tabs detailed below.
General
The following settings are configured on the General tab:
Resource Attributes: Name: The resource name displayed in other sections of the Oracle WebCenter Ensemble Console. This name must be unique. The Description is optional.
Resource Attributes: Owner: Set to the user who created the resource and can only be changed by an administrator.
Timeout: This setting applies to the resource and any associated pagelets. By default, the timeout is set to 30 seconds, but can be extended if necessary.
Status: This option allows you to disable a resource if it is not accessible.
Is Login resource: This option defines the resource as a login resource, used solely to authenticate users. Login resources are not protected by policies, because they must be accessible by all users at all times. For details on using login resources, see Chapter 3, "Oracle WebCenter Ensemble Login Customization".
Policy Attributes: Name: The name of the policy set associated with the resource. This name defaults to the name of the resource, but can be modified.
Policy Attributes: Owner: Set to the user who created the resource and can only be changed by an administrator.
Connections
The Connections tab allows you to define the Internal URL prefix that the Oracle WebCenter Ensemble proxy uses to access the application, and an External URL prefix to be exposed to users. The external URL prefix may be absolute or relative to the Oracle WebCenter Ensemble proxy. If the URL is absolute, it must either point directly to the Oracle WebCenter Ensemble proxy or, be resolvable to the Oracle WebCenter Ensemble proxy through DNS. You may configure multiple external URL prefixes to map to the internal URL prefix.
The Enable URL Rewriting option allows you to choose whether or not links within a proxied application will be transformed. If the internal and external URL prefixes are identical or all application links are relative, disabling URL rewriting will improve performance.
Credential Mapping
The Credential Mapping tab allows you to configure a resource to log in a user to the back-end application automatically by supplying the required authentication credentials. To disable Resource Authentication, select Disabled.
This page can be used to configure HTML Form-based authentication or Basic authentication using static login credentials, user profile information, or the credential vault. For detailed instructions, see the online help and theOracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble "Chapter 6, "Credential Mapping."
Headers
This tab allows you to choose which request headers and response headers are passed on to the back-end application. For example, if you are using delegated authentication, the SSO system might insert headers that should not be passed to the back-end application.
CSP
CSP is the protocol used by Oracle WebCenter Interaction to communicate with external resources. The CSP tab allows you to specify whether or not a login token will be sent to the back-end application. The login token is necessary to use the Oracle WebCenter Interaction (IDK) Remote APIs. For details, see the Oracle Fusion Middleware Web Service Developer's Guide for Oracle WebCenter Interaction.
This page also allows you to specify session preferences that can be set or obtained from the application and which user information will be sent to the application. For details on session preferences, see Session Preferences
Roles
This tab allows you to specify the Roles used by the application. The policy set associated with the resource maps users and groups to these roles via policies and policy rules. For details, see Using Oracle WebCenter Ensemble Roles in Pagelets and Proxied Applications.
SSO Log Out Settings
This tab allows you to enter an URL pattern to trigger Oracle WebCenter Ensemble SSO log out functionality. A user can be logged in to multiple applications through Oracle WebCenter Ensemble via a single sign on (SSO) system. When a user logs out of an application, Oracle WebCenter Ensemble can prompt the user to log out of that application or all applications. To enable SSO log out for a resource, enter the pattern of the logout URL in the Internal log out URL patterns list. You may enter multiple patterns.
For more information on resource configuration, see the online help and the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble "Chapter 4: Proxy Resources".
The pagelet object defines the location of the pagelet file and any associated parameters.
To create a new pagelet, go to the Applications section of the Oracle WebCenter Ensemble Console, click the Pagelets sub-tab, and click Create New.
To edit an existing pagelet, navigate to the Pagelets sub-tab and click the pagelet name. Pagelets can be created and edited by administrators, managers, and resource owners. Resource owners can only create or edit pagelets if they own the associated resource.
The pagelet configuration editor includes the tabs detailed below.
General
The following settings are configured on the General tab:
Name: The pagelet name displayed in other sections of the Oracle WebCenter Ensemble Console. This name must be unique. The Description is optional.
Parent resource: The producer resource associated with the pagelet. Each pagelet must be associated with a resource. Multiple pagelets can be associated with the same resource.
Library: A user-defined way to group pagelets. To add the pagelet to a pagelet library, type the name of the pagelet library. If the pagelet library does not already exist, one will be created.
Sample code: This field displays the XML declaration for the pagelet (pt.ensemble.inject) that can be used to insert the pagelet in a consumer resource page. This field is empty until the pagelet is saved. For information on using this code in a pagelet, see Inserting Pagelets Using Oracle WebCenter Ensemble Adaptive Tags.
Publish documentation: This option allows you to choose whether the pagelet is included in the Developer Pagelet Catalog.
Add inline refresh to all URLs: This option allows you to enable automatic inline refresh for the pagelet and related URLs. If you select this option, make sure to specify an appropriate Refresh interval.
Location
The pagelet location is composed of the Internal URL prefix of the associated resource and an URL suffix that points to the pagelet application hosted by that resource. The internal URL prefix is defined by the associated resource; to modify it, edit the resource.
Parameters
The Parameters tab provide access to configuration settings for data transport.
The Payload schema URL allows you to apply an XML schema to the pagelet's payload. Oracle WebCenter Ensemble only supplies the URL to the pagelet; it is up to the pagelet to use the schema to validate the XML payload. For information on using payloads, see the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble "Chapter 9, "Pagelets".
Parameters are name/value pairs (attributes) that provide information to the pagelet. This page allows to set a name and type for each parameter and select whether the parameter is mandatory.
The Pagelet Parameter Transport Type allows you to port Oracle WebCenter Interaction portlets that use Administrator, CommunityPortlet, or Community level preference settings to work as pagelets within Oracle WebCenter Ensemble. To send attributes to a portlet as an Oracle WebCenter Interaction setting type, choose the transport type associated with the setting type and enter the preference names in the parameters list. By default, attributes are send in the HTTP request header. Pagelet parameter values are defined in the pagelet injection code that is added to a consumer page. For information on using parameters in a pagelet, see the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble "Chapter 9, "Pagelets".
Metadata
Metadata can be used to store additional information about a pagelet. Metadata fields are viewable in the pagelet documentation.
Consumers
By default, all resources are allowed to consume a pagelet. This tab allows you to restrict which resources are allowed to consume the pagelet. To limit access to the pagelet, clear the All consumers allowed check box and add any resources that should have access to the pagelet to the Consumers list.
For more information on pagelet configuration, see the Oracle WebCenter Ensemble online help and the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble "Chapter 9, "Pagelets". For details on configuring pagelets and portlets in Oracle WebCenter Interaction, see the Oracle WebCenter Interaction online help and the Oracle Fusion Middleware Web Service Developer's Guide for Oracle WebCenter Interaction
The pt:ensemble.inject
tag injects the output of the specified pagelet into the page.
The pagelet is referenced by the fully qualified name of the pagelet as defined in Oracle WebCenter Ensemble, in the form libraryname:pageletname
. Any attributes not prefixed with "pt:" will be passed on to the pagelet. Any HTML content inside the pagelet tag will be passed to the pagelet as an XML payload.
<pt:ensemble.inject pt:name="mylibrary:mypagelet" pagelet-attribute="A pagelet attribute"> <?xml version="1.0" encoding="utf-8"?> <doc>This is an XML payload.</doc> </pt:ensemble.inject>
For an example of using this code, see Creating a Custom Pagelet with the Java Oracle WebCenter Interaction Development Kit (IDK) Proxy API or Creating a Custom Pagelet with the .NET Oracle WebCenter Interaction Development Kit (IDK) Proxy API.You can also insert pagelets into non-proxied pages; for details, see Inserting Pagelets into Non-Proxied Pages.
You can also insert pagelets into non-proxied pages using a simple javascript function.
To activate this feature, add the following HTML snippet in the <HEAD> section of the page.
<script type="text/javascript" src="http://proxy:port/inject/v2/csapi"> </script>
This script injects all CSAPI and pagelet inject functions into the page to display the pagelet. One of the sections injected is the following function:
function injectpagelet(library, name, injectmethod, payload, arguments) { ... }
This function injects an Oracle WebCenter Ensemble pagelet as a widget into the parent page. The method interface is as follows:
library: The library name of the pagelet to inject. This argument is a string that accepts spaces like 'library name'.
name: The name of the pagelet to inject. This argument is a string that accepts spaces like 'pagelet name'.
injectmethod: Specifies the manner of injecting the pagelet, if set to 'iframe', then an iframe is inserted where the call occurs, otherwise inline HTML will be used. If the inject method is specified as 'iframe', then a set of IFrame options can be sent along. These options control how the iframe will be displayed. The following iframe options are supported: width, height, frameborder, align, longdesc, marginheight, marginwidth, scrolling, stylem class. The parameters are given in the form of param=value
. The separator between parameters are spaces. For example, 'iframe align=right frameborder=1 width=100% height=200 scrolling=yes class=myclass'
.
payload: The XML payload to send along with the pagelet request
arguments: The pagelet arguments to send along with the pagelet request. Should be given in the form of: 'param1=value1¶m2=value2¶m3=value3'
.
The script also creates a new <div> with a unique name that includes a reference to the injectpagelet
function. Several examples are shown below:
<div> <script type="text/javascript"> injectpagelet('library', 'name'); </script> </div>
<div> <script type="text/javascript"> injectpagelet('library', 'name', 'iframe', 'payload', 'param1=value1¶m2=value2¶m3=value3'); </script> </div>
<div> <script type="text/javascript"> injectpagelet('library', 'name', 'iframe width=100% height=200', 'payload'); </script> </div>
The pagelet inject function can automatically resize the IFrame that encapsulates pagelet content. The resizing is done so that the IFrame stretches to fit the content within. To use this feature, the ifwidth and ifheight parameters must be set to 'auto' as shown in the example below:
<script type="text/javascript"> injectpagelet('library', 'pagelet', 'iframe ifheight=auto ifwidth=auto'); </script>
In addition, this feature relies on an external page on the same domain as the consumer page. This page is included into the pagelet IFrame as an internal hidden IFrame. This page collects the sizing information and passes it on to the parent consumer page. This page must be deployed in the same directory as the consumer page. An example is shown below.
<html> <head> <title>Resizing Page</title> <script type="text/javascript"> function onLoad() { var params = window.location.search.substring( 1 ).split( '&' ); var height; var width; var iframe; for( var i = 0, l = params.length; i < l; ++i ) { var parts = params[i].split( '=' ); switch( parts[0] ) { case 'height': height = parseInt( parts[1] ); break; case 'width': width = parseInt( parts[1] ); break; case 'iframe': iframe = parts[1]; break; } } window.top.updateIFrame( iframe, height, width ); } if (window.addEventListener) { window.addEventListener("load", onLoad, false) } else if (window.attachEvent) { window.detachEvent("onload", onLoad) window.attachEvent("onload", onLoad) } else { window.onload=onLoad } </script> </head> <body> </body> </html>
To insert a pagelet into a proxied page, use the pt:inject
tag; for details, see Inserting Pagelets Using Oracle WebCenter Ensemble Adaptive Tags. You can also inject pagelets using REST; for details, see Chapter 4, "Oracle WebCenter Ensemble REST APIs".
There are two factors that control access to a resource in Oracle WebCenter Ensemble: authentication and policies.
Oracle WebCenter Ensemble manages authentication with each proxied application based on the settings defined for the associated resource.
You can define the credential mappings for each resource. For details on configuring credential mappings, see the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble and the online help. You can create custom mappings to external credential stores. For details, see Creating a Custom Credential Mapping.
Each resource is protected by a policy set, which describes the conditions under which a user may be granted access to the resource, and the roles associated with those conditions. For details on using roles, see Using Oracle WebCenter Ensemble Roles in Pagelets and Proxied Applications.
Pagelets and proxied applications can use Oracle WebCenter Ensemble roles to control access to content and functionality.
Each incoming request to Oracle WebCenter Ensemble is evaluated against the policies for the requested resource. If the user is found to be in one or more roles, access is granted and the set of matching roles is passed on to the proxied application, allowing the application to determine the correct access level for the user. This is called Role-Based Access Control (RBAC).Roles are sent in an HTTP header and can be accessed using the Proxy IDK and adaptive tags.Adaptive tags can be included in the markup returned by any proxied page, including pagelets. Using the attributes defined in the tag, Oracle WebCenter Ensemble transforms the XML and replaces it with standard HTML to be displayed in a browser. For details, see Oracle WebCenter Ensemble Adaptive Tag Library (pt:ensemble).
The pt:ensemble.rolelist
tag creates a collection of the user's roles in the current context and stores it in memory using the name in the pt:key attribute. Each item in the collection is a variable containing the role name. The example below displays a list of the user's roles by iterating over the collection using the pt:logic.foreach tag.
<pt:ensemble.rolelist pt:key='roles'/> <pt:logic.foreach pt:data='roles' pt:var='role'> <pt:logic.value pt:value='$role'/> <pt:logic.separator><br></pt:logic.separator> </pt:logic.foreach><BR>
The pt:ensemble.roleexpr
tag evaluates an expression and stores the result as a boolean in memory using the name in the pt:key attribute. The example below checks if the user has the Admin role and displays a message based on the result using the pt:logic.if tag.
<pt:ensemble.roleexpr pt:expr='hasRole Admin' pt:key='hasrole'/> <pt:logic.if pt:expr='$hasrole'> <pt:logic.iftrue> This user has the Admin role. </pt:logic.iftrue> <pt:logic.iffalse> Warning: This user DOES NOT have the Admin role. </pt:logic.iffalse> </pt:logic.if>
The IDK bea.alui.proxy.IProxyUser
interface also allows you to get a list of the user's roles in the current context, or determine whether the user has a specific role.
The IProxyUser.getRoles
method returns an iterator of the user's roles as strings.
The IProxyUser.isUserInRole
method determines whether the user is in the role passed in the role parameter and returns true if the user has the role (false otherwise).
The IProxyUser.isAnonymous
method determines whether the user is an Anonymous user.
The IProxyUser.isUserInRole
method determines whether the user is in the role passed in the role parameter and returns true if the user has the role (false otherwise).
The simplified example below (roleconsumer.jsp) retrieves role information for the current user. The associated Oracle WebCenter Ensemble resource has three roles defined: AdminRole, MgrRole, and UserRole. (The associated policy set assigns these roles to groups or users.) In this example, the associated Oracle WebCenter Ensemble pagelet is named 'rolePagelet'. For more details on the Oracle WeCenter Interaction Development Kit (IDK) proxy API, see the API documentation.
<%@ page language='java' import='com.plumtree.remote.portlet.*, java.util.Date, java.util.*, com.bea.alui.proxy.*' %> You refreshed at <%= new Date().toString()%><br/> <% response.setHeader('Cache-Control','no-cache'); //HTTP 1.1 response.setHeader('Pragma','no-cache'); //HTTP 1.0 response.setDateHeader ('Expires', 0); //prevents caching at the proxy server IProxyContext ctx = ProxyContextFactory.getInstance().createProxyContext(request,response); IProxyRequest req = ctx.getProxyRequest(); IProxyResponse res = ctx.getProxyResponse(); Enumeration roles = req.getUser().getRoles(); boolean isAdmin = req.getUser().isUserInRole('AdminRole'); boolean isMgr = req.getUser().isUserInRole('MgrRole'); boolean isUser = req.getUser().isUserInRole('UserRole') %> <html> <head> <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'> <META HTTP-EQUIV='PRAGMA' CONTENT='NO-CACHE'> <title>Preferences</title> </head> <body> <br/> CONSUMER SETTINGS <br/> <% while (roles.hasMoreElements()) { String role = (String)roles.nextElement(); %> <br/>User has role: <%=role%><br/> <% } %> <br/>User is admin? <%=isAdmin%><br/> <br/>User is manager? <%=isMgr%><br/> <br/>User is standard user? <%=isUser%><br/> <pt:ensemble.inject xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/' pt:name='idkLib:rolePagelet'/> </body> </html>
Oracle WebCenter Ensemble provides an API for creating custom mappings to external credential stores, allowing you to authenticate users against a custom credential source.
The IVendorCredentialMapper
interface defines the Oracle WebCenter Ensemble interface for objects capable of obtaining an appropriate set of credentials needed for secondary authentication for a particular user in an application. To implement this interface, follow the directions below.
Create a java class that implements thecom.plumtree.runner.credentialmapper.IVendorCredentialMapper
interface.
Map the getCredential
and setCredential
methods of this interface to your credential vault. The simplified example below uses an internal class called VConnector
and calls VConnector.getInstance().getCrededentialsForDomain
. Note: This step is vendor-specific. It will probably include a network hop, since the credential store will most likely reside on another server. You must give the mapper a unique name, and localized ones if necessary. See the IVendorCredentialMapper API documentation for all required names.
Compile the class into a jar. The build process must link to common.jar, included with the Oracle WebCenter Ensemble distribution.
To load the custom vault into Oracle WebCenter Ensemble, copy the jar file to the Oracle WebCenter Ensemble server and edit the configuration.xml file. Add the following component, and include the path to the custom jar file in the <value>
element:
<component name="runner:credentialproviders" type="http://www.plumtree.com/config/component/type/credentialproviders"> <setting name="CredentialVaultClassPath"> <value xsi:type="xsd:string">c:/jarfolder/jarname.jar</value> </setting> <clients> <client name="runnercontext" /> </clients> </component>
If the Oracle WebCenter Ensemble proxy and adminui run on different servers, the jar file must be copied to both servers, and the configuration.xml file on both servers must be edited.
Restart the Oracle WebCenter Ensemble server (both proxy and adminui if they are on separate servers). The custom credential vault should show up in the list of credential sources on the Credential Mapping page of the Resource editor.
The example below is simplified for illustration purposes.
package com.oracle.credentialvault; import com.oracle.connector.CredentialsSet; import com.oracle.connector.VConnector; import com.plumtree.runner.credentialmapper.Credential; import com.plumtree.runner.credentialmapper.IVendorCredentialMapper; public class OracleCredentialVault implements IVendorCredentialMapper { /* * Ensemble will pass credential types as following: * Runner_*, where * is what the credential value type associated with this login form in the Ensemble adminui. * For example, if the credential value type is 'username' then "Runner_username" will be passed to the mapper. */ public Credential getCredential(String initiator, String credType) { System.out.println("OracleCredentialVault::getCredential, initiator: " + initiator + ", credType: " + credType); /* * Since this vault stores credentials per user and domain, we need to devise a scheme to * map Ensemble's credential type to a domain. One way to do this is to specify the credential * type as something like: "domain_type", which would translate to credTypes like: * Runner_domain.com_username and Runner_domain.com_password */ String username = initiator.toLowerCase(); // lets assume that the vault stores all usernames in lowercase String domain = "oracle.com"; //getDomain(credType); // lets assume that the vault stores all domains in lowercase String type = credType; //getType(credType); CredentialsSet credSet = VConnector.getInstance().getCrededentialsForDomain(username, domain); if( credSet != null ) { System.out.println("OracleCredentialVault::getCredential, found vault set: " + credSet.toString() + ", returning type = " + type); return new Credential(credSet.getCredential(type)); } else { System.out.println("OracleCredentialVault::getCredential, found null vault set"); return null; } } public String getDescription(String userLocale) { return "Test mapper that mimics a mapper between Ensemble and a credential vault that associates credentials with a username/domain relationship"; } public String getName() { return "OracleCredentialVault"; } public String getName(String userLocale) { return "OracleCredentialVault"; } public String getVendorName(String userLocale) { return "Oracle"; } public boolean setCredential(String initiator, Credential credential, String credType) { System.out.println("OracleCredentialVault::setCredential, initiator: " + initiator + ", credType: " + credType + ", Credential: " + credential.getCredentialValue()); String username = initiator.toLowerCase(); // lets assume that the vault stores all usernames in lowercase String domain = "oracle.com"; //getDomain(credType); // lets assume that the vault stores all domains in lowercase String type = credType; //getType(credType); System.out.println("OracleCredentialVault::setCredential setting username: " + credential.getCredentialValue()); CredentialsSet userCredSet = VConnector.getInstance().getCrededentialsForDomain(username, domain); userCredSet.setCrededential(type, credential.getCredentialValue()); VConnector.getInstance().setCrededentialsForDomain(username, domain, userCredSet); return true; } public boolean supportsCredentialsEditing() { // We can set new credentials using this vault return true; } /* private String getDomain(String credType) { int dstart = credType.indexOf("_"); int dend = credType.indexOf("_", dstart+1); String domain = credType.substring(dstart+1, dend); System.out.println("TestMapper::getDomain, reading domain as: " + domain); return domain; } */ /* private String getType(String credType) { int dstart = credType.indexOf("_"); dstart = credType.indexOf("_", dstart+1); String type = credType.substring(dstart+1, credType.length()); System.out.println("TestMapper::getType, reading type as: " + type); return type; } */ /* private String doGetPropertyValue(String principal, String property) { return doGetPropertyValue(principal, property, ",", "="); } */ /* private String doGetPropertyValue(String principal, String property, String propDelim, String valueDelim) { int propertyindex = principal.toLowerCase().indexOf(property.toLowerCase()); String uname = null; if( propertyindex != -1) { // found a property occurence int beginIndex = propertyindex; int endIndex = principal.toLowerCase().indexOf(propDelim.toLowerCase(), beginIndex); String prop = null; if(endIndex != -1) { prop = principal.subSequence(beginIndex, endIndex).toString().trim(); } else { prop = principal.subSequence(beginIndex, principal.length()).toString().trim(); } if( prop != null ) { int valueIndex = prop.toLowerCase().indexOf(valueDelim); if(valueIndex != -1) { uname = prop.subSequence(valueIndex + valueDelim.length(), prop.length()).toString().trim(); } } } return uname; } */ }
For details on configuring resources to use credential mappings, see the Oracle Fusion Middleware Administrator's Guide for Oracle WebCenter Ensemble and the online help.