Friday, July 22, 2011

WebCenter Navigation model revisted: creating UI menus and the hidden gem...

Typically, portals provide information from various different sources. Information may be provided by pages, portlets, task flows, content repositories, and external pages. Users need a way to easily move through this information and quickly access the specific information that they need. You provide this access to information through your portal navigation.  The navigation model defines the content, structure, and metadata of the navigation. When you create the navigation model, you specify the items to include and the hierarchy of those items. Navigation models can include the following resources, for example, pages, external resource, page queries, and other navigation models.

Using the navigation model, you can then create a  UI menu, using a combination of standard HTML tags, JSTL, and Epresssion Language (EL) to interate through the model collection.  The rendering, or look-n-feel of the menu is implemented by the CSS (skin). 

In this blog I will not be covering the creation of the navigation model, since there are numerous blogs covering this topic.  Rather I will focus more on how to render the menu in the UI, and also point out a hidden property on the naigation model that will enable you to write less code when iterating through the navigation model's collection.

Let's look at a example of a navigation model, which was created in Spaces. (Note: The following information are also relevent in a 'custom' WebCenter Portal Application).


Basically, there are 3 main (top) links (i.e. Parents), and 2 'children' under the Parent 1 link.  One of the children in this model is a regular (link) to a Page, and the other child is a Page Query (which can return a collection of Pages.  Using the Preview option in the Edit navigation model, the model will display the desire behavior in the UI.



As you can see, the Page Query also returns it's own collection of pages.  Now that we have the navaigation model in place, we now need to create the UI code that will iterate through the naigation model's collection.  As I mentioned before, I will use in this example standard code.  The following is the code that I will use to visualize my navigation model:


When I add the code to my Space Page Template, and refresh the View, the following get displayed:

So far so good.  I can see the hierarchy of the links have stamped out correctly.  In addition, the code that is iterating through the model collection is pretty straight foward.  You will also notice that there are also CSS style classes set on many of the code elements to enable the <UL> to look like a standard menu (with it's children as menu items).  When I add the CSS to my Spaces Page Template as a standard adf resource, and rerun the page, you can see the <UL> look like a standard menu:

OK, now that is what I am expecting.  A nice menu, which supports a hierarchtical navigation model.

Now, I would like to take the navigation model one step further (later exposing the hidden gem), by adding a navigation model reference into my main navigation model.  Basically, a navigation model reference enables the model to add it's model collection to the main models collection.

For this example, I will create a simple navigation model, which has only 3 parent pages.  (Note: you are not contrained to this, since this this is a full navigation model):


Back in the (main) navigation model, I will add this navigation model (under Parent 3) in the main as a navigation model reference:

Previewing the main navigation model, I can see that I am able to view the reference navigation model's child links:
Now when I rerun the template, I should be able to see the navigation model child links, just like the Page Query:



Great!  Now lets change this up a bit.  Since my code is set to iterate through the multi-levels, I would like to add the navigation model reference as a child to another child (i.e. grandchild).


Re-running the template:

Great, the UI code can still handle the multi-levels! 

So what is the hidden gem?  When you  create a navigation reference in Spaces (unlike-custom WC Portal app), there is an attribute property that gets set for you automatically.  For example, the following is the navigation model code snippet from my demo:

includeNavigation id="newincl5" insertFolderContents="true"

It is the insertFolderContents attribute, which enables the collection to 'bubble up' past the initially nav model reference.  What I mean is that the navigation model reference inside of another navigation model, is actually a 'folder', that then holds it's children.  So setting the insertFolderContents= false, (or in the case of doing these operations in the JDeveloper custom Portal application), not having this attribute set at all, will not let the navigation model reference expose it's children in the current UI code.  You can, however, write additional code to 'check' to see if the current node is a 'folder'.  But, that would me writing more code for every level of the hierarchy.  I would rather ensure that this attribute is set to 'true'.

Wednesday, June 22, 2011

Disabling Content Compression in WebCenter Spaces

By default, and for performance/optimization, WebCenter Spaces runs in the browser with the page markup generation compression set to be ON. 


However, there are cases when you are developing a customized skin (CSS) for Spaces, that you need to "see" the actual component's style class selector name (af_panelGroupLayout), not the compressed version (i.e. xyz).  To disable the compression is an easy step.  Bascially, you will need to add a context-param to Spaces web.xml:

<context-param>
  <param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
  <param-value>true</param-value>
</context-param>

What's not so intuative is how this is achieved in Spaces.  The best way to do this is through the extension workspace, DesignWebCenterSpaces.jws.  You can get more information on "extending" Space, and also the download link to the workspace here.  Once you have downloaded (and configured) the DesignWebCenterSpaces workspace, you can then follow the next steps.

Double-click the WebCenterSpacesExtensionLibrary project inside the workspace.  This will open the Project Properties dialog. In the left pane, select the Project Source Paths.  In the "Included" tab section, click on the "Add..." button.  From within the "Add Include Filters"dialog, navigate to and select the web.xml file from within the WebCenterSpacesExtensionLibrary/public_html/WEB-INF directory. 


Click OK to dismiss the dialog.  This will add the web.xml to the project.


Next, in the left pane, click on "Deployment".  In the right pane, select the custom_webcenter_spaces_war (WAR File) deployment profile, and click the "Edit..." button.  This will open the Edit WAR Deployment Profile Properties dialog.  In the left pane, open the "File Groups", "Web Files" section, and select "Filters".  In the right pane, check the web.xml file.


Click OK, to save and dismiss the dialog. Next click OK to save and dismiss the Project Properties dialog.  In the Application Navigator, expand the WebCenterSpacesExtensionLibrary\public_html\WEB-INF folder.  Notice that the web.xml has been added.  Double-click on this file to open it in the file editor.  Remove the <filter>, and <filter-mapping> tags, as these tags are not needed.  Next add the tags that will enable the disabling of the content compression:

<context-param>
  <param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
  <param-value>true</param-value>
</context-param>

Save the file.  The next step is to regenerate the WAR file for deployment.  (Note: by default (OOTB), there is already a version of this war, which has been deployed to the Spaces server.  The deployment process will created a "versioned" war.  More on this later ...)  Locate the build.xml file, which is located within the WebCenterExtensionLibrary project.  Right-click on the build.xml, and from the context menu, select "clean stage" from the Run ANT target menu options.


This will create the new "extend.spaces.webapp.war" file, which will update the already deployed version in Spaces.  Before deployment, you can check to see if the web.xml has been added to the war by looking into the "exploded" directory. For example:


You will see a <servlet> tag has been added along with the content compression based tag, but this is OK.  Once you have confirmed that the web.xml has been added.  You are ready to deploy the new war to the WebLogic managed instance. Locate the build.xml file again.  Next right-click on the file, and from the context menu, select "deploy-shared-lib" from the Run ANT target menu options.


The ANT task will run and deploy the new version of this war.  After a successfull execution, you can view the new deployment in the WebLogic console.  The newest version, signified by the highest version number, will be the library that gets used by WebLogic.


After the deployment has been verified, you will need to RESTART the Spaces managed instance.  Once this is done, open up Spaces and for example, in Firebug you will notice that the style classes are displaying the real names. 


 As you can see, this option can really help speed up the development of a CSS, and ensure that you are using the right style class.

Wednesday, June 15, 2011

Improving WebCenter Performance – Part 2

If you read George’s previous post you can also improve the client side performance, this is useful if you are running a demonstration, workshop or have a controlled IT environment where you have mandate to configure the client browser environment.
This post will look at how we can improve the client side experience of the performance and also limit the computation time for certain common operations.

Login process
The login process takes in general longer time than the subsequent operations, there is several reasons for this one is the caching which George already addressed. Secondly if you have large identity store or limited response times from the directory servers you can implement caching so the ldap bind, authentication and user information retrieval impact can be reduced.

Add following lines to jps-config.xml:

   1: <serviceInstance name="idstore.ldap" provider="idstore.ldap.provider">
   2:     <property name="idstore.config.provider" value="oracle.security.jps.wls.internal.idstore.WlsLdapIdStoreConfigProvider"/>
   3:     <property name="CONNECTION_POOL_CLASS" value="oracle.security.idm.providers.stdldap.JNDIPool"/>
   4:     <extendedProperty>
   5:       <name>user.object.classes</name>
   6:          <values>
   7:          <value>top</value>
   8:          <value>person</value>
   9:          <value>inetorgperson</value>
  10:          <value>organizationalperson</value>
  11:          <value>orcluser</value>
  12:          <value>orcluserv2</value>
  13:          <value>ctCalUser</value>
  14:        </values>
  15:   </extendedProperty>
  16: </serviceInstance>


The jps-config.xml can be found in the domain configuration where the affected managed server is running
[domains/wc_domain/config/fmwconfig]

For more information see:
http://download.oracle.com/docs/cd/E21764_01/webcenter.1111/e12405/wcadm_security_id_store.htm#BGBGIAHC


Browser tuning
Many organizations are using Internet Explorer in various version, currently when Internet Explorer is installed it comes with following download concurrency support:
Version 7: Two simultaneous download threads
Version 8: Six simultaneous download threads
Considering Georges previous blog about the near 100 downloads for some page requests when caching is not present, to tune the browser can improve the perception of the performance for the user. Microsoft has released two self fixing steps that can be taken to increase the concurrency to 10.


If you want to implement the steps manually or automatic please refer to the link below, remember to use the browser version you want to target so you get the right fix.


For more information see:
http://support.microsoft.com/kb/282402
If you click the “Fix it” link then it will download the registry fix and install it for you, alternatively you can use the manual procedure.

Wednesday, June 1, 2011

Improving WebCenter Performance – Part 1 (IIS Addendum)

If you read my previous post you might be wondering if you can achieve a similar performance with a different Web Server such as Microsoft Information Server. In this article I’ll describe the steps you need to follow to have IIS not only applying content compression, but also rewriting the expiration data in the HTTP header.

STEPS


1. Open the Internet Information Services Manager, right-click on the Default Web Site option and select Properties.

clip_image002

2.
The window below should show up. Check the “Expire after” option and set it to 1,193 Hour(s). It will change the HTTP header Cache-control parameter from Expire to max-age in all local static resources, which solves the Internet Explorer caching issue.

clip_image004

3.
Click on the MIME Types button and add the following ones:

clip_image006

4.
Select the ISAPI Filters tab and check where the WebLogic ISAPI plug-in (wlFilter) is installed. The plug-in allows a smooth integration of WebLogic's HTTP functionality into Microsoft IIS.

clip_image008

Under the iisforward.dll’s directory you should find iisproxy.ini. Open the ini file and add the FileCaching=ON property as shown below. It will add another level of buffer to IIS and force it to add Content-Length property to the HTTP Header.

WebLogicHost=<WebCenter / Load Balancer host> 
WebLogicPort=<WebCenter / Load Balancer port> 
ConnectTimeoutSecs=20 
ConnectRetrySecs=2 
WlForwardPath=/webcenter,/rest 
Debug=OFF 
FileCaching=ON 

5. Make sure content compression is still setup. Right-click on Web Sites and choose properties.

clip_image010

Select the Service tab. The “Compress static files” option must be checked.

clip_image012


Don’t forget to restart IIS after the changes.

Improving WebCenter Performance – Part 1

Tuning is quite a long and complex subject to be discussed in a single article. This first post will cover 2 basic strategies to make your Oracle WebCenter installation faster by tweaking the browser caching and adding content compression. By the end of this article your WebCenter pages should be rendering in less than 2 seconds – obviously depending on your environment – and with fewer requests.

Browser Caching


Your browser has a folder in which certain items that have been downloaded are stored for future access. Images, stylesheets, javascripts, and even entire web pages are examples of cached items. When accessing a website, your browser will check its cache folder first to see if it already has those images and, if so, it won't take the time to download them again.
There are two main reasons that web caches are used:
To reduce latency — Because the request is satisfied from the cache instead of the web server itself, it takes less time for the representation to render in the browser.
To reduce network traffic — Since there are less items to be downloaded from a web site, it reduces the amount of bandwidth used by a client.
Like in any other application, WebCenter Portal have static resources that need to be cached by the browser in order to reduce subsequent download access. The trick here is to setup OHS to rewrite the HTTP header of some specific virtual paths related to static resources in WebCenter.
We will use max-age instead of Expire. The max-age directive specifies the maximum amount of time that a representation – or file - will be considered fresh. From my perspective, the big advantage of this directive is that it’s relative to the time of the request, rather than absolute. max-age also seems to behave better with IE in general. I haven’t checked that in IE 9 so far. For this exercise, we’ve setup max-age to 2592000 seconds (30 days).

Header unset Last-Modified
Header unset Expires
Header set Cache-Control "max-age=2592000, public"
Header set Surrogate-Control "max-age=2592000"

Content Compression


To do content compression in OHS you need to configure mod_deflate. It should already be installed in your OHS under $MIDDLEWARE_HOME/Oracle_WT1/ohs/modules/mod_deflate.so. But it might not be loaded.

LoadModule deflate_module        "${ORACLE_HOME}/ohs/modules/mod_deflate.so"

With mod_deflate, you can compress HTML, text or XML files to approx. 20 - 30% of their original sizes, thus saving you server traffic. However, compressing files causes a slightly higher load on the server, but again, clients' connection times to your server decrease a lot.

mod_deflate requires you to specify which type files are going to be compressed.

AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/html

Images are supposed to be in a compressed format, and therefore are bypassed by mod_deflate.
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary

Quick Setup


To have all those changes applied to your environment, please download webcenter.conf and replace the variables listed below accordingly.
  • [wc_spaces host]
  • [wc_spaces port]
  • [wc_services host]
  • [wc_services port]
  • [ses host]
  • [ses host]
If you already have portlets being consumed by your application, don’t forget to add the proper mod_wl entries.

#Portlets
#Insert your portlet mapping here
<Location /[portlet path]>
SetHandler weblogic-handler
WeblogicHost [wc_portlet host]
WeblogicPort [wc_portlet port]
</Location>
 

And if you have already separate the static assets from your application into a different directory, you might want to set the same configuration:

Alias /[virtual path for static files] [physical path for static files]
 
<Location /[virtual path for static files]/>
Header unset Last-Modified
Header unset Expires
Header set Cache-Control "max-age=2592000, public"
Header set Surrogate-Control "max-age=2592000"
</Location>

After doing the proper setup you can drop the webcenter.conf file into $MIDDLEWARE_HOME/Oracle_WT1/instances/instance1/config/OHS/ohs1/moduleconf. You MUST restart OHS for the changes to take effect.

TESTING


Now let’s access WebCenter to see how fast it is. The first access any WebCenter Spaces page should be faster since we’re using content compression, but it should still bring lots of resources such as js files, images, css, etc.
1st Access
Capture
Activities page renders in approximately 7.5 secs with 91 requests.
2dn Access
Capture2
A subsequent access to the same page takes less than half a second and only requires a single request. All other static assets are cached by the browser and don’t need to be downloaded again.
Others
Any other request to pages that haven’t been accessed before should take less requests to render, since most of the WebCenter resources have been downloaded previously.
Capture3
Spaces page takes 1.1 seconds and 7 requests to render. Blazing fast, my friends!