17 Creating Custom Pagelets

This chapter provides detailed information about building pagelets using Pagelet Producer, including how to use the Adaptive Pagelet Scripting Framework, configure security settings for pagelets and resources to manage authentication for users, use custom web injectors and parsers to modify pagelet functionality at runtime, and access advanced logging traces for debugging.

This chapter includes the following sections:

17.1 Using the Adaptive Pagelet Scripting Framework

The Adaptive Pagelet Scripting Framework is a client-side JavaScript library that provides services to CSP pagelets and proxied pages. This section explains how to use the scripting framework to implement dynamic functionality in pagelets.

Note:

CSP (and the Adaptive Pagelet Scripting Framework) only applies to WCI and its predecessor, Plumtree Portal. WebCenter Portal does not support CSP.

This section includes the following topics:

For a full list of classes and methods, see the JSPortlet API documentation. For additional information about adaptive pagelets, see What You May Need to Know About Adaptive Pagelet Development.

17.1.1 How to Handle Structured HTTP Responses

This section describes how the adaptive pagelet scripting framework can be used as a client-side response handler for structured HTTP, 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="/images/plumtree" style="display:none"></a>
<script type="text/javascript"
src="/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 -->
-->

<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>

17.1.2 How to Use Event Notification

This section describes how the adaptive pagelet 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 scripting framework provide pagelets with access to page-level events. For a complete list, see How to Use Page-Level Events with the 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 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.

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.

The second listener pagelet displays the cube root of the number entered in the broadcast pagelet.

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>
&nbsp;<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>

17.1.2.1 How to Use Page-Level Events with the Scripting Framework

The scripting framework automatically has access to the following page-level events.

Table 17-1 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

17.1.3 How to Use In-Place Refresh

This section describes how pagelets can reload their internal content without refreshing the page using the 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 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 in-place refresh is executed by calling the refresh() method on the pagelet object instance. You can also set a new URL to be displayed within the pagelet upon 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>

<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>

17.1.4 How to Use Session Preferences

This section describes how 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 using 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.

When the user enters a color code in the text box, the color in the detail pagelet changes.

For each onkeyup event that occurs in the "Enter color" text box in the master pagelet, the following steps are executed:

  1. The master pagelet sets the session preference using the current value of the text box.

  2. The master pagelet calls an update method on the detail pagelet.

  3. The detail pagelet retrieves the session preference to get the color value.

  4. The detail pagelet redraws its color swatch area to reflect the new color value.

Note:

Shared session preferences must be specified by name on the Preferences page for the pagelet in the Pagelet Producer Console or they will not be sent to the pagelet.

The adaptive pagelet scripting framework provides an easy way to detach the relationship between pagelets and use a common event interface for communication.

Note:

The example below 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.

Master Pagelet

<div style="padding:10px;" align="center">
<p><b>Enter color:</b> &nbsp;
<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> &nbsp;
<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>

17.1.5 What You May Need to Know About Adaptive Pagelet Development

These tips apply to most pagelets that use the adaptive pagelet 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.

  • Proxy all URLs. You cannot make a request to a URL with a host/port that is different from that of the calling page. All URLs requested through JavaScript must be proxied.

  • If you are using the adaptive pagelet scripting framework, check for 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 pagelet only works in portals that support the JSPortlet API .
    The pagelet 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.

  • 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.

17.2 Modifying Pagelet Functionality at Runtime

This section describes how to modify pagelet functionality at runtime using custom injectors and parsers.

This section includes the following topics:

17.2.1 How to Use Web Injectors

A web injector inserts content into a specified location in the proxied resource page. The content may be any text, including HTML, CSS, JavaScript, and pagelet declarations. An empty injector may also be used to remove unwanted content from a page. Injectors cannot be created for OpenSocial resources. While injecting simple HTML content has a limited use case, you can also inject JavaScript that directly modifies the pagelet's HTML markup. For details on creating a web injector, see Creating Web Injectors.

17.2.2 How to Use Custom Parsers

Custom parsers allow you to supplement or change built-in logic for parsing content and finding URLs. When the built-in parsers fail to identify URLs or identify sections that must not be rewritten as URLs, custom parsers can be used to change the default behavior. Parsers cannot be created for WSRP or Oracle PDK-Java portlet producers or for OpenSocial gadget producers. For details on creating a custom parser, see Creating Custom Parsers.

17.3 Debugging Pagelets

This section describes how to use advanced logging traces for debugging pagelets. Logging is configured in the Settings section of the Pagelet Producer Console, where you can define different levels of logging for each Pagelet Producer component. For more information, see Configuring Pagelet Producer Settings.

This section includes the following topics:

17.3.1 How to View HTTP Requests and Responses

To view the HTTP requests and responses received and sent by Pagelet Producer, set the HTTP component on the Logging Settings page to Finest. The traces in "HTTP Request Received By Pagelet Producer," "HTTP Response Sent By Pagelet Producer," "HTTP Request Sent By Pagelet Producer," and "HTTP Response Received By Pagelet Producer" were captured from a test environment.

HTTP Request Received By Pagelet Producer

URL: http://example.com:7001/pagelets/bidwiki/includes/js/ajax.js
METHOD: GET
SESSION ID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614!1305769149498
HEADERS: 
Host: example.com
 Connection: keep-alive
 Referer: http://example.com:7001/pagelets/bidwiki/dashboard.action
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16
 Accept: */*
Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8,ru;q=0.6,it;q=0.4
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 If-None-Match: W/"736-1124953206000"
 If-Modified-Since: Thu, 25 Aug 2012 07:00:06 GMT
COOKIES: 
JSESSIONID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614

HTTP Response Sent By Pagelet Producer

URL: http://example.com:7001/pagelets/bidwiki/styles/main-action.css
Response Code: 200
Reason: 
HEADERS: 
Date: Thu, 19 May 2011 01:39:14 GMT
 Content-Type: text/css;charset=UTF-8
 Server: Apache-Coyote/1.1
BODY: 
.sidebar {
/*background-image: url(http://example.com:7001/pagelets/bidwiki/download/ resources/leftnav_bg.jpg);*/
 /*background-repeat: repeat-y;*/
 background-color: #F0F0F0;
 /*border-bottom:1px solid #F0F0F0;*/
} ...

HTTP Request Sent By Pagelet Producer

URL: http://xmlns.oracle.com/includes/js/ajax.js
METHOD: GET
HEADERS: 
CSP-Ensemble-REST-API: http://example.com:7001/pagelets
 X-Client-IP: example.com
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16
 CSP-Session-Username: weblogic
 Accept-Language: en-US,en;q=0.8,ru;q=0.6,it;q=0.4
 CSP-Gateway-Type: Proxy
 PT-Proxy-Passes: 1
 If-Modified-Since: Thu, 25 Aug 2012 07:00:06 GMT
 CSP-Protocol-Version: 1.4
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 Accept-Encoding: gzip,deflate,sdch
 Referer: http://example.com:7001/pagelets/bidwiki/dashboard.action
 If-None-Match: W/"736-1124953206000"
 Accept: */*
CSP-Aggregation-Mode: Single
 PT-Proxy-instance0: {DECBB085-D891-72CF-2B75-005E7FE20000}
 CSP-Gateway-Specific-Config: PT-User-Name=weblogic,PT-Guest-User=0,...

HTTP Response Received By Pagelet Producer

Original URI: http://xmlns.oracle.com/styles/main-action.css
Effective URI: http://xmlns.oracle.com/styles/main-action.css
Status Code: 200
Reason: OK
Version: HTTP/1.1
HEADERS: 
Content-Type: text/css;charset=UTF-8
 Content-Length: 29178
 Server: Apache-Coyote/1.1
 Date: Thu, 19 May 2011 01:39:14 GMT
TRAILERS: 
BODY: 
body, p, td, table, tr, .bodytext, .stepfield {
font-family: Verdana, arial, sans-serif;
 font-size: 11px;
 line-height: 16px;
 color: #000000;
 font-weight: normal;
}

17.3.2 How to View Transformation Content

To view the content proxied by Pagelet Producer before and after transformation, set the Transform component on the Logging Settings page to Finest. The purpose of these traces is to log response content at different stages of transformation, allowing you to compare them and view the result of different transformers. The example traces in the following examples were captured from a test environment.

Example: Untransformed Markup

Original request: URL: http://example.com:7001/pagelets/bidwiki/styles/main-action.css
METHOD: GET
SESSION ID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614!1305769149498
HEADERS: 
Host: example.com:7001
 Connection: keep-alive
 Referer: http://example.com:7001/pagelets/bidwiki/dashboard.action
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16
 Accept: text/css,*/*;q=0.1
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8,ru;q=0.6,it;q=0.4
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
COOKIES: 
JSESSIONID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614
 
Untransformed content: 
body, p, td, table, tr, .bodytext, .stepfield {
font-family: Verdana, arial, sans-serif;
 font-size: 11px;
 line-height: 16px;
 color: #000000;
 font-weight: normal;
}

Example: Transformed Markup (Transformed by Transformer Class)

Transformed by: class com.plumtree.server.impl.portlet.transformers.CSSTurboParser
 Original request: URL: http://example.com:7001/pagelets/bidwiki/styles/main-action.css
METHOD: GET
SESSION ID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614!1305769149498
HEADERS: 
Host: 10.148.118.211:7001
 Connection: keep-alive
 Referer: http://example.com:7001/pagelets/bidwiki/dashboard.action
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16
 Accept: text/css,*/*;q=0.1
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8,ru;q=0.6,it;q=0.4
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
COOKIES: 
JSESSIONID: GdYGNJzMhxy1CJBMVTX8xTNq32GmLXYNY9VqFBcdprFnhcyQtzdp!1377086614
 
Transformed content: 
body, p, td, table, tr, .bodytext, .stepfield {
font-family: Verdana, arial, sans-serif;
 font-size: 11px;
 line-height: 16px;
 color: #000000;
 font-weight: normal;
}