<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-2976473844390099876</atom:id><lastBuildDate>Thu, 11 Jun 2009 14:53:56 +0000</lastBuildDate><title>Fabien Sanglier: Going Further With ALUI / Webcenter</title><description>This blog specializes on ALUI / Webcenter Portal knowledge (as well as all its components:Collaboration Server, Publisher, Studio, Analytics), portal best practices, technical tips, portlet development, portal customizations, troubleshooting tips and techniques, performance improvement...and all other technical stuff that I find interesting&lt;br&gt;The whole deal, as it comes to mind!!</description><link>http://fsanglier.blogspot.com/</link><managingEditor>noreply@blogger.com (Fabien Sanglier)</managingEditor><generator>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/fsanglier/alui" type="application/rss+xml" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-6836833251409326755</guid><pubDate>Wed, 10 Jun 2009 03:34:00 +0000</pubDate><atom:updated>2009-06-09T23:36:08.783-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Native API</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>Adding JavaScript includes to all portal browsing pages</title><description>&lt;p&gt;In almost every portal deployment, we usually have the need to create some JavaScript libraries that can be used by various components…possible functions could be window openers, url encoder/decoder or any other utility functions that you might not want to include in all your portlets.&lt;/p&gt;  &lt;p&gt;Now, the question is: how do you add it to the portal page as (a) global include(s)? 2 possibilities:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Add the JavaScript include(s) to the portal header/footer portlets (which is usually done in publisher, and displayed on all pages) &lt;/li&gt;    &lt;li&gt;Create a small UI customization that does the job more reliably. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;You might have guessed it now: option 1 is not the one I am going to explain here. Why?&lt;/p&gt;  &lt;p&gt;First, option 1 would not be worth a blog post since it is fairly easy to implement. But more seriously, depending on header or footer portlets is not reliable in order to include global resources. Indeed, different portlet headers/footers are displayed based on the current experience definition, and/or the current community you are in. Also, the header/footer portlet content can easily be modified (especially if implemented in publisher for example) which increase the chances of removing the resource include(s).&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Ok, let’s dive into option 2!&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;By customizing the 2 main browsing portal DP (stands for Display Page) classes (MyPortalDP and GatewayHostedDP), you will be able to include all the JavaScript resource you need on virtually all end user portal pages: all portal community pages and on the gateway page in hosted display mode.&lt;/p&gt;  &lt;p&gt;Luckily, those DP classes provide a method to override: DisplayJavaScriptFromChild. This method returns an HTMLScriptCollection object that will be read in order to add the JavaScript to the header tag (in between the portal &amp;lt;head&amp;gt;&amp;lt;/head&amp;gt; tags).&lt;/p&gt;  &lt;p&gt;The following could be what you might want to have in this method override (it gets the list of JavaScript files to include from a Varpack, and iterate through this list in order to add it to the returned HTMLScriptCollection object)&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;protected override HTMLScriptCollection DisplayJavaScriptFromChild()&lt;br /&gt;{&lt;br /&gt;    HTMLScriptCollection scriptCollection = base.DisplayJavaScriptFromChild();&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        //get all the JS to include&lt;br /&gt;        XPArrayList arrJSToInclude = ...Getting this from Varpack is a good idea, and as such, recommended...;&lt;br /&gt;        if(null != arrJSToInclude &amp;amp;&amp;amp; arrJSToInclude.GetSize() &amp;gt; 0)&lt;br /&gt;        {&lt;br /&gt;            IXPEnumerator jsEnum = arrJSToInclude.GetEnumerator();&lt;br /&gt;            string src = &amp;quot;&amp;quot;;&lt;br /&gt;            while(jsEnum.MoveNext())&lt;br /&gt;            {&lt;br /&gt;                src = (string)jsEnum.GetCurrent();&lt;br /&gt;                if(!&amp;quot;&amp;quot;.Equals(src))&lt;br /&gt;                {&lt;br /&gt;                    HTMLScript script = new HTMLScript(HTMLScript.TYPE_JAVASCRIPT);&lt;br /&gt;                    src = src.Replace(&amp;quot;pt://images/&amp;quot;, ConfigHelper.GetImageServerRootURL(m_asOwner));&lt;br /&gt;                    script.SetSrc(src);&lt;br /&gt;                    log.Debug(&amp;quot;Adding JS external file with src: {0}&amp;quot;, src);&lt;br /&gt;                    scriptCollection.AddInnerHTMLElement(script);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    } &lt;br /&gt;    catch (Exception exc)&lt;br /&gt;    {&lt;br /&gt;        log.Error(exc, &amp;quot;An exception occurred while adding the custom javascript to the page head.&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;    return scriptCollection;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I never recommend customizing directly the portal classes...that way it is a bit simpler if you need to upgrade the portal version: you custom code is not everywhere.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So instead of customizing directly MyPortalDP and GatewayHostedDP, create new custom classes that inherit from those 2...then make sure your custom classes are loaded properly in the related Activity Spaces (PlumtreeAS and GatewayAS)...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Hope that is helpful!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-6836833251409326755?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=UeEG-T2zsmw:JJydShgGQKI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=UeEG-T2zsmw:JJydShgGQKI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=UeEG-T2zsmw:JJydShgGQKI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=UeEG-T2zsmw:JJydShgGQKI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/UeEG-T2zsmw/adding-javascript-includes-to-all.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2009/06/adding-javascript-includes-to-all.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-2503199004837785334</guid><pubDate>Mon, 11 May 2009 20:33:00 +0000</pubDate><atom:updated>2009-05-11T16:34:09.430-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Best Practices</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Search</category><category domain="http://www.blogger.com/atom/ns#">Portal Maintenance</category><title>ALUI Webcenter Grid Search: Maintaining the search cluster repository without loss of service</title><description>&lt;p&gt;Sometimes, for maintenance reasons, the cluster repository has to be unavailable for a short amount of time (I.e. the NAS on which it is hosted is patched and need to be restarted, or the central search cluster repository needs to be moved from one server to another, etc…). &lt;/p&gt;  &lt;p&gt;The main problem is that search relies heavily on the availability of search cluster repository in order for the portal content to be properly indexed (for example, the cluster registers any new index delta and ensures that these delta are redistributed to each node’s local index, that way the search nodes are always in sync with one another). Unfortunately, I’ve noticed many times that when the cluster becomes not available for as short as a couple of seconds, the search infrastructure does NOT handle this gracefully…&lt;/p&gt;  &lt;p&gt;At best, the nodes all go in “read-only” mode automatically (meaning the nodes act only as query service instead of query+index service), corrupting most of the time the process handles of the node being the “indexer” at the time of disconnection (you’ll see “invalid handles” errors in the search status screen for example)…at worse, all the nodes shutdown with a great “out of memory” error. Both scenario is not a good one, since it will not go back in run mode automatically after the disruption is over, and will probably require a overall restart of nodes.&lt;/p&gt;  &lt;p&gt;If you need to do this in PROD where uptime is usually a strong requirement, then the idea is to do such an operation without jeopardizing the search capabilities of your portal site(s). Indeed, search being so central to portal, when down, many portlets or components relying on search will be down, and overall service will be pretty degraded.&lt;/p&gt;  &lt;p&gt;Fortunately, search comes with a powerful admin utility: cadmin.exe. You can find it on any of your search nodes, usually at the following path:&lt;/p&gt;  &lt;p&gt;&amp;lt;pt_search_home&amp;gt;/bin/native/cadmin.exe&lt;/p&gt;  &lt;p&gt;Using the tool, you can gracefully put all the search nodes in “read-only” mode &lt;strong&gt;before&lt;/strong&gt; the maintenance operation. Indeed, when the nodes are in read-only mode, each node act as a “disconnected” query service, providing search results solely based on their local index. While in that state, the search cluster can be fully unavailable… and apart from any new content not being indexed, end users will not see any search disruption.&lt;/p&gt;  &lt;p&gt;So here are the commands you would want to perform, either manually or in a batch:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;cadmin runlevel readonly&lt;/em&gt; –-&amp;gt; this puts all the nodes of the cluster in readonly mode     &lt;br /&gt;&lt;em&gt;cadmin status –-verbose&lt;/em&gt; –-&amp;gt; this give you the status of the cluster. useful to make sure the previous operation worked as expected.     &lt;br /&gt;    &lt;br /&gt;…perform your maintenance operation…     &lt;br /&gt;    &lt;br /&gt;&lt;em&gt;cadmin runlevel run&lt;/em&gt; –&amp;gt; put all the nodes on the cluster back in run mode     &lt;br /&gt;&lt;em&gt;cadmin status –verbose&lt;/em&gt; –&amp;gt; sanity check…&lt;/p&gt;  &lt;p&gt;What you would want to do before any search maintenance is perform a search checkpoint (in other word search backup). 2 options: doing it manually using the Admin UI, or using the cadmin tool as follows:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;cadmin checkpoint --create&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;As an extension of this, you can check out the other operations you can perform with the cadmin tool (pretty much everything you can do with the search cluster admin UI, with more power added to it) by entering &lt;em&gt;cadmin –help&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Hope that helps. Until next time, take care!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-2503199004837785334?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=6HERF_0qz_c:Vj-1kZut0eM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=6HERF_0qz_c:Vj-1kZut0eM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=6HERF_0qz_c:Vj-1kZut0eM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=6HERF_0qz_c:Vj-1kZut0eM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/6HERF_0qz_c/alui-webcenter-grid-search-maintaining.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2009/05/alui-webcenter-grid-search-maintaining.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-7330668333245279369</guid><pubDate>Sun, 15 Mar 2009 20:38:00 +0000</pubDate><atom:updated>2009-03-15T16:39:52.594-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">ALUI Component</category><category domain="http://www.blogger.com/atom/ns#">Bug</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">bug fix</category><title>ALUI Publisher: Easy bug fix with portlet templates…</title><description>&lt;p&gt;I know ALUI Publisher is on the down slope, but until then, it does not mean I should not share some of my findings…Lately, I found something in publisher that does not make sense to me. It has to do with the creation of portlets based on publisher portlet templates. Let me explain the problem…and then the quick fix…&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;The problem:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Out of the box, when you create a portlet based on a publisher portlet template (i.e. announcement, news, etc…), there is a screen where you are asked to choose a publisher folder where the portlet publisher content should be…When clicking on the “chose publisher folder”, a publisher tree pops up, and you can pick the publisher folder. The tree picker will only show you the folders where you have “producer” access…until now it makes sense since only the “producer” role and above can create folders in publisher. &lt;/p&gt;  &lt;p&gt;But what if a user does have “producer” access to a subfolder Z located in the tree structure at X &amp;gt; Y &amp;gt; Z…but does &lt;u&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/u&gt; have producer access to the parent folder X and Y?? Then the tree picker would simply stop showing the tree at X, hence not showing the subfolder to which the user has actually access to…hence problem.&lt;/p&gt;  &lt;p&gt;A perfect (and probably common) use case is where you have various publisher sites (i.e. an intranet site, and internet site, etc…) and within each of these, you have various “community-related” publisher folders… (folders that contain the web content of each community). You will want your community administrators (in the portal) to also have “producer” or “folder administrator” role in their “community-related” publisher folder…but not have these roles in the parent publisher folders…they should have “reader” access on these parent folders…&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;The solution:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;By reverse engineering publisher one more time, I found out that this problem can be fixed really easily…basically the publisher tree picker is opened with the following url:&lt;/p&gt;  &lt;p&gt;“../folderpicker_frame.jsp?sid=&amp;quot;+sessionId+&amp;quot;&amp;amp;showItemCategory=0&amp;amp;itemId=&amp;quot;+parentFolderId+&amp;quot;&amp;amp;isMultiSelect=false&amp;amp;rootIsCheckable=true&amp;amp;minRoleId=12”&lt;/p&gt;  &lt;p&gt;What is interesting in this url is the last parameter: minRoleId=12. What it probably means is “show only the folders to the users who have at least a role 12 – producer role – assigned to it.” That’s it, we have our solution…By removing this parameter altogether, the tree will now show the folders to which the user has minimum access to (“reader” access), hence fixing the user case explained above:&lt;/p&gt;  &lt;p&gt;A producer in folder X &amp;gt; Y &amp;gt; Z will now be able to browse down to the Z folder, where he will be able to create a folder.&lt;/p&gt;  &lt;p&gt;And don’t worry, it does not impact core security at all. If the user tries to select folder X or Y as a container for his “announcement” portlet, he will simply receive an error message saying ”you do not have enough access to create a folder”…so no problem.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Detailed instructions:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Make a backup of the publisher application files \bea\alui\ptcs\6.4\webapp\ptcs.ear and \bea\alui\ptcs\6.4\webapp\ptcs.war (obvious, no?)&lt;/li&gt;    &lt;li&gt;Unpack the publisher archive (ptcs.war)&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;navigate to \bea\alui\ptcs\6.4\webapp folder&lt;/li&gt;      &lt;li&gt;create a new dir: ptcs&lt;/li&gt;      &lt;li&gt;navigate to that new dir and execute the following jar command: &lt;em&gt;jar –xvf ../ptcs.war&lt;/em&gt;&lt;/li&gt;   &lt;/ol&gt;    &lt;li&gt;edit the extracted file: ./portlet_packages/portlet_create.jsi&lt;/li&gt;    &lt;li&gt;Find the JavaScript functions “ChooseParentFolder” and “NewParentFolder”&lt;/li&gt;    &lt;li&gt;Remove the “minRoleId=12” from the “var url = …” line (1st line in each functions)&lt;/li&gt;    &lt;li&gt;Still in \bea\alui\ptcs\6.4\webapp\ptcs folder, repackage the war by executing: jar -cvf ptcs.war *&lt;/li&gt;    &lt;li&gt;move the newly created war to the \bea\alui\ptcs\6.4\webapp folder: move ptcs.war ../&lt;/li&gt;    &lt;li&gt;navigate to \bea\alui\ptcs\6.4\webapp: cd ../&lt;/li&gt;    &lt;li&gt;update the ptcs.ear file with the following command: jar -uvf ptcs.ear ptcs.war&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That’s it…&lt;/p&gt;  &lt;p&gt;Before restarting publisher, clean the temp files from the publisher container folders just to make sure your modification is loaded properly.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;\ptcs\6.4\container\tmp\deploy&lt;/li&gt;    &lt;li&gt;\ptcs\6.4\container\work\jboss.web\localhost&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As usual, do this at your own risk…and test it well before deploying to production :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-7330668333245279369?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=U-6KS_6Ccpg:2C2r3d1bJAc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=U-6KS_6Ccpg:2C2r3d1bJAc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=U-6KS_6Ccpg:2C2r3d1bJAc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=U-6KS_6Ccpg:2C2r3d1bJAc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/U-6KS_6Ccpg/alui-publisher-easy-bug-fix-with.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2009/03/alui-publisher-easy-bug-fix-with.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-7424676639702084151</guid><pubDate>Tue, 24 Feb 2009 03:29:00 +0000</pubDate><atom:updated>2009-02-23T22:29:04.395-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Native API</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>New Portal Tools On ALUI Toolbox</title><description>&lt;p&gt;In my efforts of improving the ALUI/Webcenter portal, and especially enhancing its admin management capabilities, I created over time a set of utilities that I think could be useful to the ALUI/Webcenter community. In one of my previous post, I already talked about the &amp;quot;PT URL Replace&amp;quot; utility (refer to: &lt;a title="http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html" href="http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html"&gt;http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html&lt;/a&gt;) which was already on the ALUI Toolbox Google code project as a download only. What I did some days ago is updating the ALUI Toolbox Google project (&lt;a title="http://code.google.com/p/alui-toolbox/" href="http://code.google.com/p/alui-toolbox/"&gt;http://code.google.com/p/alui-toolbox/&lt;/a&gt;) with the &amp;quot;PT URL Replace&amp;quot; code, as well as a couple of new applications/utilities:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Portlet Caching Clearer (web portlet - c#) &lt;/li&gt;    &lt;li&gt;Object Identifier (web portlet - c#) &lt;/li&gt;    &lt;li&gt;Web Service Changer (web portlet - c#) &lt;/li&gt;    &lt;li&gt;Page Lister (web portlet - c#) &lt;/li&gt;    &lt;li&gt;ALUI Knowledge Directory Security Agent (java app runnable from console and/or scheduled task such as ALUI jobs) – feature download at &lt;a title="http://code.google.com/p/alui-toolbox/" href="http://code.google.com/p/alui-toolbox/"&gt;http://code.google.com/p/alui-toolbox/&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Improvements for PT URL Replace utility – &lt;a title="http://code.google.com/p/alui-toolbox/" href="http://code.google.com/p/alui-toolbox/"&gt;http://code.google.com/p/alui-toolbox/&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All the above apps use the &lt;u&gt;&lt;strong&gt;Server API&lt;/strong&gt;&lt;/u&gt; (for Server API introduction, refer to previous posts:) because the tasks performed would not be possible by simply using the IDK. It has been written for ALUI 6.1.x versions and might not work fully on version 6.5 and above without minor changes (because the server API does change between portal releases). When I get the chance, I will update the Google code project with 2 extra branches that follows the more current portal versions.&lt;/p&gt;  &lt;p&gt;The code is released under the &lt;u&gt;&lt;strong&gt;GPL license&lt;/strong&gt;&lt;/u&gt; (you can find a copy the the GPL license in the root folder of the apps, or go to &lt;a title="http://www.gnu.org/licenses/gpl.html" href="http://www.gnu.org/licenses/gpl.html"&gt;http://www.gnu.org/licenses/gpl.html&lt;/a&gt;), and off course is provided without any kind of warranty...&lt;/p&gt;  &lt;p&gt;I'll go quickly over each of these utilities in order for you to understand why they might be useful. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Portlet Caching Clearer: &lt;/u&gt;&lt;/strong&gt;    &lt;br /&gt;In order to maximize performance, each portlet in the portal can have output caching enabled to a particular timeframe. The drawback of such caching mechanism is that the updates performed by content managers are not instantaneously viewable to end users. This portlet that can be added on your &amp;quot;My Page&amp;quot; allows you to clear portlet caching in 3 different ways:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Using the portal tree picker, select the portlet(s) you want to clear. &lt;/li&gt;    &lt;li&gt;Using the portal tree picker, select the &amp;quot;Community Page(s)&amp;quot; whose portlets you want to clear. The utility will find all the portlets currently added to the selected pages, and clear the cache for each of them. &lt;/li&gt;    &lt;li&gt;Using the portal tree picker, select the &amp;quot;Community(ies)&amp;quot; you want to clear. The utility will find all the portlets currently added to the selected pages of the selected communities, and clear the cache for each of them. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;That way the content managers can easily clear caching for a set of pages, communities, or portlets...&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Object Identifier:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;Let's say that you have a portlet application that identify a portal object in its config file by its UUID (or its ID for that matter)...Now let's say you come back to that portlet 6 month later because you need to perform an improvement and/or fix something...Unless you clearly documented what object corresponds to this ID/UUID (and where it is in the portal), it will not be easy to find it (unless you can easily run a DB query...). This portlet basically answer that needs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Provide a UUID and it will tell you the corresponding Classid/ObjectID pair + Object Name + Object Location in the Portal Admin Hierarchy. &lt;/li&gt;    &lt;li&gt;Provide a Classid/ObjectID pair, and it will tell you the corresponding UUID + Object Name + Object Location in the Portal Admin Hierarchy.      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Web Service Changer:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;Have you ever noticed that you cannot change the webservice attached to a portlet once you initially picked it and created the portlet? Now let's say that you have a bunch of publisher portlets that are all tied to the same &amp;quot;Publish Content Web Service&amp;quot; object. But all a sudden, you change your mind and decide to have some portlets that should be tied to 2 different &amp;quot;Publish Content Web Service&amp;quot; objects, each one with a different caching timeframe (i.e. a long caching for the content that hardly change, and a shorter caching for the content that changes often). In the portal out of the box, you cannot do that easily, and will probably have to recreate all the portlets and re-attach them to the same publisher content etc...(big pain).&lt;/p&gt;  &lt;p&gt;Well this portlet allows you to easily change the &amp;quot;portlet web service&amp;quot; OR the &amp;quot;portlet template&amp;quot; attached to a particular portlet or group of portlets:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Using the portal tree picker, pick the portlet you want to change. &lt;/li&gt;    &lt;li&gt;Using the portal tree picker, pick the web service OR portlet template that you want these portlet to be assigned to. &lt;/li&gt;    &lt;li&gt;Click Submit...Done. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Page Lister:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;This simple utility allows to display as a list of HTML links (simple &amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt; tags) all the Community Pages in the portal that a certain users have access to...&lt;/p&gt;  &lt;p&gt;Why doing this? it is a simple way of creating a Sitemap that a web &amp;quot;crawler&amp;quot; (either ALUI web crawler, or Google appliance etc...) could hit in order to be dynamically aware of all the ALUI pages of your site that are accessible to the guest users for example...Or that could also be used as a security monitoring tool in order to verify which pages are accessible to a particular user (i.e. Guest) and ensure it is not a security mistake etc...&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;ALUI Knowledge Directory Security Agent:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This utility, written in java (we have to think about our linux/unix user base too :) ), was created as a scheduled task agent in order to act as a security cop in the knowledge directory. What it does is go through all the KD folders the agent user has access to, and automatically assign the found cards with their parent folder security.&lt;/p&gt;  &lt;p&gt;All you need to provide are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;KD folder ID to start with, &lt;/li&gt;    &lt;li&gt;A user ID / password (or session token if you run as a portal &amp;quot;external operation&amp;quot;) the agent should impersonate with, &lt;/li&gt;    &lt;li&gt;(Optional) CrawlerIDs (if you want to change only the cards that were brought into KD by a specific set of crawlers)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;2 main use cases I see for this tool:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Use it as a &amp;quot;cop&amp;quot; background schedule job in order to ensure the security on the cards is always right, based on the security of the folder. &lt;/li&gt;    &lt;li&gt;In the event you use a single crawler with various filters that organize your content in various folders. Without this agent, the crawled cards will get the security defined in the crawler's &amp;quot;crawled content permission&amp;quot; section...and that might not be in phase with the security of the various KD folders the content will be organized into (due to filters). If you run this cop security agent after each crawl, then you are all set based on the destination folder, not on the crawler's &amp;quot;crawled content permission&amp;quot; section... &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That's it for now. I hope you'll test them out and let me know if you think these are useful or not.    &lt;br /&gt;Don’t hesitate to give ideas and/or wish lists of things which would be good to have in the portal...and don't hesitate to share the cool utilities you've done too&lt;/p&gt;  &lt;p&gt;I or others will be updating the project every so often so keep informed or you might miss out on some good resources :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-7424676639702084151?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9vBLYwAIX3o:urUQr1-612g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9vBLYwAIX3o:urUQr1-612g:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9vBLYwAIX3o:urUQr1-612g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=9vBLYwAIX3o:urUQr1-612g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/9vBLYwAIX3o/new-portal-tools-on-alui-toolbox.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2009/02/new-portal-tools-on-alui-toolbox.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-3410535260881867638</guid><pubDate>Sun, 18 Jan 2009 18:26:00 +0000</pubDate><atom:updated>2009-01-18T13:55:51.353-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Native API</category><category domain="http://www.blogger.com/atom/ns#">ALUI Search</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>WebCenter Native API Development: Advanced Search Query explained (and applied to WebSite Search)</title><description>&lt;p&gt;In his article about &amp;quot;Dot Com Portals: Smart Searching&amp;quot;, Jordan Rose already explained really well how to easily implement with Webcenter Interaction an efficient and accurate website-like search (enter a search term, and expect in the results either website pages, or documents within these pages).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;To summarize the challenge:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The very powerful WebCenter search component will index everything the user has access to (i.e. web content items, documents, crawled third party websites, etc…) independently from their real presence on the web site pages. For example, the search results would present web content items instead of the website pages where the web content item is displayed through a portlet.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;To summarize a bit the solution:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Using WebCenter interaction “web crawler” capability (google like spider that follows links on a page and index its content for future searches) coupled with experience definition features (to hide the part of the page that we don’t want the crawler to index, like the top/left navigation, the banner, etc…), it is easy to actually implement a website-like search with accurate portal page results (Refer to Jordan's blog post:&lt;a href="http://jordanportal.blogspot.com/2008/07/dot-com-portals-smart-searching.html"&gt;Dot Com Portals: Smart Searching&lt;/a&gt;) &lt;/p&gt;  &lt;p&gt;But one thing that was not there yet in the solution was: &amp;quot;How can the crawler navigate from page to page&amp;quot; if the navigation is not there? What we did at first (we did not have time to do better) is create &lt;strong&gt;manually&lt;/strong&gt; this HTML file that would contain all the pages of the website, and direct the web crawler to that page, instead of to the root of the public portal website url. &lt;/p&gt;  &lt;p&gt;This would work ok, but would require a manual update of this file each time you create a new page...not super practical. Anyway, I finally took the time to improve it, and created this &amp;quot;Page Listing&amp;quot; code that basically render a list of pages located within a specific folder...Basically, you simply create a request with &amp;quot;topfolderid&amp;quot;, &amp;quot;includesubfolders&amp;quot;, and &amp;quot;openerhost&amp;quot; (http://&lt;your application hostname&gt;/&lt;your application native&gt;/PageLinkListing?topfolderid=123&amp;amp;includesubfolders=true&amp;amp;openerhost=yourdomainhost) and the dotnet page will render all the portal page links that correspond to these values. &lt;/p&gt;  &lt;p&gt;In this article I'd like to use this example in order to focus on the Native Search API (refer to my previous article about the native API) because the dotnet frontend is pretty simple: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;DotNet front end page &lt;/li&gt;    &lt;li&gt;Native Portal API &lt;/li&gt;    &lt;li&gt;Webcenter search API to query the pages &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;First as always, it all starts with the native session creation…then, that’s when you can start creating the search request object:&lt;/p&gt;  &lt;p&gt;IPTSearchRequest req = m_ptSession.GetSearchRequest();&lt;/p&gt;  &lt;p&gt;From there, the PTSearchRequest object allows you to set all sorts of setting that will define the search you want to make. Simply call the SetSettings method. This method takes a setting ID and a value (that can be a string, int, or array of objects). The main problem is the non-documentation of this API (native API is non documented)…but luckily, the setting IDs are all available through the PT_SEARCH_SETTING class, and each name is relativelly straightforward (not always though). Check out the example below that sets the fields to return, specify not to execute best bet and spell check, and the maximum number of results to bring back:&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[] arPropIDs = { PT_INTRINSICS.PT_PROPERTY_OBJECTID, PT_INTRINSICS.PT_PROPERTY_OBJECTNAME, PT_INTRINSICS.PT_PROPERTY_OBJECTSUMMARY};&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_RET_PROPS, arPropIDs);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_INCLUDE_USUAL_FIELDS, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_KWIC, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_BESTBETS, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_SPELLCHECK, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_SKIPRESULTS, 0);&lt;/pre&gt;&lt;br /&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_MAXRESULTS, 10000);&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;You can also specify the admin folders (or KD folders) within which the search should be performed:&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_ADMINFOLDERS, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[] { adminfolderid });&lt;/pre&gt;&lt;br /&gt;  &lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;and the object type the search should be dealing with (here we want to search only community pages, but very similarly to the object type checkboxes in the advanced search interface, you could pick several object type to search for):&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; req.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_OBJTYPES, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;[] { PT_CLASSIDS.PT_PAGE_ID });&lt;/pre&gt;&lt;br /&gt;  &lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Finally, you can create all sorts of filters statements that you can add to this search request. It works very similarly to the snapshot query interface: A filter can contain several “Filter Clauses” and each clause can contain several “Filter Statements”. Clauses and Statements can be put together using “OR” or “AND” operations.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here for this exercise, we will look for objects with ID greater than 230 and name containing “Test”… (kind if useless query…but that’s not the point here…)&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// Create a filter for the search request which will &amp;quot;AND&amp;quot; together each filter clause.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; IPTFilter ptFilter = PortalObjectsFactory.CreateSearchFilter();&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; ptFilter.SetOperator(PT_BOOLOPS.PT_BOOLOP_AND);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Create the clause that will contains the statements we need for the query&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; IPTPropertyFilterClauses ptFilterClause = (IPTPropertyFilterClauses) ptFilter.GetNewFilterItem(PT_FILTER_ITEM_TYPES.PT_FILTER_ITEM_CLAUSES);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt;// The filter clause should &amp;quot;AND&amp;quot; each of the statements.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; ptFilterClause.SetOperator(PT_BOOLOPS.PT_BOOLOP_AND);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Statement 1: ObjectID &amp;gt; 230&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; IPTPropertyFilterStatement statement1 = (IPTPropertyFilterStatement)filter.GetNewFilterItem(PT_FILTER_ITEM_TYPES.PT_FILTER_ITEM_STATEMENT);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; statement1.SetOperand(PT_INTRINSICS.PT_PROPERTY_OBJECTID);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; statement1.SetOperator(PT_FILTEROPS.PT_FILTEROP_GT);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; statement1.SetValue(230);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Statement 2: Object Name contains the text &amp;quot;Test&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt; IPTPropertyFilterStatement statement2 = (IPTPropertyFilterStatement) ptFilter.GetNewFilterItem(PT_FILTER_ITEM_TYPES.PT_FILTER_ITEM_STATEMENT);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt; &lt;span style="color: #008000"&gt;//search on the name property.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt; statement2.SetOperator(PT_FILTEROPS.PT_FILTEROP_CONTAINS);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt; statement2.SetValue(&lt;span style="color: #006080"&gt;&amp;quot;Test&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt; &lt;span style="color: #008000"&gt;//add statements to clause&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt; ptFilterClause.AddItem(statement1, ptFilterClause.GetCount());&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt; ptFilterClause.AddItem(statement2, ptFilterClause.GetCount());&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt; &lt;span style="color: #008000"&gt;//add clause to filter&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt; ptFilter.SetPropertyFilter(ptFilterClause);&lt;/pre&gt;&lt;br /&gt;  &lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;As you can see it is very powerful and straightforward, and allows you to perform all sort of searches that fit your needs.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Finally, when you are done with the search parameters and filters, you simply need to execute the query, and get the results back…&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; IPTSearchQuery query = req.CreateAdvancedQuery(filter);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; IPTSearchResponse ptPagesResponse = req.Search(query);&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nResultCount = ptPagesResponse.GetResultsReturned(); &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nIndex = 0; nIndex &amp;lt; nResultCount; nIndex++) { &lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//do something with the data... &lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     ptPagesResponse.GetFieldsAsInt(nIndex, PT_INTRINSICS.PT_PROPERTY_OBJECTID));&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     ptPagesResponse.GetFieldsAsString(nIndex, PT_INTRINSICS.PT_PROPERTY_OBJECTNAME));&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     ptPagesResponse.GetFieldsAsString(nIndex, PT_INTRINSICS.PT_PROPERTY_OBJECTSUMMARY));&lt;/pre&gt;&lt;br /&gt;    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;br /&gt;  &lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Here it is, I hope you see the endless possibilities you now have using the native search API in your various Native API Utilities (Portlet, Console application, etc…). I will soon post on the ALUI Toolbox google project the integrality of this code plus many other extras. Stay tune, and Happy new year! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-3410535260881867638?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=imQ6AMJEx3Q:VS6soPKzkAU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=imQ6AMJEx3Q:VS6soPKzkAU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=imQ6AMJEx3Q:VS6soPKzkAU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=imQ6AMJEx3Q:VS6soPKzkAU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/imQ6AMJEx3Q/webcenter-native-api-development.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2009/01/webcenter-native-api-development.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-8000885487062422106</guid><pubDate>Sun, 16 Nov 2008 20:51:00 +0000</pubDate><atom:updated>2008-11-16T16:28:54.964-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">Best Practices</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">Native API</category><title>ALUI / WebCenter Interaction: Introduction to Native API development (Part 1)</title><description>&lt;p dtid="562949953421316"&gt;Most of the time, creating a remote portlet  application using the standard IDK is enough. Indeed, commonly, you just need to  access user profile information, portlet ID, page ID etc... or perform simple  operations exposed by the IDK PRC API.&lt;/p&gt;&lt;p dtid="562949953421317"&gt;But if you hit the limits of the IDK, it is  not the end of the road. In the ALUI/Webcenter development documentation, they  explain how to perform various UI customizations such as view replacement, PEI  development, Activity Spaces creation or extensions, etc... All these are  created within the portal application itself...Another option is to create what  I call a "Native API Portlet Application". As its name indicates, this portlet  application accesses directly the portal API and can perform virtually any  operation that the portal can do...very powerful (but non supported :) so make  sure your application is well written so that you can change the portal API  access layer easily if you upgrade the portal version for example)&lt;/p&gt;&lt;p dtid="562949953421318"&gt;&lt;strong dtid="562949953421319"&gt;&lt;u dtid="562949953421320"&gt;First, the 2 main requirements in order to  create a Native API application are:&lt;/u&gt;&lt;/strong&gt; &lt;/p&gt;&lt;ul dtid="562949953421321"&gt;&lt;li dtid="562949953421322"&gt;The  application needs to be on the same server as Portal, or Automation, or API  service &lt;/li&gt;&lt;li dtid="562949953421323"&gt;The application needs to  reference various portal DLLs (located in  &lt;portal_home&gt;/ptportal/6.1/bin/assemblies for dotnet, or  &lt;portal_home&gt;/ptportal/6.1/lib/java for java). You don’t need them all.  Here is the minimum list: &lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\opencache.dll  &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openconfig.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\opencounters.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openfoundation.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openhttp.dll  &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openkernel.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openkernelsearch.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openkernelsearchimpl.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openlog-framework.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openprocman.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\opensharedcache.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\opentempfile.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openusage.dll  &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openusage-api.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\openusage-impl.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\plumtreeserver.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\portal.dll  &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\pthome.dll &lt;br /&gt;&lt;br/&gt;ptportal\6.1MP1\bin\assemblies\ptportalobjects.dll &lt;/li&gt;&lt;/ul&gt;&lt;p dtid="562949953421344"&gt;&lt;/p&gt;&lt;p dtid="562949953421345"&gt;Important note: It is perfectly allowed to  also include the IDK Dlls here too... and I find it particularly recommended if  you are writing a native API portlet (for instance getting the current login  token for example is fairly easy using the IDK API)&lt;/p&gt;&lt;p dtid="562949953421346"&gt;&lt;strong dtid="562949953421347"&gt;&lt;u dtid="562949953421348"&gt;Second, you need to create the native session  (everything starts from here, really):&lt;/u&gt;&lt;/strong&gt; &lt;/p&gt;&lt;div dtid="562949953421349"&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421350"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421351"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421352"&gt;1:&lt;/span&gt; String strServerConfigDir = ConfigPathResolver.GetOpenConfigPath(); &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421353"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421354"&gt;2:&lt;/span&gt; IOKContext configContext = OKConfigFactory.createInstance(strServerConfigDir,&lt;span style="color: rgb(0, 96, 128);" dtid="562949953421355"&gt;"portal"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421356"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421357"&gt;3:&lt;/span&gt; PortalObjectsFactory.Init(configContext);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421358"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421359"&gt;4:&lt;/span&gt; IPTSession ptsession = PortalObjectsFactory.CreateSession();&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="csharpcode" dtid="562949953421361"&gt;From there you actually need to connect this  session with a particular user identity. That way, the session object will be  aware of your identity and especially the security and permission associated  with your identity. In other words, even if you are using the native API, you  cannot do more than you are allowed to. &lt;/div&gt;&lt;p dtid="562949953421362"&gt;To connect, 2 main options:&lt;/p&gt;&lt;ul dtid="562949953421363"&gt;&lt;li dtid="562949953421364"&gt;Use the  login token that you can simply get from the IDK API (that is prefered option if  you can) &lt;/li&gt;&lt;/ul&gt;&lt;div dtid="562949953421365"&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421366"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421367"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421368"&gt;1:&lt;/span&gt; String loginToken = m_portletRequest.GetLoginToken(); &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421369"&gt;//IDK call&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421370"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421371"&gt;2:&lt;/span&gt; ptsession.Reconnect(loginToken);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul dtid="562949953421372"&gt;&lt;li dtid="562949953421373"&gt;Use  explicit Username (or user ID) / Password to connect. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p dtid="562949953421375"&gt;&lt;/p&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421376"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421377"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421378"&gt;1:&lt;/span&gt; String username = &lt;span style="color: rgb(0, 96, 128);" dtid="562949953421379"&gt;"myusername"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421380"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421381"&gt;2:&lt;/span&gt; String pwd = &lt;span style="color: rgb(0, 96, 128);" dtid="562949953421382"&gt;"mypassword"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421383"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421384"&gt;3:&lt;/span&gt; ptsession.Connect(username, pwd, &lt;span style="color: rgb(0, 0, 255);" dtid="562949953421385"&gt;null&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;strong dtid="562949953421386"&gt;&lt;u dtid="562949953421387"&gt;&lt;/u&gt;&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;&lt;p dtid="562949953421388"&gt;&lt;strong dtid="562949953421389"&gt;&lt;u dtid="562949953421390"&gt;Third (and Final), you access the right  ObjectManager Class depending on which type of portal object you want to  interact with.&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p dtid="562949953421391"&gt;When the  session is created (that was pretty easy, right?), that is when you can actually  start interacting with the portal internals...and a majority of actions goes  through the PTObjectManager objects (IPTObjectManager interface). For  instance:&lt;/p&gt;&lt;p dtid="562949953421392"&gt;&lt;/p&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421393"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421394"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421395"&gt;1:&lt;/span&gt; IPTCommunityManager ptCommManager = ptSession.GetCommunities(); &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421396"&gt;//for community objects&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421397"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421398"&gt;2:&lt;/span&gt; IPTPageManager ptPageManager = ptSession.GetPages(); &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421399"&gt;//for community page objects&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421400"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421401"&gt;3:&lt;/span&gt; IPTObjectManager ptGadgetManager = ptSession.GetGadgets(); &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421402"&gt;//for portlet objects&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421403"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421404"&gt;4:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421405"&gt;//etc...&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p dtid="562949953421406"&gt;You noticed that for portlets, there is not a  IPTGadgetManager insterface....that’s ok as all the "Manager" interfaces are  children of the base IPTObjectManager interface.&lt;/p&gt;&lt;p dtid="562949953421407"&gt;Although the vast majority of manager objects  are accessible through a direct ptsession.Get() call, you can also get the right  manager using the generic call below (using the classID of the object type you  want)&lt;/p&gt;&lt;div dtid="562949953421408"&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421409"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421410"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421411"&gt;1:&lt;/span&gt; IPTObjectManager ptCrawlerManager = ptSession.GetObjectManagers(PT_CLASSIDS.PT_CRAWLER_ID); &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421412"  &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421413"&gt;2:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);" dtid="562949953421414"&gt;//using     the class id of the object type you want&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;From there, the freedom is yours... and  various operations will be available depending on the manager you called. One  call for instance that all managers have is the open object:&lt;/div&gt;&lt;div dtid="562949953421416"&gt;&lt;div style="border-style: none; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt; background-color: rgb(244, 244, 244);font-family:consolas,'Courier New',courier,monospace;font-size:8pt;" dtid="562949953421417"  &gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 100%; color: black; line-height: 12pt;font-family:consolas,'Courier New',courier,monospace;font-size:8pt;color:black;" dtid="562949953421418"   &gt;&lt;span style="color: rgb(96, 96, 96);" dtid="562949953421419"&gt;1:&lt;/span&gt; ptObjectManager.Open(objectid, lockObject);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p dtid="562949953421421"&gt;With  this call, you get directly access a particular object in the portal, and  interact with it as if you were in the UI&lt;/p&gt;&lt;p dtid="562949953421422"&gt;In the next article, I will show you how I  package these API call in a standalone library to minimize as much as possible  any API call within the presentation layer code...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-8000885487062422106?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mY8bZggzLII:gH6UfPOWYWE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mY8bZggzLII:gH6UfPOWYWE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mY8bZggzLII:gH6UfPOWYWE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=mY8bZggzLII:gH6UfPOWYWE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/mY8bZggzLII/webcenter-interaction-introduction-to.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/11/webcenter-interaction-introduction-to.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-5841341427490394519</guid><pubDate>Tue, 28 Oct 2008 03:02:00 +0000</pubDate><atom:updated>2008-10-29T22:26:30.309-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Customization</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Publisher - Part 3: No Redirect Bug Fix of Bug Fix :)</title><description>&lt;p&gt;I have been relatively lazy in regards of my blog lately, and I have plenty of articles that are stacking up...But in the meantime, I thought this one is pretty urgent.&lt;/p&gt;  &lt;p&gt;In one of my previous article, &lt;a href="http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html"&gt;ALUI Publisher - Part 2: Increase Performance by enabling REAL Caching - No Redirect Bug Fix&lt;/a&gt;, I was explaining how to fix the Publisher &lt;strong&gt;published_content_noredirect.jsp&lt;/strong&gt; (see&amp;#160; in that serie the benefits of using this instead of &lt;strong&gt;published_content_redirect.jsp&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;Well, I found out a small little bug on my part, and it is definitely worth fixing if you have not done so already. In my corrective code, I was trimming the content string from its end spaces (just to optimized the HTML output)...and I did not think of the likely negative effects, such as if the buffered content does finish on a meaningful space character (such as a sentence separator etc...)&lt;/p&gt;  &lt;p&gt;So the updated code with bug fix is: (specifically the trim that is removed)&lt;/p&gt;  &lt;pre&gt;//if there is content, forward to the requesting client&lt;br /&gt;int buffersize = 2000;&lt;br /&gt;int charread = 0;&lt;br /&gt;char[] content;&lt;br /&gt;&lt;br /&gt;//read until no byte is found in the input stream because request content length is no reliable&lt;br /&gt;// UTF-8 is necessary&lt;br /&gt;BufferedReader bisr = new BufferedReader(new InputStreamReader(conn.getInputStream(), &amp;quot;UTF-8&amp;quot;));&lt;br /&gt;&lt;br /&gt;do {&lt;br /&gt;               content = new char[buffersize];&lt;br /&gt;               charread = bisr.read(content);&lt;br /&gt;               out.write(new String(content)&lt;strike&gt;&lt;strong&gt;.trim()&lt;/strong&gt;&lt;/strike&gt;);&lt;br /&gt;} while(charread &amp;gt; -1);&lt;br /&gt;&lt;br /&gt;bisr.close();&lt;br /&gt;bisr = null;&lt;br /&gt;content = null;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Better to find it late than never! :)&lt;br/&gt;&lt;br /&gt;The code should be updated on the famous (yeah right...) &lt;a href="http://code.google.com/p/alui-toolbox/"&gt;ALUI Toolbox&lt;/a&gt; Google project (or should be soon)&lt;br/&gt;&lt;br /&gt;So Long.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-5841341427490394519?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ziONn7SFjoE:32EMpH7jYIM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ziONn7SFjoE:32EMpH7jYIM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ziONn7SFjoE:32EMpH7jYIM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=ziONn7SFjoE:32EMpH7jYIM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/ziONn7SFjoE/alui-publisher-part-3-no-redirect-bug.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/10/alui-publisher-part-3-no-redirect-bug.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-4256572165973648297</guid><pubDate>Mon, 29 Sep 2008 05:02:00 +0000</pubDate><atom:updated>2008-09-29T22:16:40.368-04:00</atom:updated><title>ALUI Enhancement: Get/Set All Preferences from Javascript</title><description>&lt;p&gt;As you probably already know, ALUI Portal personalization features are mostly guarantied by the possibility of setting/getting &amp;quot;preferences&amp;quot; with various scopes. Not to myself extend too much on this concept, you can refer to the ALUI Development Documentation (Link &lt;a target="_blank" title="ALUI dev doc" href="http://edocs.bea.com/alui/devdoc/docs60/Portlets/Basics/PlumtreeDevDoc_Integration_Portlets_Settings.htm"&gt;HERE&lt;/a&gt;) to have further explanations. While you read this documentation, you'll learn that preferences can be set and retrieved through: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the IDK API (most commonly), &lt;/li&gt;    &lt;li&gt;the server API (much less common since Server API should mostly be used only if the IDK cannot fulfill your needs), or &lt;/li&gt;    &lt;li&gt;the Javascript API (but only for preferences of scope &amp;quot;session&amp;quot;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;What is usually done consists in building a JAVA or Dotnet application that uses the IDK API to get/set preferences within a portlet, allowing for the presentation or behavior of the portlet to change based on the preference chosen.&lt;/p&gt;  &lt;p&gt;But as you build ALUI intranet or even Internet websites, you often realize that most of the portlets are either content-specific with some kind of personalization (i.e. a link showing only if this preference has been set for that user...), or have a pretty simple behavior and presentation.&lt;/p&gt;  &lt;p&gt;Would not that be cool to be able to use &amp;quot;Publisher&amp;quot; for example to build those simple portlets? In most cases, with the power of the ALUI Portal Adaptive Tags coupled with the Publisher PCS Tags (this could apply to any other Web Content Management Systems, but why not use Publisher as an example since it is still alive :) ), you could build such simple portlets without the need for programming a portlet in JAVA or Dotnet...&lt;/p&gt;  &lt;p&gt;But what about preferences? How could you set and get preferences, since they are available only through an API that can be used only using those programming languages? Well, ALUI has already thought it through, and integrated within their Javascript API the possibility to set/get &amp;quot;Session&amp;quot; preferences. That was great thinking indeed. But I kept (and still keep) asking myself: Why having developed this idea only half way through?? Why allowing to only set/get &amp;quot;&lt;strong&gt;&lt;em&gt;Session&lt;/em&gt;&lt;/strong&gt;&amp;quot; preferences through Javascript? All I know is that there is no reason why not...and I just wanted to share this essential feature.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Javascript Session preference: How does this work?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;So first, let's understand how the Javascript preference access works. Basically an activity space has been developed and its code is found in the following package: &lt;em&gt;com.plumtree.portalpages.browsing.sessionprefs.&lt;/em&gt; As the portal follows a strict MVC (Model View Controller) architecture, an activity space is mostly composed of a &amp;quot;Control&amp;quot; class (implementing IControl interface), a &amp;quot;Model&amp;quot; Class (implementing IModel interface) and a &amp;quot;Presentation&amp;quot; class (implenting IDisplayPage interface). You can refer to the &amp;quot;ALUI Portal Customization Package&amp;quot; to see the code of this sessionPrefs activity space. To request the activity space functionnality, simply create a HTTP request with the right parameters, like this:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs" href="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs&amp;amp;_preferencename="&gt;http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs&amp;amp;_preferencename=&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs" href="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=setprefs&amp;amp;_preferencename=preferencervalue"&gt;http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=setprefs&amp;amp;_preferencename=preferencervalue&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;From there, all there is to do is to allow that request to be called from Javascript, through an AJAX HTTPWebRequest...The javascript methods getSession() and SetSession() which initiate that AJAX HTTPWebRequest will use the PTPortalContext javascript object defined on every page to get the right ActivitySpace url as follows: &lt;/p&gt;  &lt;p&gt;PTPortalContext.GET_SESSION_PREFS_URL = '&lt;a href="http://localhost/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs';"&gt;http://localhost/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs';&lt;/a&gt;     &lt;br /&gt;PTPortalContext.SET_SESSION_PREFS_URL = '&lt;a href="http://localhost/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=setprefs';"&gt;http://localhost/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=setprefs';&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;...and that's it...Plumtree/BEA delivered your ALUI Javascript-Enabled &amp;quot;Session&amp;quot; Preference behavior.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Javascript preference of &amp;quot;All Type&amp;quot;: How does this work?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;All I did was extending on this principle in order to make all type of preferences available through Javascript, and as you understood now, through the behind-the-scene Preference Activity Space. Since I post the code on &amp;quot;&lt;strong&gt;ALUI Toolbox Google Project&lt;/strong&gt;&amp;quot;, I will pass on the very details of the code...&lt;/p&gt;  &lt;p&gt;The main outline is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Create a new Activity Space called &amp;quot;PortalPrefs&amp;quot; instead of SessionPrefs &lt;/li&gt;    &lt;li&gt;Update the PortalPrefControl class to take into account a new parameter &amp;quot;type&amp;quot; which allow user to specify the type of preference you want to get/set (possible values are: portlet, admin, session, user, community, communityportlet). &lt;/li&gt;    &lt;li&gt;Update the PortalPrefsModel class with the corresponding Preference Getter/Setter methods for each preference type (or scope) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Now, after installing this new code, the urls to access the AS are (differences in bold)&lt;/p&gt;  &lt;p&gt;&lt;a title="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs" href="http://your.host.domain.com/portal/server.pt?space=PortalPrefs&amp;amp;control=PortalPrefs&amp;amp;action=getprefs&amp;amp;type=PreferenceType&amp;amp;_preferencename="&gt;http://your.host.domain.com/portal/server.pt?space=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;control=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;action=getprefs&amp;amp;&lt;strong&gt;type=PreferenceType&lt;/strong&gt;&amp;amp;_preferencename=&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://your.host.domain.com/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs" href="http://your.host.domain.com/portal/server.pt?space=PortalPrefs&amp;amp;control=PortalPrefs&amp;amp;action=setprefs&amp;amp;type=PreferenceType&amp;amp;_preferencename=preferencervalue"&gt;http://your.host.domain.com/portal/server.pt?space=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;control=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;action=setprefs&amp;amp;&lt;strong&gt;type=PreferenceType&lt;/strong&gt;&amp;amp;_preferencename=preferencervalue&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Then you have the choice as far as Javascript is concerned: either you create your own layer that performs the call to this new activity space, or you plug this new bahavior into the already existing Javascript framework, without any modification to the framework itself.&lt;/p&gt;  &lt;p&gt;I personally chose the later, since I always try not to modify the portal existing libraries (just to allow for easier future upgrades of those libraries). All you have to do is to make sure to override on your portal page the PTPortalContext URL properties with the new AS URL end point BEFORE you call the already existing GetSession()/SetSession() javascript methods. To do that, you could simply create the following Facade JS methods to be called from your portlets:&lt;/p&gt;  &lt;p&gt;&amp;lt;Script&amp;gt;&lt;/p&gt;  &lt;p&gt;GetPortalPreference(prefType, prefname){&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;PTPortalContext.GET_SESSION_PREFS_URL = '&lt;a href="http://localhost/portal/server.pt?space=SessionPrefs&amp;amp;control=SessionPrefs&amp;amp;action=getprefs';"&gt;&lt;/a&gt;http://your.host.domain.com/portal/server.pt?space=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;control=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;action=getprefs&amp;amp;&lt;strong&gt;type=&lt;/strong&gt;' + prefType;&lt;/p&gt; &lt;/blockquote&gt; &lt;/a&gt;  &lt;blockquote&gt;   &lt;p&gt;GetSession(prefname); (this is the call to the already existing JS framework for session preference)      &lt;br /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;}&lt;/p&gt;  &lt;p&gt;SetPortalPreference(prefType, prefname, prefvalue){&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;PTPortalContext.SET_SESSION_PREFS_URL = '&lt;a href="http://your.host.domain.com/portal/server.pt?space=PortalPrefs&amp;amp;control=PortalPrefs&amp;amp;action=setprefs&amp;amp;type=PreferenceType'"&gt;http://your.host.domain.com/portal/server.pt?space=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;control=&lt;strong&gt;PortalPrefs&lt;/strong&gt;&amp;amp;action=setprefs&amp;amp;&lt;strong&gt;type=&lt;/strong&gt;&lt;/a&gt;' + prefType;&lt;/p&gt; &lt;/blockquote&gt; &lt;/a&gt;  &lt;blockquote&gt;   &lt;p&gt;SetSession(prefname); (this is the call to the already existing JS framework for session preference)&lt;/p&gt;    &lt;p&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;  &lt;p&gt;That's it! Feel free to browse the code (only JAVA version for now) at the &lt;a target="_blank" title="Alui Tool Box Google Code Project" href="http://code.google.com/p/alui-toolbox/source/browse/trunk/?r=4#trunk/ALUICommons/java/src/com/toolbox/alui/portalpages/browsing/portalprefs"&gt;Google Code Project&lt;/a&gt; I created (I also created for you the JAR that contains this code...that way, you can easily install and test this on your portal) and please let me know your thoughts! Hopefully, this will be integrated in the future releases of ALUI.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-4256572165973648297?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=fof4HH675IQ:Og77GhlW1sI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=fof4HH675IQ:Og77GhlW1sI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=fof4HH675IQ:Og77GhlW1sI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=fof4HH675IQ:Og77GhlW1sI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/fof4HH675IQ/alui-enhancement-getset-all-preferences.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/09/alui-enhancement-getset-all-preferences.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-4360534552918666029</guid><pubDate>Tue, 05 Aug 2008 02:28:00 +0000</pubDate><atom:updated>2008-08-04T22:44:34.008-04:00</atom:updated><title>ALUI Best Practice - Don't Hardcode ObjectIDs: Use UUIDs Instead</title><description>&lt;p&gt;In ALUI, there are 2 ways to identify uniquely an object: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ClassID (the type of object) + ObjectID (The ID of the object within the classID family) &lt;/li&gt;    &lt;li&gt;Global UUID (unique ID throughout the environment) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The ClassID/ObjectID combination is used throughout the Portal API to query/open/manage the ALUI objects, as well as navigate to communities and pages. The ALUI ADAPTIVE TAGS are no exception: you will notice that they require ObjectID / ClassID to perform their tasks, like for example the opener tag:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;lt;pt:standard.openerlink pt:objectid=&amp;quot;219&amp;quot; pt:classid=&amp;quot;514&amp;quot; pt:mode=&amp;quot;2&amp;quot; target=&amp;quot;myWindow&amp;quot;&amp;gt;view community page&amp;lt;/pt:standard.openerlink&amp;gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The main problem is not in the fact the ObjectID / ClassID is a bad way to identify an object, but in the fact that the &lt;strong&gt;&lt;em&gt;&lt;u&gt;ObjectID WILL NOT NECESSARILY (very improbable actually) be the same when you migrate objects from one environment to another&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;. And that's where it can hurt...&lt;/p&gt;  &lt;p&gt;Indeed good practice is to test out your creation in DEV / TEST / STAGING etc... and then migrate it using the ALUI migration tool. Since objectIDs will be different after migration in the new environment, all the objectIDs used in Adaptive Tags will have to be changed...hassle indeed.&lt;/p&gt;  &lt;p&gt;Fortunately, &lt;u&gt;&lt;strong&gt;&lt;em&gt;UUID does NOT change with migration (or very improbable)&lt;/em&gt;&lt;/strong&gt;&lt;/u&gt; from environments to environments. So that would seem a good option if you need to hardcode IDs, especially in Adaptive Tags, and I'd recommend that option everywhere you can.&lt;/p&gt;  &lt;p&gt;In order to make it possible, I built a Adaptive Tags that does just this: Transform a UUID into its corresponding ClassID/ObjectID pair. All you need to do is use that Adaptive Tag before using the opener link tag for example. The object and class IDs are stored in shared memory (adaptive tag framework) with the specified scope and can be reused with any other tags that require objectID / ClassID.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;lt;pt:taglibname.convertuuidtoid pt:uuid=&amp;quot;{UUID}&amp;quot; pt:objectid=&amp;quot;objectIDKey1&amp;quot; pt:classid=&amp;quot;classIDKey1&amp;quot; pt:scope=&amp;quot;portlet request&amp;quot; /&amp;gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;lt;pt:standard.openerlink pt:objectid=&amp;quot;$objectIDKey1&amp;quot; pt:classid=&amp;quot;$classIDKey1&amp;quot; pt:mode=&amp;quot;2&amp;quot; target=&amp;quot;myWindow&amp;quot;&amp;gt;view community page&amp;lt;/pt:standard.openerlink&amp;gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;What's even better is that you can use this tag even for your remote portlet applications, like any other tags. &lt;/p&gt;  &lt;p&gt;The code to change a UUID to the ObjectID / ClassID pair is fairly simple. Just get the Migration manager and call the convert method UUIDToObjectID to get the job done. I created a helper method that package it altogether:&lt;/p&gt;  &lt;div&gt;   &lt;p&gt;public Object[] getClassObjectID(String uuid){     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Object[] oClassIDObjectID = null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (null != uuid) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IPTMigrationManager oPTMigrationMgr = (IPTMigrationManager) oPTSession      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .OpenGlobalObject(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PT_GLOBALOBJECTS.PT_GLOBAL_MIGRATION_MANAGER,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; false);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; oClassIDObjectID = oPTMigrationMgr.UUIDToObjectID(uuid);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } catch (Exception exc) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; oClassIDObjectID = null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return oClassIDObjectID;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;The first item in the returned array is the ClassID (oClassIDObjectID[0]), the second item is the object ID (oClassIDObjectID[1]).&lt;/p&gt;  &lt;p&gt;You can download the code on my newly created subversion project (&lt;a title="http://alui-toolbox.googlecode.com" href="http://alui-toolbox.googlecode.com"&gt;http://alui-toolbox.googlecode.com&lt;/a&gt;) on Google code (I'll be updating/maintaining this as I see fit - feel free to suggest at will :)):&lt;/p&gt;  &lt;p&gt;&lt;tt&gt;svn checkout &lt;strong&gt;&lt;em&gt;http&lt;/em&gt;&lt;/strong&gt;://alui-toolbox.googlecode.com/svn/trunk/ alui-toolbox-read-only&lt;/tt&gt;&lt;/p&gt;  &lt;p&gt;No more mocking around with IDs during migration :)&lt;/p&gt;  &lt;p&gt;Hope that helps!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-4360534552918666029?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=GrsFN2PJNBY:LDB8qTBS8to:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=GrsFN2PJNBY:LDB8qTBS8to:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=GrsFN2PJNBY:LDB8qTBS8to:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=GrsFN2PJNBY:LDB8qTBS8to:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/GrsFN2PJNBY/alui-best-practice-don-hardcode.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/08/alui-best-practice-don-hardcode.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-5174169736325534073</guid><pubDate>Thu, 24 Jul 2008 03:07:00 +0000</pubDate><atom:updated>2008-07-23T23:07:39.332-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ALUI Component</category><category domain="http://www.blogger.com/atom/ns#">Bug</category><category domain="http://www.blogger.com/atom/ns#">Architecture</category><category domain="http://www.blogger.com/atom/ns#">Portal Maintenance</category><title>Inside ALUI Grid Search: Redundancy Bug (6.1 on window at least)</title><description>&lt;p&gt;With ALUI 6.1, BEA introduced a completely revamped search component for ALUI, allowing for better redundancy and better throughput: Grid Search. The main advantages of that new search component are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Multiple search nodes to provide redundancy for serving search requests. &lt;/li&gt;    &lt;li&gt;Search index can be split in multiple partitions, each attached to various search nodes., to increase throughput. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Every nodes on the same partition automatically replicate locally their search index to guaranty redundancy and performance.&lt;/p&gt;  &lt;p&gt;Although there is capability for multiple nodes that guaranty redundancy, all the nodes need to access a central &amp;quot;cluster&amp;quot; data repository located somewhere on the network (through file share). It is located by default at &amp;lt;ALUI_HOME&amp;gt;/ptsearchserver/6.1/cluster. What is usually done is to share that folder (simple network share if you are on windows) and set up the other nodes to access that share as their cluster repository. This cluster repository holds the cluster information (nodes and partitions info) and the multiple search checkpoints that allow for search index backup.&lt;/p&gt;  &lt;p&gt;One main problem that I personally experienced with that design consists in the fact that this cluster repository represent a single point of failure... if the cluster share is suddenly not available (hard disk, server, or network failure), all the nodes are not able to talk to the cluster and there might be problems happening.&lt;/p&gt;  &lt;p&gt;And actually, a huge problem occurs in that case: if the cluster share is not available, all the nodes are suddenly experiencing an &amp;quot;Out Of Memory&amp;quot; exception and shutting down abruptly. Thus, although you deployed multiple nodes and partitions, if the cluster share is down, your search architecture is...down.&lt;/p&gt;  &lt;p&gt;It is pretty easy to test (at least I successfully reproduced the bug on ALUI 6.1 MP1 Patch 1 on windows server 2003): have your nodes all running, and simply remove the share from your cluster folder...all your nodes will go down (apart from the one that accesses the share locally if the cluster share is installed on the same server as one of the nodes)&lt;/p&gt;  &lt;p&gt;2 options from there: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;make sure the share is never down (windows clustering, redundant NAS cluster, or polyserve technologies) &lt;/li&gt;    &lt;li&gt;install that critical fix from BEA that fixes this bug &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you don't have an infrastructure that provides the first expensive option, you might want to look seriously into the 2nd one...and contact your sales rep asap. Basically, the critical fix allow for the nodes to continue serving requests even if the cluster share is no longer available. All the nodes switch automatically in read only mode without the &amp;quot;out of memory&amp;quot; exception that was occurring before. &lt;/p&gt;  &lt;p&gt;Although it is much better, some problems are still present with that critical fix. When in read-only mode, the nodes are no longer indexing new content...your search index is then blocked at the point in time when the cluster share did actually go down, and any new object or document will not show up in the search as long as the cluster share is not restored. The second problem is that the nodes will NOT automatically roll back to read/write mode whenever the cluster is available again. It will require a manual restart.&lt;/p&gt;  &lt;p&gt;But compared to a total shut down of search, these problems seem less important indeed!&lt;/p&gt;  &lt;p&gt;I am not 100% sure this fix has been pushed to ALUI 6.5 but I sure hope so. And by fix, I am talking about a total fix including auto rollback to &amp;quot;normal&amp;quot; mode when share is available anew, or even allowing for TOTAL continuity of service when this share goes down...&lt;/p&gt;  &lt;p&gt;Please let me know (leave comment) if you have that information on 6.5, or if you reproduce this with other versions of the portal.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-5174169736325534073?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=BCA0Y7jvdVc:9_lKGKfiwCA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=BCA0Y7jvdVc:9_lKGKfiwCA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=BCA0Y7jvdVc:9_lKGKfiwCA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=BCA0Y7jvdVc:9_lKGKfiwCA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/BCA0Y7jvdVc/inside-alui-grid-search-redundancy-bug.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/07/inside-alui-grid-search-redundancy-bug.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-8385398420951884089</guid><pubDate>Wed, 16 Jul 2008 03:06:00 +0000</pubDate><atom:updated>2008-07-15T23:22:51.535-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Database Script</category><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">MS SQL Server</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">Portal Maintenance</category><title>ALUI Tool: URL (or text) Migration within Publisher Items</title><description>&lt;p&gt;Following my previous article &amp;quot;&lt;a title="ALUI Administration Tool for Environment Refresh: String Replacing for URLS" href="http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html"&gt;ALUI Administration Tool for Environment Refresh: String Replacing for URLS&lt;/a&gt;&amp;quot; talking about migration between environments, here is an extra piece that you might find very useful (I surely use it all the time)&lt;/p&gt;  &lt;p&gt;Basically, as explained in the previous article, it is common to have different DNS aliases set up per environment...I.e for publisher remote server, you could have:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://publisher.domain.com"&gt;http://publisher.domain.com&lt;/a&gt; for production&lt;/li&gt;    &lt;li&gt;&lt;a href="http://publisher-stg.domain.com"&gt;http://publisher-stg.domain.com&lt;/a&gt; for staging&lt;/li&gt;    &lt;li&gt;&lt;a href="http://publisher-dev.domain.com"&gt;http://publisher-dev.domain.com&lt;/a&gt; for development&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Similarly, the publish browsing URL is not an exception to this rule:&lt;/p&gt;  &lt;li&gt;&lt;a href="http://publisher-content.domain.com/publish"&gt;http://publisher-content.domain.com/publish&lt;/a&gt;&amp;#160; for production&lt;/li&gt;  &lt;li&gt;&lt;a href="http://publisher-content-stg.domain.com/publish"&gt;http://publisher-content-stg.domain.com/publish&lt;/a&gt; for staging&lt;/li&gt;  &lt;li&gt;&lt;a href="http://publisher-content-dev.domain.com/publish"&gt;http://publisher-content-dev.domain.com/publish&lt;/a&gt; for development&lt;/li&gt;  &lt;p&gt;When you add an image or a link in the free text editor of content items in publisher, it will most of the time create an absolute URL to that resource...thus you can imagine that there will be a lot of DNS aliases within a lot of publisher items throughout the environment.&lt;/p&gt;  &lt;p&gt;What happen when you migrate the publisher DB from one environment to another? Well you will have a lot of DEV dns aliases within your Staging environment (in case of a DEV promotion to Stage); or a lot of production DNS aliases within your dev environment in the case of a production refresh to DEV.&lt;/p&gt;  &lt;p&gt;In my previous article &amp;quot;&lt;a title="ALUI Administration Tool for Environment Refresh: String Replacing for URLS" href="http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html"&gt;ALUI Administration Tool for Environment Refresh: String Replacing for URLS&lt;/a&gt;&amp;quot;, I was mostly talking about migrating URL within portal objects, but nothing really about migrating urls within publisher items.&lt;/p&gt;  &lt;p&gt;Thus, I created some DB scripts (SQL Server only for now) that do just that...&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;&lt;em&gt;puburls-PTCSDIRECTORY-nvarchar-replace.sql&lt;/em&gt;&lt;/strong&gt;: Script to change a particular string within the PUBLISHEDTRANSFERURL and PUBLISHEDURL columns (which is mapped out in the DB to a column of type VARCHAR)&lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;puburls-PTCSVALUE-ntext-replace.sql&lt;/strong&gt;&lt;/em&gt; and &lt;strong&gt;&lt;em&gt;puburls-PTCSVALUEA-ntext-replace.sql&lt;/em&gt;&lt;/strong&gt;: Scripts to change a particular string within the &amp;quot;long text&amp;quot; property of a publisher item (which is mapped out in the DB to a column of type TEXT)&lt;/li&gt;    &lt;ol&gt;     &lt;li&gt;PCSVALUES.LONGVALUE (hosting the long text of the currently published item)&lt;/li&gt;      &lt;li&gt;PCSVALUESA.LONGVALUE (hosting the long text values of all the previous versions of the item)&lt;/li&gt;   &lt;/ol&gt; &lt;/ol&gt;  &lt;p&gt;For the first script, PUBLISHEDTRANSFERURL and PUBLISHEDURL columns are of type VARCHAR and thus it is easy to replace a string within those columns using the REPLACE MS SQL Function. Thus, a simple SQL statement is good here.&lt;/p&gt;  &lt;p&gt;The main challenge was really with the 2nd scripts...indeed, within a column of type TEXT, the SQL &amp;quot;REPLACE&amp;quot; function cannot be used...The workaround is to use the PATINDEX and UPDATETEXT functions within a &lt;b&gt;Transact-SQL&lt;/b&gt; (&lt;b&gt;T-SQL&lt;/b&gt;) script. To give the credit to to the right person, I adapted a script that I found at &lt;a title="ASP FAQ - How do I handle REPLACE() within an NTEXT column in SQL Server?" href="http://sqlserver2000.databases.aspfaq.com/how-do-i-handle-replace-within-an-ntext-column-in-sql-server.html"&gt;ASP FAQ - How do I handle REPLACE() within an NTEXT column in SQL Server?&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;DISCLAIMER: ALTHOUGH I PERSONNALY USE THIS SCRIPT ALL THE TIME, THERE IS NO GUARANTY; SO USE THIS TOOL AT YOUR OWN RISK blah blah blah AND USE IT ONLY IF YOU ARE PROFFICIENT ENOUGH WITH ALUI PORTAL TECHNOLOGIES.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Attached is the zip file package that contains the 3 scripts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="puburls-PTCSDIRECTORY-nvarchar-replace.sql" href="http://fabiensanglier.googlepages.com/puburls-PTCSDIRECTORY-nvarchar-repla.sql"&gt;puburls-PTCSDIRECTORY-nvarchar-replace.sql&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a title="puburls-PTCSVALUE-ntext-replace.sql" href="http://fabiensanglier.googlepages.com/puburls-PTCSVALUE-ntext-replace.sql"&gt;puburls-PTCSVALUE-ntext-replace.sql&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a title="puburls-PTCSVALUEA-ntext-replace.sql" href="http://fabiensanglier.googlepages.com/puburls-PTCSVALUEA-ntext-replace.sql"&gt;puburls-PTCSVALUEA-ntext-replace.sql&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Don't forget to change the string to look for, and the string to replace it with&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;puburls-PTCSDIRECTORY-nvarchar-replace.sql&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;UPDATE&lt;/span&gt; [dbo].[PCSDIRECTORY]&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; &lt;br /&gt;[PUBLISHEDTRANSFERURL]=REPLACE([PUBLISHEDTRANSFERURL],&lt;span class="str"&gt;'-DEV.DOMAIN.COM'&lt;/span&gt;,&lt;span class="str"&gt;'-TST.DOMAIN.COM'&lt;/span&gt;), &lt;br /&gt;[PUBLISHEDURL]=REPLACE([PUBLISHEDURL],&lt;span class="str"&gt;'-DEV.DOMAIN.COM'&lt;/span&gt;,&lt;span class="str"&gt;'-TST.DOMAIN.COM'&lt;/span&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; &lt;br /&gt;publishedtransferurl &lt;span class="kwrd"&gt;like&lt;/span&gt; &lt;span class="str"&gt;'%-DEV.DOMAIN.COM%'&lt;/span&gt; &lt;br /&gt;&lt;span class="kwrd"&gt;or&lt;/span&gt; publishedurl &lt;span class="kwrd"&gt;like&lt;/span&gt; &lt;span class="str"&gt;'%-DEV.DOMAIN.COM%'&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;puburls-PTCSVALUE-ntext-replace.sql&lt;/strong&gt;&lt;/em&gt; and &lt;strong&gt;&lt;em&gt;puburls-PTCSVALUEA-ntext-replace.sql&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @oldString = N&lt;span class="str"&gt;'por-pubcontent-dev.domain.com'&lt;/span&gt;; &lt;span class="rem"&gt;-- remove N &lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @newString = N&lt;span class="str"&gt;'por-pubcontent-tst.domain.com'&lt;/span&gt;; -- remove N &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That's it! Let me know if you find it as useful as I do! Enjoy!!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-8385398420951884089?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=xbqEAe6GiJw:awlg4LWQDkA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=xbqEAe6GiJw:awlg4LWQDkA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=xbqEAe6GiJw:awlg4LWQDkA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=xbqEAe6GiJw:awlg4LWQDkA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/xbqEAe6GiJw/alui-tool-url-migration-within.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/07/alui-tool-url-migration-within.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-951880193050598547</guid><pubDate>Mon, 30 Jun 2008 18:59:00 +0000</pubDate><atom:updated>2009-03-12T16:15:46.043-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ALUI Component</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Publisher - Part 2: Increase Performance by enabling REAL Caching - No Redirect Bug Fix</title><description>&lt;p&gt;Previously (&lt;a title="http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase.html" href="http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase.html"&gt;http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase.html&lt;/a&gt;) , I've been talking (and proving I hope) that using a "no redirect" mechanism for serving published content from publisher is the best option to enable portal caching. Publisher 6.4 offers already such a possibility (although not publicized a lot): using in the portal Published Content Web Service object &lt;strong&gt;published_content_noredirect.jsp&lt;/strong&gt; instead of the standard &lt;strong&gt;published_content_redirect.jsp.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Unfortunately, if you start using this, you are going to start seeing a weird behavior: the publish content is getting truncated in some special cases...and this is due to the way the JSP has been coded. Several options for you: either you wait for a Critical fix to be issued to you by BEA (i am not aware of one yet), or you upgrade to ALUI 6.5 (I hear that this has been fixed in 6.5...have not verified though), or you simply do it yourself, as this is a simple fix to implement (ultimately, that might be the same type of code that would be issued by a CF I imagine)&lt;/p&gt;  &lt;p&gt;By looking at the JSP within the publisher web application archive (ptcs.war - explode the war using jar command), we can see what's wrong and why the content is truncated in some case:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;HttpURLConnection conn = (HttpURLConnection)url.openConnection();&lt;br /&gt;                  &lt;br /&gt;&lt;span class="rem"&gt;// make the request&lt;/span&gt;&lt;br /&gt;conn.connect();&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;//read the content length&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; contentLength = conn.getContentLength();&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;//if there is content, forward to the requesting client&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;( contentLength &amp;gt; 0 ){&lt;br /&gt;  &lt;span class="rem"&gt;// UTF-8 is necessary&lt;/span&gt;&lt;br /&gt;  InputStreamReader isr = &lt;span class="kwrd"&gt;new&lt;/span&gt; InputStreamReader(conn.getInputStream(), &lt;span class="str"&gt;"UTF-8"&lt;/span&gt;);&lt;br /&gt;  &lt;span class="kwrd"&gt;char&lt;/span&gt;[] content = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;[contentLength];&lt;br /&gt;  isr.read(content);&lt;br /&gt;  isr.close();&lt;br /&gt;  &lt;span class="kwrd"&gt;out&lt;/span&gt;.write(content);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;As you can see, an HTTP GET request is made, and the content length of the response is gotten from the "getContentLength()" method. This call is going to get the content length number fro mthe response header rather than actually count all the bytes that are contained in the response content. Thus, since the code base itself on this number to output the content to the JSP output stream (see above: char array of length equal to contentlength), the content will indeed be truncated if the contentlength number is not correct...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A simple correction (and more robust code) is actually to make sure ALL the content is pushed to the output stream, independently from the contentlength number returned by the response header. Here is my code below that fixes that issue, and also increase performance by using the preferred BufferedReader wrapper class instead of the bare InputStreamReader:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;------EDITED 3/12/2009--------&lt;br /&gt;BufferedReader bisr = null;&lt;br /&gt;            try {&lt;br /&gt;                bisr = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));&lt;br /&gt;                String line;&lt;br /&gt;                while ( (line = bisr.readLine( ) ) != null ) {&lt;br /&gt;                    out.println(line);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            catch(Exception exc){&lt;br /&gt;                throw exc; //to be caught by the global try catch&lt;br /&gt;            } finally {&lt;br /&gt;                if(bisr != null)&lt;br /&gt;                    bisr.close();&lt;br /&gt;                bisr = null;&lt;br /&gt;            }&lt;br /&gt;            return;&lt;br /&gt;------END EDITED 3/12/2009--------&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Basically, the code will read by chunks of 2000 chars (this is a chunk size that I think is appropriate) the entirety of the content until the last character...and write it all to the output stream...This does not rely on the contentlength at all, and thus is more reliable and robust.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;After changing the &lt;strong&gt;published_content_noredirect.jsp&lt;/strong&gt; as above, you can repackage the ptcs.war with the new corrected JSP (within the root of the previously extracted ptcs.war folder, run &lt;strong&gt;&lt;em&gt;jar -cvf ptcs.war *&lt;/em&gt;&lt;/strong&gt; command) and redeploy to ALL redirector and publisher instances...&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Voila, you have your perfect solution for ALUI 6.1 and Publisher 6.4 (and previous versions too).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-951880193050598547?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ZQqy7zh6XQk:TAJn8WPtkdk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ZQqy7zh6XQk:TAJn8WPtkdk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=ZQqy7zh6XQk:TAJn8WPtkdk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=ZQqy7zh6XQk:TAJn8WPtkdk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/ZQqy7zh6XQk/alui-publisher-part-2-increase_30.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-5192948945770238116</guid><pubDate>Mon, 30 Jun 2008 17:21:00 +0000</pubDate><atom:updated>2008-06-30T15:02:07.872-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Best Practices</category><category domain="http://www.blogger.com/atom/ns#">ALUI Component</category><category domain="http://www.blogger.com/atom/ns#">Architecture</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Publisher - Part 2: Increase Performance by enabling REAL Caching</title><description>&lt;p&gt;In my previous post &lt;a title="http://fsanglier.blogspot.com/2008/02/alui-publisher-increase-performance.html" href="http://fsanglier.blogspot.com/2008/02/alui-publisher-increase-performance.html"&gt;http://fsanglier.blogspot.com/2008/02/alui-publisher-increase-performance.html&lt;/a&gt;(man, already couple of month ago...I know I've been sucked into a black hole since then :) ) I was talking about how to best design a scalable and redundant ALUI Publisher architecture. But what I had not pushed enough in the last article was &lt;strong&gt;performance&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;In my opinion, the Publisher standard behavior for serving content has some performance flaw (at least in ALUI 6.1 - Publisher 6.4) related to caching... Since there are ways around this (that's what we do, right?), I think you might benefit from this a lot, and in my last implementation, the change explained below increased performance under load to complete new levels (in the meantime reducing DB requests and DB and publisher redirector CPU utilization)...So here it goes...&lt;/p&gt;  &lt;p&gt;As I explained in previous post, each published content portlet within a portal page are going to make a request to the Publish Content Redirector component, and particularly the JSP page in charge of performing the redirect: &lt;strong&gt;published_content_redirect.jsp&lt;/strong&gt; (you can see that defined in the Published Content portal web service object). As the name says, this Java Server Page (JSP) performs a &lt;strong&gt;302 redirect&lt;/strong&gt; to the published content item (as seen in previous post, this location should be served by your favorite web server, apache or IIS for example...). But BEFORE making this redirect, it must know where to redirect to... so for that, the code makes a DB request to the publisher Database in order to get the browsing path to the published content item (passing the publisher content item ID that was saved when you created your published content portlet earlier). &lt;/p&gt;  &lt;p&gt;&lt;u&gt;Ok so here is the first flaw I was taking about in previous paragraph&lt;/u&gt;: To be able to see some content through the publisher portlets within the portal page, you can see from the above explanation that multiple calls to the publisher DB will be made. Let's say we have 5 publisher portlets on the page (not uncommon), for each page rendering for 1 user, 5 DB calls will be made to the publisher DB (in addition of multiple other DB calls for portal and analytics). If we are now talking about thousands of users, we are talking about too many DB calls to simply see some content that does not change often. This has an unnecessary impact on DB load of your infrastructure, and will increase the page load consequently since DB calls are inherently slower that simple content rendering...&lt;/p&gt;  &lt;p&gt;While reading, some of view are already thinking for a good reason: &lt;strong&gt;CACHING&lt;/strong&gt;! Yeah, indeed, caching is the secret to scaling and performance (not always necessary to take out the big bucks and supercharge even more the DB infrastructure). And great for us, the portal offers a great out-of-the-box caching capability within the web service object: simply set the minimum caching to 2 hours, max to 20 days, and normally, you would think that the portal should simply cache the published content for that amount of time...removing the need to call the &lt;strong&gt;published_content_redirect.jsp&lt;/strong&gt; altogether, and thus the need to make a DB call!! ...but it does not happen this way. You don't believe me? Enable access logging on publish content redirector components (un-comment &amp;quot;Access logger&amp;quot; section within &amp;lt;ALUI HOME&amp;gt;\ptcs\6.4\container\deploy\jbossweb-tomcat50.sar\server.xml) and you will clearly see that even though your page contains only published content portlets that should be cached, the &lt;strong&gt;published_content_redirect.jsp&lt;/strong&gt;&amp;#160; is still constantly called...and thus caching is not really....caching. &lt;/p&gt;  &lt;p&gt;&lt;u&gt;Why does this happen?&lt;/u&gt; It is because of the redirect mechanism for serving content...From &lt;a href="http://www.w3.org"&gt;www.w3.org&lt;/a&gt;, 302 is explained this way: &amp;quot;&lt;em&gt;The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field.&lt;/em&gt;&amp;quot; Thus, the portal is doing is job perfectly (it acts as a client here) and will never cache a response with a temporary redirect 302 status code.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Ok so what can make it better?&lt;/u&gt; Changing the redirect mechanism to something that does not redirect...Well, using this other JSP actually already present and developed within ALUI 6.4 (I have not verified if present in earlier versions of publisher): &lt;strong&gt;published_content_noredirect.jsp. &lt;/strong&gt;Instead of issuing a redirect to the published content, this jsp performs an HTTPGetRequest to it and write its content to the JSP output stream. The response code is now a simple 200 OK (&amp;quot;&lt;em&gt;The request has succeeded&lt;/em&gt;&amp;quot; - &lt;a href="http://www.w3.org"&gt;www.w3.org&lt;/a&gt;) that can be cached by the portal. To enable this, simply change the HTTP url of the Published Content Web Service Object to be &lt;strong&gt;published_content_noredirect.jsp&lt;/strong&gt; instead of &lt;strong&gt;published_content_redirect.jsp&lt;/strong&gt;. Of course, check out the publisher redirector access logs to see the dramatic difference...under load, you will initially see a bunch of requests to &lt;strong&gt;published_content_noredirect.jsp,&lt;/strong&gt; but very very fast, the access log becomes silent, all the content being really cached by portal...&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Result??&lt;/u&gt; You can increase the load even more, and the page response satys the same (or is even better), and the DB utilization is not altered by that load...you simply have a site that is so much more performant. Our initial results showed that under constant intensive load (with and without the change) the publisher infrastructure would not crash anymore, the CPU usage of both DB and publisher redirectors would be consequently diminished, the number of DB requests would drop, and the load could actually be increased to new levels without loss of performance and functionality, thanks to caching.&lt;/p&gt;  &lt;p&gt;Since this post is already long, I am going to stop here for now...Please read next post (&lt;a title="http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html" href="http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html"&gt;http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html&lt;/a&gt;) to understand the second flaw: the &lt;strong&gt;published_content_noredirect.jsp&lt;/strong&gt; has a truncation bug...that is fixable of course :)&lt;/p&gt;  &lt;p&gt;So long!&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9c192868-c372-464a-937b-c3180db0cabb" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Aqualogic" rel="tag"&gt;Aqualogic&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ALUI" rel="tag"&gt;ALUI&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Publisher" rel="tag"&gt;Publisher&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Web%20CMS" rel="tag"&gt;Web CMS&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ALUI%20Architecture" rel="tag"&gt;ALUI Architecture&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-5192948945770238116?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=1LMfvi67XHQ:m5D22GcXGvw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=1LMfvi67XHQ:m5D22GcXGvw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=1LMfvi67XHQ:m5D22GcXGvw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=1LMfvi67XHQ:m5D22GcXGvw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/1LMfvi67XHQ/alui-publisher-part-2-increase.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-8427902675669436070</guid><pubDate>Wed, 27 Feb 2008 01:00:00 +0000</pubDate><atom:updated>2008-07-29T20:18:04.504-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Best Practices</category><category domain="http://www.blogger.com/atom/ns#">ALUI Component</category><category domain="http://www.blogger.com/atom/ns#">Architecture</category><category domain="http://www.blogger.com/atom/ns#">ALUI Publisher</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Publisher: Increase Performance, Scalability and Availability</title><description>&lt;p&gt;ALUI publisher is the component that provides out of the box Web Content Management for the ALUI portal. Depending on the nature of your portal, Publisher can be an important or even critical part of your portal infrastructure (ALUI-powered Internet sites for example, or intranet with a lot of static content displayed through portlets).&lt;/p&gt;  &lt;p&gt;So if this component is really critical, the architecture design for that component must provide performance, scalability and redundancy. This article is meant to show you how to design Publisher Architecture to maximize performance, scalability and redundancy, and ultimately provide the best experience to the end user.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Published Content portlets - How it works&lt;/u&gt;&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;First, let's lay out all the key components and understand the request flow &lt;strong&gt;for each Publish Content Portlet&lt;/strong&gt; on a single portal page:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; &lt;a href="http://lh5.ggpht.com/fabiensanglier/SI-zN4dyIfI/AAAAAAAAACI/zb5UEOUdxyI/s1600-h/PubContentRequestFlow_thumb_1%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="278" alt="PubContentRequestFlow_thumb_1" src="http://lh5.ggpht.com/fabiensanglier/SI-zOyACYLI/AAAAAAAAACM/jKTHiSwXYdM/PubContentRequestFlow_thumb_1_thumb%5B1%5D.jpg?imgmax=800" width="506" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It is important to reiterate that this flow is not per portal page, but per portlet. In other words, a portal page with 4 published content portlets will initiate 4 simultaneous request flows like the one above. From that, you can understand that depending on the load of these portal pages, the number of requests to the redirector and the publish content services could easily skyrocket, which is a strong proponent of clustering these components.&lt;/p&gt;  &lt;p&gt;The redirector, as its name states, will simply redirect the request to the right content url, based on the content ID that is given. Since this component actually makes more intensive DB calls and is accessed for every pub content requests (when content is not cached by the portlet of course), we definitely would want to cluster it and allow for future addition to that cluster when the load increase.&lt;/p&gt;  &lt;p&gt;The published content piece is a very simple &amp;quot;static web content serving solution&amp;quot;. Although JBOSS or any other application servers are able to serve static content, none are as performant as true web servers optimized for the task: Amongst others, Apache or IIS are good possibilities.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;The problems&lt;/u&gt;&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;The main problem consist in the fact that the installer does not provide any tip to help you achieve that. By default, Publisher installer provides 2 options: Full Component (it means publisher engine, workflow engine, and the embedded redirector) or Publish Content Redirector Only.&lt;/p&gt;  &lt;p&gt;A couple of common shortfall if out of box design is followed:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Publisher engine (explorer) cannot be clustered. &lt;/li&gt;    &lt;li&gt;Publisher internal application server (JBOSS) is serving publisher, workflow, redirection, and published content. &lt;/li&gt;    &lt;li&gt;Publish Content Redirector standalone is not optimized for serving static content (it is used mainly to redirect to the actual publish content url, based on the requested publisher item ID) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;The Solutions:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Ultimately, what we want to do is decouple each component from each other in order to scale it independently from the others. Thus, what we want to improve through architecture design consist in:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Publisher and workflow engine set up in failover mode. (Hot-Warm or Hot-Cold failover) &lt;/li&gt;    &lt;li&gt;Publish Content Redirector Load balanced using Hardware (F5 BigIP, Cisco LB) or software load balancer. &lt;/li&gt;    &lt;li&gt;Publish Content Served by appropriate web server (apache or IIS), optimized to best deliver static content (best performance)...instead of the publisher internal jboss app server (better optimized for dynamic J2EE content delivery). &lt;/li&gt;    &lt;li&gt;Publish Content Web Server (apache or IIS) to be load balanced using Hardware (F5 BigIP, Cisco LB) or software load balancer. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Following that design, the redirector can be scaled independently from the publish content serving mechanism, as well as from the publisher admin. And also, if the server that hosts publisher is down, the redirector services and publish content services are still able to provide content without any problem. Similarly, since the redirectors and pub content web servers are load balanced, they are fully redundant, providing maximum availability of static content on your ALUI powered internet site for example.&lt;/p&gt;  &lt;p&gt;So how do we tie everything together? Here is an overview of tasks that corresponds to what we talked about until now: (here using 4 servers in my example...could use more or less depending on what hardware is available to you...with a minimum of 2 servers of course.)&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Install full Publisher on Server A (contains redirector capability by default) &lt;/li&gt;    &lt;li&gt;Import the publisher objects in the portal (pte file) &lt;/li&gt;    &lt;li&gt;Install redirector component on Server B &lt;/li&gt;    &lt;li&gt;Install Apache/IIS on server C and D &lt;/li&gt;    &lt;li&gt;Create the 3 load balancing pools, 1 for Publisher (useful for HOT-WARM failover), 1 for Redirector, 1 for publish content web server. &lt;/li&gt;    &lt;li&gt;In publisher explorer, set the &amp;quot;publishing target&amp;quot; to a fault tolerant and fully redundant file share. (clustered NAS for example) &lt;/li&gt;    &lt;li&gt;Still in &amp;quot;publishing target&amp;quot; screen, set the browsing url to make sure it access the publish content web server pool (and as such access the Apache/IIS web servers) &lt;/li&gt;    &lt;li&gt;Setup Apache/IIS web servers on C and D in order to expose the published content that is at the &amp;quot;publishing target&amp;quot; set up previously &lt;/li&gt;    &lt;li&gt;We need to modify the publisher portal objects in order to make them access the correct load balancing pools      &lt;ol&gt;       &lt;li&gt;Change PubContent Web Service Url to make it access the redirector load balancing pool. &lt;/li&gt;        &lt;li&gt;Also, change accordingly the gateway prefixes of the PubContent Web Service, especially the ones related to published content (publish/preview) &lt;/li&gt;        &lt;li&gt;Make sure the publisher url is actually going to the LB instead of going directly to publisher. &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;One last thing you might want to do to still increase performance: Make sure you publish the images to the image server instead of the publish content repository. (Since the image server is publicly accessible from the internet, do this only if the images you are working with are not exposing information that should not be publicly accessible!). This is explained by the fact that serving binary content through the portal gateway component is much slower than serving the content directly to end user.&lt;/p&gt;  &lt;p&gt;Et Voila! When you are done configuring all that, you have a publisher infrastructure that is completely redundant in every aspects, offers maximum scalability for each critical components, as well as&amp;#160; maximum performance for serving static content.&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ed78b600-98f5-44a9-b7a1-d51bc41fbdfa" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/ALUI%20Portal" rel="tag"&gt;ALUI Portal&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Architecture" rel="tag"&gt;Architecture&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ALUI%20Component" rel="tag"&gt;ALUI Component&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ALUI%20Publisher" rel="tag"&gt;ALUI Publisher&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Best%20Practices" rel="tag"&gt;Best Practices&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-8427902675669436070?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9DxTmwM4G3M:aiiBQiy28Lo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9DxTmwM4G3M:aiiBQiy28Lo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=9DxTmwM4G3M:aiiBQiy28Lo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=9DxTmwM4G3M:aiiBQiy28Lo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/9DxTmwM4G3M/alui-publisher-increase-performance.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/02/alui-publisher-increase-performance.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-4987056039294083518</guid><pubDate>Tue, 29 Jan 2008 00:58:00 +0000</pubDate><atom:updated>2008-08-21T11:39:35.320-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">Portal Maintenance</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Administration Tool for Environment Refresh: String Replacing for URLS</title><description>&lt;p&gt;Any company that owns a portal infrastructure such as ALUI will usually also plan for extra portal environments for troubleshooting and test purposes. Any portlet developments, portal customizations, or administrative changes will be implemented and tested in those environments. This is very good practice indeed. But you will quickly notice something happening: Your production portal is no longer in sync with your other staging / QA / Test environments. Although not necessarily a huge deal in the immediate future, that could become a problem when your test environment is really too different from the production one: Imagine the test team trying to execute a test plan in Staging environment, but half the production communities are simply not present in the test environment...etc...etc...etc...&lt;/p&gt;  &lt;p&gt;I am sure you figured where I am going: Sooner or later, a clean refresh of your tests environments will be needed. Such a refresh is best done by a full database copy from production to your test environment (ALUI built-in export / import functionality is not suited for a large amount of objects, and thus is totally inappropriate and not recommended in the present case)&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;Besides restoring all the appropriate repositories (documents, published content, search indexes etc...), a major problem remains: All the various service' urls specified in the various ALUI objects (Remote servers, web services, KD cards, server urls, etc...) are no longer accurate in the refreshed test environments (of course: those urls are the production ones). Thus&amp;#160; your test environment is far from working yet. &lt;/p&gt;  &lt;p&gt;2 possibilities from here (1 good and 1 less good):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You use host files in your test environments. These hosts files will direct the same production urls to the appropriate test servers (not good in my point of view because it is dangerous: if the hosts files is removed, there is a huge risk of having your test environment accessing production - thus not good :) ) &lt;/li&gt;    &lt;li&gt;You use environment-specific DNS entries for each services. (Much better because no risk of inter-environment communication) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;First, it is much better practice to call each service through DNS name rather than directly to through the server name. And secondly, it makes it much easier when it comes to environment refresh. &lt;/p&gt;  &lt;p&gt;Why? Because all the DNS entries follow a global &amp;quot;intelligent&amp;quot; pattern (i.e. PUBLISHER.COMPANY.COM / PUBLISHER-TEST.COMPANY.COM / PUBLISHER-DEV.COMPANY.COM / etc...), it is much easier to create a tool (or a DB query for those DB gurus out there) that will allow for automatic replace of these DNS names.&lt;/p&gt;  &lt;p&gt;That's where I wanted to lead you: &lt;/p&gt;  &lt;p&gt;I created a tool that allow just that: for all the portal objects that contain URLs, the tool can replace a specific pattern with another one that you define. Although I could have created a set of DB queries that could do the job (I actually started to do that when I had to do my first environment refresh), I realized that a utility written in JAVA (most portable language) and using ALUI server API would guaranty portability, extensibility and reusability. The main advantage is that it is completely independent from backend technologies, and can work with any ALUI portal (.NET or JAVA), as well as any database (MS SQL or Oracle). It has been tested with JRE 1.4 and used by me on all G6 portal versions (until 6.1 MP1 included)&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;DISCLAIMER: ALTHOUGH I PERSONNALY USE THIS TOOL, THERE IS NO GUARANTY; SO USE THIS TOOL AT YOUR OWN RISK blah blah blah AND USE IT ONLY IF YOU ARE PROFFICIENT ENOUGH WITH ALUI PORTAL TECHNOLOGIES.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;2 smart moves if you are not the easily scared type of person: First, make a DB backup of the test environment you are going to refresh, and second, test it in your local environment first, and see with your own eyes that it works perfectly well :)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;For the moment, this migration utility only updates the main portal objects that contain urls:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Remote servers     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Web Services     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Portal Settings&lt;/p&gt;  &lt;p&gt;When I have time, I'll improve the utility and include publisher content items (especially urls embedded in them) in the list of migration objects.&lt;/p&gt;  &lt;p&gt;Shell scripts (.bat and .sh) are created in order to facilitate and secure the usage of this utility. The user must provide several key information for the program to run:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Application name (by default: portal)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Administration username (must be an ALUI local database user)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Username password     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Pattern to look for (any valid regular expression)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Replacement String     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -Optional: Debug mode? (if true, details of the parsed objects is output to screen) &lt;/p&gt;  &lt;p&gt;The executable JAR along the appropriate launch scripts (bat for windows, sh for unix/linux) must be copied into the &amp;lt;PT_HOME&amp;gt;/bin folder in order to access the required libraries (otherwise the shell script -especially the java classpath- can be changed appropriately)&lt;/p&gt;  &lt;p&gt;I zipped this tool (scripts and jar) for your convenience and uploaded it (pturlreplace-1.0.zip) to my google code project (&lt;a title="http://code.google.com/p/alui-toolbox/" href="http://code.google.com/p/alui-toolbox/"&gt;http://code.google.com/p/alui-toolbox/&lt;/a&gt;). &lt;/p&gt;  &lt;p&gt;Let me know what you think of it after you tested it. If you think it is useful, I'll update this post with new version of the tool as I come up with it. Enjoy!&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d7e5803a-aacf-4e0b-9b5c-e1359bbcefb0" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/ALUI%20Portal" rel="tag"&gt;ALUI Portal&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Portal%20Maintenance" rel="tag"&gt;Portal Maintenance&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Technical%20Tips" rel="tag"&gt;Technical Tips&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Tools" rel="tag"&gt;Tools&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-4987056039294083518?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=8cdXrRV8Y3s:SiCF_99K8uE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=8cdXrRV8Y3s:SiCF_99K8uE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=8cdXrRV8Y3s:SiCF_99K8uE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=8cdXrRV8Y3s:SiCF_99K8uE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/8cdXrRV8Y3s/alui-administration-tool-for.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/01/alui-administration-tool-for.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-4186717474781877373</guid><pubDate>Sun, 13 Jan 2008 00:52:00 +0000</pubDate><atom:updated>2008-06-24T21:02:41.448-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI Portlet Monitoring Tool</title><description>&lt;p&gt;Most ALUI Portal environments will usually contain a large number of portlets, either &amp;quot;out-of-the-box&amp;quot; or custom portlets. These portlets, which range from simple bookmark links to sophisticated applications that interact with third party products such as Siebel or SAP, are indeed the major components that serve the high value functionality of your ALUI portal. Thus, it is vital that these portlets are monitored properly, so that a problem can be detected as soon as possible (preferably before your customer calls you to report the error that you had no idea was occurring...) and of course corrected asap.&lt;/p&gt;  &lt;p&gt;Developed by Project Performance Corporation (&lt;a href="http://www.ppc.com"&gt;www.ppc.com&lt;/a&gt;), Portlet Monitor&amp;#174; is a utility designed to track the operational status of all portlets registered in any communities or mypages of your ALUI Portal environment. Although Rakesh Gupta from PPC is the creator of this product, I personally redesigned and upgraded it for version 6.X of ALUI, and thus know the internals of it inside out.&lt;/p&gt;  &lt;p&gt;You can contact me (fsanglier-at-ppc-dot-com) if you need additional information and pricing.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;What is it?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Portlet monitor is a stand alone application (developed in .NET) that uses the Port&lt;/p&gt;  &lt;p&gt;al Server API to read the portal data, especially the community and portlet objects. It can be installed on any server that have the following components: Portal, Automation, or API Service (to be able to use the server API). Using windows automated tasks (or even ALUI automation server) portlet monitor can be configured to run at any pre-specified time.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;How does it work?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In plain English, Portlet Monitor connect as a portal user (by initiating a portal session) and iterate through all communities, mypages and finally portlets (the ones that are actually used on the community or &amp;quot;My&amp;quot; pages) that this user has access to. For each of the portlet found, Portlet monitor will &amp;quot;fake&amp;quot; a gateway call to the remote server hosting the portlet, passing all the required portal preferences and other ALUI-specific settings to the remote portlet application. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Error Found?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Various types of error can be caught by portlet monitor:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Various HTTP Errors (500 / 401 / etc...) returned by the remote portlet application/web server. &lt;/li&gt;    &lt;li&gt;Portlet Timeout errors &lt;/li&gt;    &lt;li&gt;Network errors (remote portlet server has some network problems) &lt;/li&gt;    &lt;li&gt;Portal exceptions (portal settings or portlet preferences missing, problem with gateway component or any other portal internal component, etc...) &lt;/li&gt;    &lt;li&gt;Specific error text pattern found in the portlet (if the above errors are not found, an error can be triggered if a specific text patterns is found in a specific portlet) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Results?&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;The result of each run is locally saved in an XML file that contains the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The portlet ID &lt;/li&gt;    &lt;li&gt;The community / mypage of the analyzed portlet &lt;/li&gt;    &lt;li&gt;Processing Time &lt;/li&gt;    &lt;li&gt;If &amp;quot;Broken&amp;quot;, the last date/time the portlet was found &amp;quot;Working&amp;quot; &lt;/li&gt;    &lt;li&gt;If &amp;quot;Broken&amp;quot;, the cause of the error (exception trace or error code) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;After each run, an email containing the above XML report is automatically sent to the specified email list. (usually portal administrator and specific portlet developer(s))&lt;/p&gt;  &lt;p&gt;It is also possible to eventually serve the XML report directly in the portal through a portlet (with a XSLT applied of course)&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Performance?&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;Portlet monitor can be installed on any windows server that contains either the portal, automation or API service component (It is important to note that the portal component service does not need to be running) Thus, to minimize the performance impact of portlet monitor successive runs, it is recommended to install it on a server that is not part of the live portal cluster.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Why using this Tool versus Enterprise Monitoring Tools?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;While most enterprise monitoring tools (i.e. NETIQ) work from the component service (or process) point of view, Portlet Monitor works from the portal point of view. What does it mean exactly?&lt;/p&gt;  &lt;p&gt;Basically, enterprise monitoring tools are able to to monitor windows services, and eventually restart them if something wrong is happening. They are also able to monitor component log files and search for any text pattern that are relevant to an error, and if found, perform a specific action. (like restart the service) They are also able to perform a lot of other various operations...&lt;/p&gt;  &lt;p&gt;But what they are not able to do in a portal context like ALUI (versus Portlet Monitor) are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Detect the errors before the end-user finds it (by running the portlet monitor scans at scheduled intervals) - compared to finding the errors in the log files when the end-user actually triggered the error himself... &lt;/li&gt;    &lt;li&gt;Detect point of failure(s) between the portal and the portlet remote server &lt;/li&gt;    &lt;li&gt;Detect portal application or database defects (i.e. gateway problem) that could induce the portlet in error (from portal point of view), even if the remote application is just working fine. &lt;/li&gt;    &lt;li&gt;Detect misconfiguration of the portlet that could induce the portlet in error (from portal point of view), even if the remote application is just working fine. &lt;/li&gt;    &lt;li&gt;Detect any infrastructure or software errors that would induce a timeout of the portlet. &lt;/li&gt;    &lt;li&gt;Detect any portlet errors even if the monitoring agent is not running (sometimes the monitoring agent can have defect too...) &lt;/li&gt;    &lt;li&gt;Detect any portlet errors even if the portlet application service is in a &amp;quot;Frozen&amp;quot; state (meaning the service is still up, the log are not showing any error, and thus the monitoring system is not reporting anything wrong, but the application is actually not responsive anymore) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It is important to note that portlet monitor is just a monitoring and notifying tool: It does not perform any action (like restarting services etc...) other than notifying the right people.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Last Words&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you don't have a monitoring infrastructure in place, this tool will offer you monitor effectively the most important and valuable components of your portal (portlets).&lt;/p&gt;  &lt;p&gt;If you have already a monitoring infrastructure in place, this tool is &lt;strong&gt;not meant to replace&lt;/strong&gt; it, but rather to be a valuable &lt;strong&gt;addition&lt;/strong&gt; that completes your monitoring infrastructure already in place.&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:67df18ab-18a2-4d6c-815e-84d5f1532064" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Aqualogic%20User%20Interaction" rel="tag"&gt;Aqualogic User Interaction&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ALUI%20Portal" rel="tag"&gt;ALUI Portal&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Tools" rel="tag"&gt;Tools&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-4186717474781877373?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=oj-6_Yv0GxM:D-GOjdxPX7s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=oj-6_Yv0GxM:D-GOjdxPX7s:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=oj-6_Yv0GxM:D-GOjdxPX7s:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=oj-6_Yv0GxM:D-GOjdxPX7s:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/oj-6_Yv0GxM/alui-portlet-monitoring-tool.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2008/01/alui-portlet-monitoring-tool.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-8896626015299424819</guid><pubDate>Wed, 05 Dec 2007 23:25:00 +0000</pubDate><atom:updated>2008-06-24T19:37:49.271-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Portlet Development</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI and Java Server Faces Portlet development - Part 2 (Continued)</title><description>&lt;p&gt;In my previous ALUI JSF post &lt;a title="ALUI and Java Server Faces Portlet development - Part 1" href="http://dev2dev.bea.com/blog/fsanglier/archive/2007/12/alui_and_java_server_faces_por.html"&gt;ALUI and Java Server Faces Portlet development - Part 1&lt;/a&gt;, I talked about the problems you might encounter while using JSF and ALUI, and I also started to explain how to fix those problems. I will continue with that post...&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Form Unique Id&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It is standard (best) practice to make sure every ids and every javascript function names in a HTML page are unique. That way, Javascript functions are targetted correctly when called, and Javascript functions can effectively use &amp;quot;getElementById()&amp;quot; to access the right element within the portlet. When you are in a Portal environment, it is difficult to ensure that all the portlets on the page have unique ids. And thus it is possible to have a defective portlet when rendered with others on the same page, due to those kind of interferences (same element ids or same javascript function names). The probably of error reach 100% of chance if you put 2 portlets with identical content on the page.&lt;/p&gt;  &lt;p&gt;Traditionally, with web applications where you have control over every elements and javascript function throughout the page (i.e. standard JSP), you would surely use the &lt;a href="http://edocs.bea.com/alui/devdoc/docs60/Portlets/Adaptive_Portlets/Using_Adaptive_Tags/plumtreedevdoc_integration_portlets_adaptive_namespacetoken.htm#namespace"&gt;pt:common.namespace&lt;/a&gt; adaptive tag, in order to append to every JS functions and form ids the token string (i.e. $$PT_TOKEN$$)&lt;/p&gt;  &lt;p&gt;But unfortunately, that won't work with JSF. Why is that?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;First, quick reminder:&lt;/strong&gt; It is important to note that &amp;quot;namespace&amp;quot; tag (like every ALUI Adaptive Tags) is transformed by the GATEWAY component. In other word, if you use the tag $$PT_TOKEN$$ throughout your JSF form, the remote JSF application DO see literally &amp;quot;$$PT_TOKEN$$&amp;quot;, not the actual portlet IDs. When the portlet response goes through the gateway component, that is when the tag &amp;quot;$$PT_TOKEN$$&amp;quot; is changed on the fly with the real portlet id number. &lt;/p&gt;  &lt;p&gt;Since JSF is a component oriented framework that generates the HTML markup, we don't have direct control over the HTML elements...and also, the element &amp;quot;name&amp;quot; (this is posted back to the server) is usually the same as the element &amp;quot;id&amp;quot;. Thus, when you use:&lt;/p&gt;  &lt;pre&gt;&lt;p&gt;&amp;lt;h:form id=&amp;quot;editaddress_$$PT_TOKEN$$&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;h:inputText id=&amp;quot;fullname&amp;quot; value=&amp;quot;#{bean_backing.fullname}&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/h:form&amp;gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You HTML markup for the response is:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;p&gt;&amp;lt;form id=&amp;quot;editaddress_$$PT_TOKEN$$&amp;quot; =&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;input id=&amp;quot;editaddress_$$PT_TOKEN$$:fullname&amp;quot; &lt;br /&gt;name=&amp;quot;editaddress_$$PT_TOKEN$$:fullname&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And when you visualize the portlet source code (as rendered by the portal, where 289 is the portlet id that renders your web application), you get:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;p&gt;&amp;lt;form id=&amp;quot;editaddress_289&amp;quot; =&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;input id=&amp;quot;editaddress_289:fullname&amp;quot; &lt;br /&gt;name=&amp;quot;editaddress_289:fullname&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So great, we do have unique HTML elements within each portlets, but you start to get the problem, right? Okay I am still going to explain :)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So the JSF component is waiting for a posted request attribute with literal name &amp;quot;street_$$PT_TOKEN$$&amp;quot;, but actually, the posted attribute is &amp;quot;street_289&amp;quot;...and thus the JSF component cannot decode the posted value, and thus the form post won't work.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So the solution is to include the real portlet Id on the remote application side directly. I will use the same technique that I explained in the previous post: Custom renderer for the Form JSF component, overriding this time the base method &amp;quot;&lt;em&gt;&lt;strong&gt;convertClientId(FacesContext context, String clientId)&lt;/strong&gt;&lt;/em&gt;&amp;quot;. Within the overridden method, I get the portlet id by simply using the IDK and then append the id to the component id.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="width: 795px; height: 231px"&gt;&lt;p&gt;    @Override&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public String convertClientId(FacesContext context, String clientId) {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IPortletContext ctx = PortletContextFactory.createPortletContext(&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (HttpServletRequest)context.getExternalContext().getRequest(), &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (HttpServletResponse)context.getExternalContext().getResponse()&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IPortletRequest portletRequest = ctx.getRequest();&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //add the portlet id to the form&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if(portletRequest.isGatewayed())&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; clientId += ctx.getRequest().getPortletID();&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return super.convertClientId(context, clientId);&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That's it!! That way, even if you let JSF generate the form element id, the &amp;quot;portlet id&amp;quot; WILL be appended if you are viewing the application through the portlet. And since the component is aware of the portlet id, the post will work fine. And finally, since the &amp;lt;h:form&amp;gt; is very often the top element of your JSF page, all the sub elements will also be unique since the form id is the prefix for all the children component ids.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Although you probably don't want to create a custom specific renderer for every components you want to use, this technique seems the best to me because it is completely non-intrusive within your JSF page...and thus, in the future, if BEA corrects all those JSF problems, you just disable the custom renderers and everything will work without any change.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-8896626015299424819?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=43JNqPipAeo:NCvZlT0nxZA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=43JNqPipAeo:NCvZlT0nxZA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=43JNqPipAeo:NCvZlT0nxZA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=43JNqPipAeo:NCvZlT0nxZA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/43JNqPipAeo/alui-and-java-server-faces-portlet_05.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/12/alui-and-java-server-faces-portlet_05.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-5600426108167562787</guid><pubDate>Sun, 02 Dec 2007 01:25:00 +0000</pubDate><atom:updated>2008-06-12T00:49:30.811-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Portlet Development</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>ALUI and Java Server Faces Portlet development - Part 1</title><description>&lt;p&gt;Lately I have been looking into JSF and especially the Myfaces implementation as a development framework&amp;#160; for ALUI portlets, Similar to ASP.NET, I personally do think JSF is also an awesome and powerful framework to develop all sort of cool portlets and applications. But similar to ASP.NET portlets, JSF portlets have some problems when integrated in ALUI portal.&lt;/p&gt;  &lt;p&gt;Mainly, the problems lie in the fact that those 2 frameworks are component oriented: We don't have a lot of control on the rendition of those control, and sometimes, the way they render is not fully compatible with the way ALUI portal behave:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Some urls in generated javascript are not always successfully gatewayed. &lt;/li&gt;    &lt;li&gt;The portal does not enforce generated Html components to have unique IDs throughout the portal pages (i.e. 2 portlets on the same page can possibly have 2 form tags with same ids...which would very likely mess with the functionality of the portlets) &lt;/li&gt;    &lt;li&gt;If you don't enable ALUI inline refresh, the portlets will go in the &amp;quot;Gateway&amp;quot; space (or the maximized state) on any navigation event. Although that can be useful in certain case, it won't to perform portlet-to-portlet communication (since the other portlets disappear in this maximized state). &lt;/li&gt;    &lt;li&gt;If you DO enable inline refresh, you will hit other problems due to the fact that the Javascript layer added to the &amp;quot;inline-refresh&amp;quot; enabled portlet can interfere with the good behavior of some of the JSF/DOTNET components... &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Ok...having painted such a &amp;quot;&lt;em&gt;Dantesque&lt;/em&gt;&amp;quot; picture of the portlet development within ALUI portal, I now want to reassure you: Because ALUI is so extensible and powerful, all those problems can be resolved, and that's the goal of this post: Showing you some of the trick to make it all work.&lt;/p&gt;  &lt;p&gt;For you DotNet users, you are in luck :) BEA introduced the &amp;quot;BEA AquaLogic .NET Application Accelerator&amp;quot; to offer a remedy to all the problems above. Since it is all there at &lt;a title="http://www.bea.com/framework.jsp?CNT=index.htm&amp;amp;FP=/content/products/more/accelerator/" href="http://www.bea.com/framework.jsp?CNT=index.htm&amp;amp;FP=/content/products/more/accelerator/"&gt;http://www.bea.com/framework.jsp?CNT=index.htm&amp;amp;FP=/content/products/more/accelerator/&lt;/a&gt; I won't talk to much about it.&lt;/p&gt;  &lt;p&gt;But what about you poor JSF users? Well unfortunately for you (and I), we will have to get to work :)&lt;/p&gt;  &lt;p&gt;But before getting to work, some of you might say: What about the &amp;quot;Java Portlet Tool&amp;quot; (&lt;a title="http://dev2dev.bea.com/pub/a/2006/05/java-portlet-tools.html" href="http://dev2dev.bea.com/pub/a/2006/05/java-portlet-tools.html"&gt;http://dev2dev.bea.com/pub/a/2006/05/java-portlet-tools.html&lt;/a&gt;)? Well I looked at that quite thoroughly. I must admit that it is a pretty involved and clever piece of code...and it makes things work a little better on the JSF side. I especially do like the bean support for IDK functionality. Unfortunately, the following points are making me very hesitant and uneasy about this framework:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Unlike &amp;quot;BEA AquaLogic .NET Application Accelerator&amp;quot;, the &amp;quot;Java Portlet Tool&amp;quot; (which is written by a BEA resource) is not supported by BEA. (Even though I could go with that - after all since the Java portlet tool code is provided, we could eventually support it ourselves - I would not recommend it to my clients who pay a lot of money to get support), &lt;/li&gt;    &lt;li&gt;In addition to that, the java portlet tool, which rely on the modification of the pretty involved inline refresh jsxml javascript libraries (PTXML.js), seems to have been developed and tested with Plumtree 5.x, and does not seem to have been upgraded for 6.x versions of the portal. (thus, it might or might not work with 6.x versions) &lt;/li&gt;    &lt;li&gt;Finally, the java portlet tool project has not been modified since 2006, which makes me think there are not a lot of people using it, or keeping it up-to-date. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Okay...so no supported portal framework for JSF...but still I want to use inline refresh...&lt;/p&gt;  &lt;p&gt;Does it mean that I have to develop my JAVA portlets the way I use to develop them 5 years ago, without the popular frameworks out-there? Well I personally refuse to do that, and you should too :)&lt;/p&gt;  &lt;p&gt;So it is time to have some fun finally!&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;JSF Navigation&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;A major problem I found with the ALUI inline refresh and JSF is that HTTP POSTs with JSF navigation is not working. JSF framework navigation (similarly to struts etc...) is controlled by the framework itself, based on the navigation rules you define in the JSF config file. (faces-config.xml). In other words, when the form is posted back to the server, the framework will deal with the navigation based on the action define on the command button that triggered the HTTP POST. Nothing unusual until now, and such a navigation behavior will work fine if you don't enable inline refresh...but the next page will be displayed in the maximized state we want to avoid.&lt;/p&gt;  &lt;p&gt;When you enable inline refresh though, the ALUI portal will intercept the button submit action and perform its own submit action using its AJAX/Javascript framework (PTXML.js). On the html side, you will see:&lt;/p&gt;  &lt;pre style="width: 993px; height: 69px" rows="6"&gt;&lt;p&gt;&amp;lt;form id=&amp;quot;viewaddress&amp;quot; name=&amp;quot;viewaddress&amp;quot; onsubmit=&amp;quot;pt_280.formRefresh(this); return false;&amp;quot; method=&amp;quot;post&amp;quot;&lt;/p&gt;&lt;p&gt;action=&amp;quot;&lt;a href="http://localhost:7001/portal/server.pt/gateway/PTARGS_0_0_280_377_0_43/http%3B/localhost%3B7001/MyJSFDemo/viewAddress.jsf&amp;quot;"&gt;http://localhost:7001/portal/server.pt/gateway/PTARGS_0_0_280_377_0_43/http%3B/localhost%3B7001/MyJSFDemo/viewAddress.jsf&amp;quot;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We can particularly notice how the submit is intercepted: the OnSubmit event handlers of the form tag does a &amp;quot;return false&amp;quot;, which is the equivalent of saying: the submit button has never been clicked, the form has never been submitted. The &amp;quot;pt280.formRefresh(this);&amp;quot; is the statement that will post the form using an AJAX call. How this works is interesting: Using JavaScript to go through the DOM, the portal reconstructs the post request using all the input fields in the form (which would have been posted to the server). But the problem is: during that reconstruction, the &amp;lt;input type=&amp;quot;button&amp;quot; /&amp;gt; and &amp;lt;input type=&amp;quot;submit&amp;quot; /&amp;gt; are purposely left out. Although this usually makes sense in a standard web application (those buttons don't have a particular meaning on the server side, they are just useful to trigger a post back to the server), it does not make sense in the JSF world: the button name/value pair should be posted back to the server because the navigation rules won't happen otherwise. The result is that with inline refresh, navigation initiated by a form post is NOT working.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That is inconvenient...but we can correct that easily: if we create a hidden input field that has the same name and value as the button clicked, then this hidden field WILL be included in the posted request and the navigation will then work! Great! But you don't want to manually add yourself the hidden field in the form...for the simple reason that you want the value posted only when a particular button is clicked.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So the simple fix is to use javascript to dynamically add the input field in the form:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="width: 1011px; height: 247px"&gt;&lt;p&gt;&amp;lt;pt:namespace pt:token=&amp;quot;PORTLET_ID&amp;quot; xmlns:pt='&lt;a href="http://www.plumtree.com/xmlschemas/ptui/'"&gt;http://www.plumtree.com/xmlschemas/ptui/'&lt;/a&gt; /&amp;gt;&lt;/p&gt;&lt;p&gt;function setHiddenInputPORTLET_ID(form, name, value){&lt;br /&gt;	var newInput = document.createElement('input');&lt;br /&gt;	newInput.setAttribute('type','hidden');&lt;br /&gt;	newInput.setAttribute('name',name);&lt;br /&gt;	newInput.setAttribute('value',value);&lt;br /&gt;	form.appendChild(newInput);&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;&amp;lt;input id=&amp;quot;viewaddress:_idJsp12&amp;quot; name=&amp;quot;viewaddress:_idJsp12&amp;quot; type=&amp;quot;submit&amp;quot; value=&amp;quot;Change&amp;quot; &lt;/p&gt;&lt;p&gt;onclick=&amp;quot;if(typeof window.oamSetHiddenInputPORTLET_ID!='undefined'){setHiddenInputPORTLET_ID(this.form,'viewaddress:_idJsp12','Change');}&amp;quot; /&amp;gt;&lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That way, when you click the button, the equivalent hidden input is added to the form, which will then be effectively posted by the &amp;quot;pt280.formRefresh(this);&amp;quot; call. You noticed that I also use the ALUI adaptive tag to generate a unique token (portlet id) and thus make the JavaScript function &amp;quot;setHiddenInput&amp;quot; unique (that way, no interferences can occur if multiple portlets are on the same page)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In addition, you certainly don't want to force your developers to create that by hand for every buttons, (as well as introducing in your presentation code such a specific bug fix). So in order to be the least intrusive possible, I chose to customize a little bit the rendering of the &amp;lt;h:commandButton&amp;gt; element, which is the one responsible for postback and navigation:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="width: 1005px; height: 86px"&gt;&lt;p&gt;&amp;lt;h:panelGroup&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;h:commandButton action=&amp;quot;editaddress&amp;quot; value=&amp;quot;Change&amp;quot;&amp;gt;&amp;lt;/h:commandButton&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;/h:panelGroup&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To do that, you just have to create a Class that extends the HtmlButtonRenderer class, and overrides 2 methods: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;encodeEnd to generate the javascript function setHiddenInput281() &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;  &lt;li&gt;buildOnClick so add the call to the generated function setHiddenInput281() &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That way, your JSF page are exactly the same...but the rendering of it is a little different when viewed through the portal. You can find the full custom renderer &lt;a title="PTCmdRendered.java" href="http://dev2dev.bea.com/blog/fsanglier/PTCmdRenderer.java"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That fix alone will take care of a good majority of the problems you would have had with using JSF and inline refresh inside ALUI. On a next post, I will show you how to deal with form ids when several JSF portlets are on the same page.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So long!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-5600426108167562787?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=Dqp2_05O1eU:8phS1gx6zMQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=Dqp2_05O1eU:8phS1gx6zMQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=Dqp2_05O1eU:8phS1gx6zMQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=Dqp2_05O1eU:8phS1gx6zMQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/Dqp2_05O1eU/alui-and-java-server-faces-portlet.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/12/alui-and-java-server-faces-portlet.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-3593131866590024301</guid><pubDate>Sun, 18 Nov 2007 00:11:00 +0000</pubDate><atom:updated>2008-06-12T00:12:42.936-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Best Practices</category><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>BEA Aqualogic Portal (ALUI) - Single Sign On (SSO) Concerns and Techniques</title><description>&lt;p&gt;As explained very well on this great post &amp;quot;&lt;a title="Changing SSO Settings" href="http://www.function1.com/blog/aqualogic-user-interaction/changing-sso-settings.html"&gt;Changing SSO Settings&lt;/a&gt;&amp;quot; from Function1, it is highly recommended to protect only the &amp;quot;SSOServlet&amp;quot; (default path= /portal/SSOServlet) when you want to SSO-enable the ALUI Portal. As I worked recently with an integration of ALUI with CA Siteminder, I am going to go a little bit further so that the SSO solution is complete.&lt;/p&gt;  &lt;p&gt;But first, the 2 benefits of protecting only SSOServlet are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Performance (as explained in Function1's post) &lt;/li&gt;    &lt;li&gt;Enable guest access to the portal with same url (the portal is the gate, not the SSO agent) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;But the main concerns are related to the SSO Session versus the Portal Session. As explained in Function1's post, the timeouts of portal and SSO agent should be in sync so that the user is actually logged out when the portal session times out (20 minutes by default). As it is well explained, you want both timeout to be very close, the portal timeout being trigged a bit before the SSO timeout. &lt;/p&gt;  &lt;p&gt;But that's where I want to go just a little further...timeout sync is not enough to make the system perfect. Indeed, 2 extra use cases exist (and are not covered yet):&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;SSO session &amp;quot;keep-alive&amp;quot; &lt;/li&gt;    &lt;li&gt;SSO session Logged out. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;SSO session &amp;quot;keep-alive&amp;quot;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Basically, after the user successfully logged into ALUI portal (using SSO login screen), a SSO token has been created for its session (SSO cookie embedded in the browser session). But the problem is that after a successful login, the portal won't call SSOServlet again, and thus the SSO agent (generally on the web server front end, or the application server hosting the portal) has no longer anything to say about the traffic going through its agent since it is all unprotected from its point of view. Actually, it is as if the agent is not even seeing that traffic at all. Why do we care?? Well, the SSO session timeout is only refreshed if the agent is actually seeing any protected traffic. When the agent is not seeing any protected traffic, the timeout count down starts. &lt;/p&gt;  &lt;p&gt;So to sum up, when the user successfully logged in the portal and is browsing the portal protected content, it is as if the session was idle from the Siteminder point of view. That is perfectly fine (at least you wont notice the problem) if you only use SSO for the portal. But imagine you use SSO for any other application in your enterprise (which is the use of SSO by the way :) ), or even portlets within your ALUI portal, then you probably don't want your SSO session to timeout while you are browsing the portal. Otherwise, after 20 or 30 minutes (whatever is set up on your SSO system for SSO timeout), you will still be able to browse the portal fine (since you are not idle from the portal point of view), but your SSO Session WILL HAVE TIMED OUT...and you will have to login again if you go to another of your favorite enterprise SSO protected sites...&lt;/p&gt;  &lt;p&gt;So how can we make that work?? How can we ensure that the SSO session (or SSO token) is &amp;quot;kept alive&amp;quot; while we browse the portal?? Very simple trick actually: I basically created a dummy SSO protected content on the front end web server (for example &lt;a href="http://portal.com/sec/dummy.html"&gt;http://portal.com/sec/dummy.html&lt;/a&gt;) and embedded that url in an invisible iframe in every portal pages (well suited for the footer portlet of your portal, or better, put that in your favorite liquidskin component - see my liquidskin ongoing serie &amp;quot;&lt;a title="Overview of BEA ALUI LiquidSkin: Part 1" href="http://dev2dev.bea.com/blog/fsanglier/archive/2007/10/my_first_post_bea_liquidskin_o.html"&gt;Overview of BEA ALUI LiquidSkin: Part 1&lt;/a&gt;&amp;quot; and &amp;quot;&lt;a title="Overview of BEA ALUI LiquidSkin: Part 2" href="http://dev2dev.bea.com/blog/fsanglier/archive/2007/10/overview_of_bea_alui_liquidski.html"&gt;Overview of BEA ALUI LiquidSkin: Part 2&lt;/a&gt;&amp;quot;)... &lt;/p&gt;  &lt;p&gt;Basically, you have &amp;lt;iframe src=&amp;quot;&lt;a href="http://portal.com/sec/dummy.html"&gt;http://portal.com/sec/dummy.html&lt;/a&gt;&amp;quot; width=&amp;quot;0&amp;quot; height=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt; at the bottom of every page you wish...it seems low tech, but works pretty well: every portal pages that have that footer portlet will initiate a request to that protected url, letting the SSO agent know: Hey, i am not idle, my session is still alive!!&lt;/p&gt;  &lt;p&gt;Ok, good...but I am still not happy yet :)&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;SSO Log out&lt;/strong&gt;&lt;/u&gt; &lt;/p&gt;  &lt;p&gt;When you logout from the portal, you also want the SSO session to be logged out too. this is easy enough with CA siteminder: in the SSO policy you just provide the log out pattern to look for (usually something like &lt;a href="http://&amp;lt;portal&amp;gt;/portal/server.pt?open=space&amp;amp;name=Login&amp;amp;control=Login&amp;amp;doLogout=&amp;amp;clearsession=true"&gt;/portal/server.pt?open=space&amp;amp;name=Login&amp;amp;control=Login&amp;amp;doLogout=&amp;amp;clearsession=true&amp;quot;&amp;gt;/portal/server.pt?open=space&amp;amp;name=Login&amp;amp;control=Login&amp;amp;doLogout=&amp;amp;clearsession=true&amp;quot;&amp;gt;/portal/server.pt?open=space&amp;amp;name=Login&amp;amp;control=Login&amp;amp;doLogout=&amp;amp;clearsession=true&amp;quot;&amp;gt;http://&amp;lt;portal&amp;gt;/portal/server.pt?open=space&amp;amp;name=Login&amp;amp;control=Login&amp;amp;doLogout=&amp;amp;clearsession=true&lt;/a&gt;) and the SSO agent (remember it is on your front end web server or application server) will kill the SSO token if it intercept such a pattern in the request url. Cool!! That way, when you click log off in the portal, you are actually logged out.&lt;/p&gt;  &lt;p&gt;But again, let's imagine we have multiple systems that uses the SSO session. You first loggedin the portal, browse it a little, and then decide to go to this other SSO-protected application. Then you decide you are finished and logout from there. What happens if you log out from another system apart from the portal?? Well if you don't do anything special, you will logoff from this other application, which will normally kill the SSO session (same &amp;quot;finding logout url pattern&amp;quot; technique)...but if you go back to the portal after that (and you were previously logged in)...oh surprise, you can go in no problem!! Well that's normal, your portal session is not over yet (provided that you were not away from the portal more than the portal timeout) and you did not do anything to finish it...&lt;/p&gt;  &lt;p&gt;But that is not how it should work, right? If the SSO session is over (by logging off from any SSO protected system), you should not be able to go in any other SSO protected system!! Just imagine if your favorite banking web site was working this way...you logoff from your savings account, but your checking account interface is not logged off...I would not particularly like that from a security point of view :)&lt;/p&gt;  &lt;p&gt;So we have to deal with it: I see 2 options in order to make sure all your systems are logging out when 1 is logging out:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Having an independent logout page that initiates logout requests for all the protected applications in your enterprise (for example an HTML page containing as many &amp;lt;img&amp;gt; tags or &amp;lt;iframe&amp;gt; tags as you have application to log out) -- I don't like this method so much because I will have to maintain this central logout page as soon as I add / remove a protected application in my environment, &lt;/li&gt;    &lt;li&gt;Making applications log out on their own if the SSO token is not there. (or at least forcing any requests to SSO login if the SSO token is not present in the request) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The second solution is to me the best since it works once and for all. But it is a little more complex than the first one since we are protecting only the SSOServlet...(if the site was fully protected, that would work without doing anything...the agent would not see the SSO token and would not let you pass as long as you don't authenticate successfully)&lt;/p&gt;  &lt;p&gt;How can we do that in the portal? I chose to implement a JAVA filter (I was working with JAVA portal with that client) that checks for SSO token presence (you can implement the same filter functionality in DOTNET too: it is called http module). The simplified logic is: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;If SSO token is present and valid, do nothing, &lt;/li&gt;    &lt;li&gt;Otherwise, force portal logout (if you actually previously logged in)...which will make the request being redirected to SSO login... &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Et Voila! That way, the portal will logout nicely, on his own, when no SSO token is found.&lt;/p&gt;  &lt;p&gt;I hope this helps you better understand the different concerns of implementing Single Sign On with your favorite ALUI portal (would actually apply to other portals too)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-3593131866590024301?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mjkmsxX-FZo:mZFTvhzH71o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mjkmsxX-FZo:mZFTvhzH71o:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=mjkmsxX-FZo:mZFTvhzH71o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=mjkmsxX-FZo:mZFTvhzH71o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/mjkmsxX-FZo/bea-aqualogic-portal-alui-single-sign.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/11/bea-aqualogic-portal-alui-single-sign.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-517262676098706572</guid><pubDate>Sun, 04 Nov 2007 04:09:00 +0000</pubDate><atom:updated>2008-06-12T00:10:31.702-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Technical Tips</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>How to Change ALUI Components Passwords</title><description>&lt;p&gt;Each ALUI component requires Database information (host, schema, user, password, etc&amp;#8230;) in order to interact with their respective Database.&lt;/p&gt;  &lt;p&gt;When DBAs change the password of a database user (in some companies, it can actually happen pretty often) that is used by an Aqualogic User Interaction component, a similar &amp;#8220;password change&amp;#8221; procedure has to be done for each the concerned components&amp;#8217; configuration files.&lt;/p&gt;  &lt;p&gt;If that was just it, that could be easy...but thanks to security, every passwords in the ALUI configuration files are encrypted...and thus, you need to encrypt the password too. But how do you encrypt those passwords? Where is the encryption utility? &lt;/p&gt;  &lt;p&gt;ALUI provides several encryption mechanisms that you can apply to each component. I will try to walk you through what I call the encryption maze so that changing ALUI passwords becomes a breeze. (Note: files *.bat or *.cmd exist also in the unix/linux world...extension sh)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;ALI Portal&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;DB Configuration File(s) path : &lt;/p&gt;  &lt;p&gt;&amp;lt;PORTAL_HOME&amp;gt;\settings\common\serverconfig.xml&lt;/p&gt;  &lt;p&gt;Encryption Utility path: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptportal\&amp;lt;VERSION&amp;gt;\bin\ptconfig.exe (this utility will change the password directly in the serverconfig.xml file, OR &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptportal\&amp;lt;VERSION&amp;gt;\bin\cryptoutil.bat (must be executed in a shell or dos prompt -- provides the encrypted version of the text provided) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;ALI publisher / Workflow&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;DB Configuration File(s) path:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcs\&amp;lt;VERSION&amp;gt;\settings\config\database.content.properties (publisher DB connection) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcs\&amp;lt;VERSION&amp;gt;\settings\config\database.portal.properties (portal DB connection) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptworkflow\&amp;lt;VERSION&amp;gt;\settings\config\application.conf (workflow DB connection) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Encryption Utility path: &lt;/p&gt;  &lt;p&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcs\&amp;lt;VERSION&amp;gt;\bin\native\pcsencrypt.cmd&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Note: You can use that same utility to encrypt the publisher basic authentication user password too.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;ALI Collaboration&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;DB Configuration File(s) path: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcollab\&amp;lt;VERSION&amp;gt;\settings\config\database.xml (collaboration DB connection) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptnotification\&amp;lt;VERSION&amp;gt;\settings\config\database.xml (notification DB connection) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Encryption Utility path: &lt;/p&gt;  &lt;p&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcollab\&amp;lt;VERSION&amp;gt;\bin\passwordChanger.bat&lt;/p&gt;  &lt;p&gt;The utility passwordChanger.bat will change the password in both config file and database directly. This is very useful indeed, but what if the DBA only can change the password, or what if he already did change it...What now? Well another solution is available to you...you can use another encryption utility that works (weirdly): The publisher encryption utility &lt;em&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcs\&amp;lt;VERSION&amp;gt;\bin\native\pcsencrypt.cmd&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Note: You can use that same utility to encrypt the collaboration basic authentication user password too.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;strong&gt;Studio&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;DB Configuration File(s) path: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptstudio\&amp;lt;VERSION&amp;gt;\settings\config\PTStudioConfig.xml (studio and portal DB connections) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Encryption Utility path: No encryption utility is provided in the studio directory, so believe it or not...you guessed it...again the publisher encryption utility can be used for both studio and portal DB passwords.&lt;/p&gt;  &lt;p&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptcs\&amp;lt;VERSION&amp;gt;\bin\native\pcsencrypt.cmd&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Analytics&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptanalytics\&amp;lt;VERSION&amp;gt;\settings\config\security\securityservice-config.xml (portal DB connection) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptanalytics\&amp;lt;VERSION&amp;gt;\settings\config\hibernate.properties (analytics DB connection) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptanalytics\&amp;lt;VERSION&amp;gt;\settings\config\configurator.properties (analytics, portal, collaboration and publisher DB connections) &lt;/li&gt;    &lt;li&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptanalytics\&amp;lt;VERSION&amp;gt;\settings\config\jobs.properties (portal, collaboration and publisher DB connections) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Encryption Utility path: Analytics provide a web configuration interface for changing DB connections and passwords in all the configuration files. But if you need to do it yourself without this web interface, again a solution exist: this time use the ... portal encryption for all the passwords!!&lt;/p&gt;  &lt;p&gt;&amp;lt;PORTAL_HOME&amp;gt;\ptportal\&amp;lt;VERSION&amp;gt;\bin\cryptoutil.bat&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;That's all I got for now! Hope this helps to navigate in ALUI Password encryption hell! :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-517262676098706572?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=psaWFyvUyxc:YNhGuSdrMJY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=psaWFyvUyxc:YNhGuSdrMJY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=psaWFyvUyxc:YNhGuSdrMJY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=psaWFyvUyxc:YNhGuSdrMJY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/psaWFyvUyxc/how-to-change-alui-components-passwords.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/11/how-to-change-alui-components-passwords.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-3371930708564528613</guid><pubDate>Sun, 28 Oct 2007 03:49:00 +0000</pubDate><atom:updated>2008-07-29T20:15:48.582-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Product Overview</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>Overview of BEA ALUI LiquidSkin : Part 1</title><description>&lt;p&gt;On one of my past project, I worked quite a bit with this (fairly) new BEA offering for BEA Aqualogic Interaction (ALUI) Portal: LiquidSkin. But what is it exactly?    &lt;br /&gt;Well, LiquidSkin is a pluggable component (or pluggable navigation in the ALUI jargon) that will transform your standard ALUI Portal Interface into a web-like easy-to-use easy-to-update interface.     &lt;br /&gt;LiquidSkin can be installed on any G6 portal (6.0, 6.1, 6.1 MP1) and supports rapid development of custom pluggable navigations.     &lt;br /&gt;It is important to note that this component DOES NOT come free with your portal purchase(inquire with BEA in regards of the pricing), but once bought, it includes installation/training by a BEA professionnal, as well as fairly good support. &lt;/p&gt;  &lt;p&gt;All in all, I've been quite impressed with this component and want to give an overview of the great features that it provides to your ALUI portal. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;First what is an ALUI pluggable navigation?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The pluggable navigations are ALUI software components that create the content around the portlets in your portal (for example links to mypages, my home, my communities, mandatory communities, my account, help, etc...) &lt;/p&gt;  &lt;p&gt;By default, ALUI provides a couple of standard navigation options:&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh6.ggpht.com/fabiensanglier/SI-vwY3d91I/AAAAAAAAABM/6wr5kIiDetg/s1600-h/NavigationOptions%5B5%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="279" alt="NavigationOptions" src="http://lh6.ggpht.com/fabiensanglier/SI-vxbzFqwI/AAAAAAAAABU/yxC1NBOrUKg/NavigationOptions_thumb%5B3%5D.jpg?imgmax=800" width="468" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Even though you can already do good things with those out-of-the-box navigations, it does not offer you a great flexibility. Indeed, if you want to customize you navigation (i.e. putting an extra link somewhere outside of your portlets), you will go through a great deal of code...(unless you are a real ALUI guru of course) &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;So what does LiquidSkin give me??&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;LiquidSkin fills that gap by offering a pluggable navigation &amp;quot;on steroid&amp;quot;, with a long list of navigational components that you can use easily in order to build the ALUI interface of your dream :) &lt;/p&gt;  &lt;p&gt;To give you a better idea of what LiquidSkin gives you, here are the parts of the screen that are the responsability of LiquidSkin (and thus that you can customize easily)&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh3.ggpht.com/fabiensanglier/SI-yk0RU9aI/AAAAAAAAABY/fDASJ4Cfijw/s1600-h/LiquidSkinAreas%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="298" alt="LiquidSkinAreas" src="http://lh5.ggpht.com/fabiensanglier/SI-yl76a2OI/AAAAAAAAABc/WC3oKh_WiV0/LiquidSkinAreas_thumb%5B1%5D.jpg?imgmax=800" width="453" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;List of Interesting features&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I dont want to sound too marketing (I am neither a BEA employee, nor have shares in the company :)), but below is a list of the feature that I most appreciate in LiquidSkin: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Complete configurable Pluggable Navigations that allows rapid development of custom navigations. &lt;/li&gt;    &lt;li&gt;Construct and deploy custom navigations by modifying simple XML configuration files. &lt;/li&gt;    &lt;li&gt;Only skills required: HTML (table-less) and CSS. No Coding!! &lt;/li&gt;    &lt;li&gt;Each skin tied to an experience definition: provide multiple intranet or .com-like navigation experiences within 1 portal. &lt;/li&gt;    &lt;li&gt;The navigation is available in both .Net and Java versions, and it is easy to install (15-30 minutes) &lt;/li&gt;    &lt;li&gt;Both the code and the configuration options are well documented, and there are multiple configuration examples. &lt;/li&gt;    &lt;li&gt;No Portal Restart when modifying or installing a new skin. &lt;/li&gt;    &lt;li&gt;Skin loader: Configurable schedule. &lt;/li&gt;    &lt;li&gt;Easy deployment from development to production: Copy only folders, images and xml documents (no compilation of code needed) &lt;/li&gt;    &lt;li&gt;Make it easy to internationalize your nav customizations. &lt;/li&gt;    &lt;li&gt;Optimize performance by selectively caching components output. &lt;/li&gt;    &lt;li&gt;Hide page display for communities with page name starting with specified word. &lt;/li&gt;    &lt;li&gt;Styles possibly targeted to different browsers &lt;/li&gt;    &lt;li&gt;Etc...(you will see for yourself when you start working with it) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;A couple of components you might like&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Top Nav and Breadcrumb&lt;/strong&gt;&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh5.ggpht.com/fabiensanglier/SI-ymYy8WRI/AAAAAAAAABg/Wh7g00CKX90/s1600-h/Breadcrumb%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="98" alt="Breadcrumb" src="http://lh6.ggpht.com/fabiensanglier/SI-ymtGkd7I/AAAAAAAAABk/_9uRQuO8wu8/Breadcrumb_thumb%5B1%5D.jpg?imgmax=800" width="541" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Left Navigation&lt;/strong&gt;&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh6.ggpht.com/fabiensanglier/SI-ynG9iXtI/AAAAAAAAABo/N9mAOeryM_8/s1600-h/LeftNavigation%5B2%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="236" alt="LeftNavigation" src="http://lh3.ggpht.com/fabiensanglier/SI-ynsH5W2I/AAAAAAAAABs/iGleGC4PQPw/LeftNavigation_thumb.jpg?imgmax=800" width="213" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;All together&lt;/strong&gt;&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh5.ggpht.com/fabiensanglier/SI-yodmoRjI/AAAAAAAAABw/ggPg5pUKm_o/s1600-h/AllComponents%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="270" alt="AllComponents" src="http://lh3.ggpht.com/fabiensanglier/SI-ypa2KSaI/AAAAAAAAAB0/FozX9QKFyoY/AllComponents_thumb%5B1%5D.jpg?imgmax=800" width="595" border="0" /&gt;&lt;/a&gt;     &lt;br /&gt;    &lt;br /&gt;On this last one, we can see one portlet on the page (Portal Login) and the rest is displayed by LiquidSkin (Top DHTML Nav, Top Sub Nav for pages and subcommunities, Left Nav, and buttons for quick functionnality access) &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;What's under the hood?&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;I spared you the technical part ... until now. But dont worry, it is not that complex. Basically, to add component to a view, or edit component properties, or delete components from a view, you have to edit the &amp;quot;LiquidSkin.xml&amp;quot; that is located in your image server, within the LiquidSkin folder (ptimages\imageserver\plumtree\portal\custom\LiquidSkin\&amp;lt;your liquid skin name&amp;gt;\)&lt;/p&gt;  &lt;p&gt;After you edited that file, the Liquid Skin timer task that runs every X seconds (you specify the reload interval in the same Liquidskin.xml file) will reload the file in the portal memory, which will make your changes visible on the screen.&lt;/p&gt;  &lt;p&gt;To give you a basic idea, this Liquidskin.xml configuration file is similar to the following:&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh6.ggpht.com/fabiensanglier/SI-yqErmSAI/AAAAAAAAAB4/nMiFJHtLOg4/s1600-h/LiquidSkinXml%5B4%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="430" alt="LiquidSkinXml" src="http://lh3.ggpht.com/fabiensanglier/SI-yrYZOJYI/AAAAAAAAAB8/MFQJ7b_yY2Q/LiquidSkinXml_thumb%5B2%5D.jpg?imgmax=800" width="701" border="0" /&gt;&lt;/a&gt;     &lt;br /&gt;    &lt;br /&gt;As you can see, nothing fancy: Just a well formatted XML that contains all the views you want to use, all the components that you want to add in each view, and all the parameters for each components... &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;But how do I link my portal experience to the liquidskin??&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You just have to specify in the property attached to your portal experience definition the name of the LiquidSkin you are developping. (see below). This name will correspond to the liquid skin that is one your image server, at the foloowing path: ptimages\imageserver\plumtree\portal\custom\LiquidSkin\&lt;strong&gt;&amp;lt;your liquid skin name&amp;gt;&lt;/strong&gt;\LiquidSkin.xml&amp;#160; &lt;br /&gt;    &lt;br /&gt; &lt;a href="http://lh4.ggpht.com/fabiensanglier/SI-ysAu4OQI/AAAAAAAAACA/bsSXRznSacE/s1600-h/ExpDefinition%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="285" alt="ExpDefinition" src="http://lh5.ggpht.com/fabiensanglier/SI-ysh4D0YI/AAAAAAAAACE/mM23EjSre-4/ExpDefinition_thumb%5B1%5D.jpg?imgmax=800" width="535" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Final Words&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Even though this component offers great flexibility and a fairly long number of components to use, the real challenge will be to build the LiquidSkin.xml file, which requires a good knowledge of all the components available to you (and how they works), as well as a fairly good understanding of tableless HTML (every thing is DIV-based) and Cascading Style Sheets. Nothing hard for a seasoned web-designer :)&lt;/p&gt;  &lt;p&gt;So long...see you next time to talk about how easy it is to install that component!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-3371930708564528613?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=A04ouFGRWkQ:v6FHFRMDb8E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=A04ouFGRWkQ:v6FHFRMDb8E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=A04ouFGRWkQ:v6FHFRMDb8E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=A04ouFGRWkQ:v6FHFRMDb8E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/A04ouFGRWkQ/overview-of-bea-alui-liquidskin-part-1.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/10/overview-of-bea-alui-liquidskin-part-1.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2976473844390099876.post-2426028560751843157</guid><pubDate>Sat, 27 Oct 2007 04:06:00 +0000</pubDate><atom:updated>2008-06-12T00:07:22.790-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Product Overview</category><category domain="http://www.blogger.com/atom/ns#">ALUI Liquidskin</category><category domain="http://www.blogger.com/atom/ns#">ALUI Portal</category><title>Overview of BEA ALUI LiquidSkin: Part 2</title><description>&lt;p&gt;In my previous post &amp;quot;Overview of BEA ALUI Liquidskin&amp;quot;, I talked about the great features that this offering provides. Now I want to talk about the installation of the component.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;But first, I might not have been clear on my previous post: The LiquidSkin engine is running on the portal server, NOT on the image server. On the ALUI image server(s), you will find the different configuration files (all called LiquidSkin.xml in their own folder) that contains the settings for each skin in the various portal experience definitions. The xml files on the image server are of course not accessed every time a page is displayed, but loaded in the portal memory at specific intervals (very similar to Varpacks loading for those of you who are familiar with Varpacks).&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;LiquidSkin&lt;/strong&gt; comes in 2 flavors: .NET or Java (like the portal). Depending on the portal you are running, you will chose the appropriate version.&lt;/p&gt;  &lt;p&gt;For .NET, those are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;LiquidSkin.dll (core LiquidSkin code that contains the base classes and the&amp;#160; various utility classes) &lt;/li&gt;    &lt;li&gt;LiquidSkinComponents.dll (contains the majority of Liquidskin components, i.e. LeftNavigation, Breadcrumb, Links, etc... Each of those components extends a base class defined in the core LiquidSkin.dll) &lt;/li&gt;    &lt;li&gt;LiquidSkinImpersonate.dll (optional component -for security purpose- that allows an administrator to impersonate any user in the portal. When activated, the administrator is logged in the portal as that user.) &lt;/li&gt;    &lt;li&gt;LiquidSkinFilteredCommunities.dll (optional component that creates a list of &amp;quot;My Community&amp;quot; links which are filtered to include and/or exclude certain 'types' of communities. A community 'type' is defined by a combination of property values associated with the community. Note: &lt;strong&gt;Expensive process. Enable Caching.)&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For Java, you just replace dll with jar for the names.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Installation Steps:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It is said in the documentation that it should not take more than 30 minutes to install Liquidskin. This is TRUE!&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Stopping/Starting portal server(s) &lt;/li&gt;    &lt;li&gt;Copying a the jar/dll files to each portal server &lt;/li&gt;    &lt;li&gt;Editing the CustomActivitySpaces.xml and portalconfig.xml files on each portal server &lt;/li&gt;    &lt;li&gt;Copying the skin folders to each image server &lt;/li&gt;    &lt;li&gt;Importing a .pte file to create the custom properties used by LiquidSkin &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Jar / Dll Installation&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In order to install those jars / dlls in your portal, you just need to put them in the library folders of the portal installation, as well as in the portal web application itself.&lt;/p&gt;  &lt;p&gt;Thus, you need to copy them in &lt;strong&gt;&lt;em&gt;&amp;lt;pt_home&amp;gt;/ptportal/6.0/lib&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;And in the portal web application (method differs slightly between .NET and Java)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;For .NET,&lt;/strong&gt; it is easy since the portal application is not packaged in an archive, as it is for java. Thus, you just need to copy all the dlls in the &lt;em&gt;&lt;strong&gt;&amp;lt;pt_home&amp;gt;/ptportal/6.0/webapp/portal/web/bin&lt;/strong&gt;&lt;/em&gt; folder.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;For Java&lt;/strong&gt;, you will need to explode the portal.war and copy the LiquidSkin Jars in the newly exploded folder &lt;strong&gt;&lt;em&gt;WEB-INF\lib\.&lt;/em&gt;&lt;/strong&gt; Then, just repackage the portal.war and update the portal.ear.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Little Reminder for Jar operations:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Exploding the war: &lt;strong&gt;jar -xvf portal.war&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Repacking the new war:&lt;strong&gt; jar -cvf portal.war *&lt;/strong&gt; (to be done at the root of what you want to package) &lt;/li&gt;    &lt;li&gt;Update the ear: &lt;strong&gt;jar -uvf portal.ear portal.war&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Portal Configuration&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;To enable the LiquidSkin pluggable navigation, you must edit the &amp;quot;&amp;lt;PORTAL_HOME&amp;gt;\settings\portal\CustomActivitySpaces.xml&amp;quot; file and add in it the LiquidSkin libraries:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;AppLibFiles&amp;gt;      &lt;br /&gt;&amp;lt;libfile name=&amp;quot;LiquidSkin&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;lt;libfile name=&amp;quot;LiquidSkinComponents&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;lt;/AppLibFiles&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Portal Object Import&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You must import the PTE package that contains 2 properties:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;quot;NavConfigFolder&amp;quot; property: This is attached (Global Object Property Map) to experience definition objects. You will save in that property the name of the liquidskin that corresponds to the experience definition you want &amp;quot;LiquidSkin enabled&amp;quot; &lt;/li&gt;    &lt;li&gt;&amp;quot;Subcommunity Display Order&amp;quot; is attached (Global Object Property Map) to the community objects. This is to allow custom sorting of communities within the Top or Left navigation components. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Optional: Modify margins and view width&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;As any other portal navigation. it is possible to change margins and view width in the PortalConfig.xml (section &amp;quot;portal:Navigation&amp;quot;). The only thing you need to know is that the the id of the LiquidSkin navigation framework is 71. This ID is to be appended to the navigation properties so that you can get for example a specific left navigation column width.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;Finally, restart the web application server that host the portal. DONE!! In 18min 32 seconds!! See I did not lie :)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2976473844390099876-2426028560751843157?l=fsanglier.blogspot.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=uTtPWyjfvCk:AbfppRk6_a8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=uTtPWyjfvCk:AbfppRk6_a8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/fsanglier/alui?a=uTtPWyjfvCk:AbfppRk6_a8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/fsanglier/alui?i=uTtPWyjfvCk:AbfppRk6_a8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/fsanglier/alui/~3/uTtPWyjfvCk/overview-of-bea-alui-liquidskin-part-2.html</link><author>noreply@blogger.com (Fabien Sanglier)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fsanglier.blogspot.com/2007/10/overview-of-bea-alui-liquidskin-part-2.html</feedburner:origLink></item></channel></rss>
