Showing posts with label Portlet. Show all posts
Showing posts with label Portlet. Show all posts

Inspecting or Troubleshooting with portlet preferences stored in different modes



Extracting different types of Portlet Preferences

1.       Personal or User Level (Edit Mode) preferences : Preferences set in the edit mode is called user level preferences. These preferences are scope to only that particular instance of portlet (If same page has more than one instance of this portlet, each instance will their own copy) .   You can view all user level preferences in page XMLAccess export.

                       <portletinstance action="update" domain="rel" objectid="Z5_SIB0OKE1GON2E0IT6I9LS520O5" portletref="Z3_SIB0OKE1GON2E0IT6I9LS52084"/>
                        <portletinstance action="update" domain="cust" objectid="Z5_SIB0OKE1GON2E0IT6I9LS520O3" owner="uid=wpsadmin,o=defaultWIMFileBasedRealm" parentref="Z5_SIB0OKE1GON2E0IT6I9LS520O5" portletref="Z3_SIB0OKE1GON2E0IT6I9LS52084">
                            <preferences name=".SivaPortletEditKey" update="set">
                                <value><![CDATA[TestEditPreference]]></value>
                            </preferences>
                        </portletinstance>

NOTE:  domain=”cust” indicates that these preferences will go to the customization schema  (that is where all user customizations stored). Actucal portlet instance related will go the release schema (that is all portal resources gets stored).

2.       Shared (Edit Defaults Mode) Preferences : Preferences set in the “Edit Defaults” mode is applicable only for this instances of the portlet for all users. You can get these preferences also from the page XMLAccess export.

                        <portletinstance action="update" domain="rel" objectid="Z5_AAAAA" portletref="Z3_SIB0OKE1GON2E0IT6I9LS52084">
                            <preferences name=".SivaPortletEditDefaultsKey" update="set">
                                <value><![CDATA[TestSharedPreference]]></value>
                            </preferences>
                        </portletinstance>

Note: Above sample XML snippet contains shared preference that gets stored in the release schema. These preferences are not associated with any owner as user level preferences.  
There are scenarios where you may see same preference key  in the user level and also at the edit shared preferences (Ex: like No.of results to display portlet…etc . Requirements like Editors should able set default value for this instance (for all users) and let end users to configured their preferred number).   Sample page XMLAcess  export will look like below.

                        <portletinstance action="update" domain="rel" objectid="Z5_SIB0OKE1GON2E0IT6I9LS520O5" portletref="Z3_SIB0OKE1GON2E0IT6I9LS52084">
                            <preferences name="Common-Pref-Key" update="set">
                                <value><![CDATA[TestSharedPreference]]></value>
                            </preferences>
                        </portletinstance>
                        <portletinstance action="update" domain="cust" objectid="Z5_SIB0OKE1GON2E0IT6I9LS520O3" owner="uid=wpsadmin,o=defaultWIMFileBasedRealm" parentref="Z5_SIB0OKE1GON2E0IT6I9LS520O5" portletref="Z3_SIB0OKE1GON2E0IT6I9LS52084">
                            <preferences name="Common-Pref-Key" update="set">
                                <value><![CDATA[TestEditPreference]]></value>
                            </preferences>
                        </portletinstance>



3.       Global or Admin (Config Mode) Preferences :  Preferences set in the “Config” mode is applicable to all instances of this portlet on all pages for all users . As these preferences are not specific to any page,  we can’t retrieve them using page XMLAccess export.   You can retrieve these preferences from the portlet XMLAccess export.

<portlet action="update" active="true" defaultlocale="en" domain="rel" name="SivaPortlet" objectid="Z3_SIB0OKE1GON2E0IT6I9LS52084" provided="false" servletref="ZV_SIB0OKE1GON2E0IT6I9LS52080">
                    <preferences name=".SivaPortletConfigKey" update="set">
                        <value><![CDATA[TestConfigPreference]]></value>
                    </preferences>
                    <access-control externalized="false" owner="uid=wpsadmin,o=defaultwimfilebasedrealm" private="false"/>
                </portlet>

                Another way of inspecting these admin level preferences is using the portal admin console --> portlets -->configure

               



Resources

Writing Custom Portlet Mode in WebSphere Portal



Steps
a.  Override generic portlet Dispatch method

private static final PortletMode CUSTOM_CONFIG_MODE = new PortletMode("config");
private static final PortletMode CUSTOM_EDIT_DEFAULTS_MODE = new PortletMode("edit_defaults");

protected void doDispatch(RenderRequest request, RenderResponse response) throws PortletException, IOException {
              if (!WindowState.MINIMIZED.equals(request.getWindowState())){
                     PortletMode mode = request.getPortletMode();                 
                     if (CUSTOM_CONFIG_MODE.equals(mode)) {
                           doCustomConfigure(request, response);
                           return;
                     }
                     else if (CUSTOM_EDIT_DEFAULTS_MODE.equals(mode)) {
                           doCustomEditDefaults(request, response);
                           return;
                     }
              }
              super.doDispatch(request, response);
       }

b. Add following in the portlet.xml

<custom-portlet-mode>
            <portlet-mode>config</portlet-mode>
      </custom-portlet-mode>
      <custom-portlet-mode>
            <portlet-mode>edit_defaults</portlet-mode>
</custom-portlet-mode>

Add following entries under the portlet tag
<supports>
      <portlet-mode>config</portlet-mode>
      <portlet-mode>edit_defaults</portlet-mode>
</supports>

Note: If a custom portlet mode defined in the deployment descriptor is not mapped to a custom portlet mode provided by WebSphere Portal, portlets must not be invoked in that portlet mode.  Ex: you can not create like "resize" mode for the portlet that deployed in websphere as websphere doesn't support it.

JSR 286 Content Viewer Portlet vs IBM Content Viewer Portlet(till 6.0)

This Article describes differences between the IBM Content Viewer and JSR 286 version of Content viewer


IBM Content Viewer Portlet (till 6.0.1)
In the IBM Portlet API version of the viewer, you can simply add a query parameter to a URL addressing the page and all the IBM portlets on that page received that parameter. You then configured the portlet to listen to broadcasts and created a URL in the format:
http://[PORTAL_HOST]/[PORTAL_CONTEXT_ROOT]/[PORTAL_PAGE_URL_MAPPING]
/?WCM_GLOBAL_CONTEXT=<pathCmpnt type="noprefixservlet" />/[LIBRARY]/[SITE]
/[SITE_AREA_PATH]/[CONTENT]
 
http://mysystent/wps/portal/home?WCM_GOBAL_CONTEXT=/mynewslib/usnews/news1.
 
This portlet is simple to use, but it has the following drawbacks:
  • Since the parameter is not maintained in the URL, it needs to be stored in the session (even in the case of anonymous use) and therefore impacts portal server memory consumption.
  • Once you’ve interacted with the page and the parameter is no longer in the URL -- but stored in the session -- you can no longer bookmark your selection.
  • For static pages, caching in the browser doesn’t work because the selection is not encoded into the URL. This means the browser can’t distinguish between news item 1 and news item 2 and therefore cannot cache on the browser level.
The query parameter solution of the old IBM Portlet API has two disadvantages:
  • You only get the parameter for one request; after that each portlet on the page needs to store the value in the session. This requires having sessions even in the case of anonymous use.
  • You don't know what parameter a portlet understands, as the portlets don’t formally declare this. You can even run in a situation where two portlets define the same parameter name, but with different semantics that would prevent you from putting these two portlets onto the same page, and you wouldn’t know this beforehand.
JSR 286 Content Viewer Portlet


The Java Portlet Specification V 2.0 (JSR 286) defines something called a render parameter that is provided to the portlets for each request. For example, when the user presses the browser's reload button, the portlet gets the same render parameters again and can render the same view. This means that the portlet does not need to store this navigational state information in the session any longer

The fully qualified name of the public render parameter that is supported by the JSR 286 Web content viewer is http://www.ibm.com/xmlns/prod/datatype/content:context
Because you might have many public and private render parameters that you need to store in the URL, you need to make sure that the URLs don't get too long. WebSphere Portal does this by zip-encoding that part of the URL

If a specific parameter gets too large, it is stored in the session and only the reference key is stored in the URL. This helps to keep the URL below the 2K size limit enforced by many browsers or other HTTP infrastructure components, such as proxies.
The disadvantage of this solution is that you are now no longer able to create these parameters by hand because of the encoding. Therefore, Portal provides you with the above mechanism of adding a simple URI at the end of a portal URL


Reset WCM_GLOBAL_CONTEXT when switching portal pages


JSR-286 based Web Content Viewer portlet does not make use of the WCM_GLOBAL_CONTEXT query parameter but instead uses a public render parameter as defined by the portlet standard to holds its context information. By default all public render parameters are shared across pages in Portal.

So what happens is that when you select the link to the item on the first page a public render parameter is set that basically tells the JSR-286 Web Content Viewer portlet, that was configured to listen to broadcast links from other portlets, to renders the content item that was set in the public render parameter. When you then switch to the next page all public render parameter are maintained and also available on the second page. Thus the web content viewer on the second page renders the content item set in the public render parameter.

To solve this you can either:
  • Set the parameter "param.sharing.scope" on both pages to a unique value. This parameter is documented here http://publib.boulder.ibm.com/infocenter/wpdoc/v6r1/topic/com.ibm.wp.ent.doc_v6101/dev/pltcom_pubrndrprm.html and controls how public render parameter for JSR portlet are scope. To have a unique scoping simply set the value of this parameter to any arbitrary but unique value.
  • Use web content pages instead of "normal" portal pages. As for web content pages the param.sharing.scope parameter is set to a unique value automatically during page creation
Note: 
If you want reset all render state(private or public render parameter) of all JSR portlets when selecting page from navigation links(generated from theme) with use of the following
<portal-navigation:urlGeneration keepNavigationalState="false"> 

Click Here( Infocenter) to see more details on JSP tag 



URI Resolver Framework 

In the newer JSR 286 viewer, you use the URI resolver framework in WebSphere Portal to address pages and content items from external systems. The URI resolver framework is a generic resolver framework that can also be leveraged for custom URI schemes. Web Content Management defines the schema wcm: as follows:
wcm:path:LIBRARY/SITE_AREA_PATH/CONTENT [[& page=unique_name | object_id] &mapping=mapping | &current=true]

means that you provide the path to the content and then optionally provide one of the following:
  • A target page, using either the unique name of the page or its object ID.
  • A URL mapping.
  • The current page selected in the URL to use before the URI.
If you don't provide any of the above, WebSphere Portal automatically tries to find the right page. This works only if you’re using the Web Content Pages, where you map a Web Content Management site area to a portal page so that WebSphere Portal is aware of the relationship.
So, how do you get a complete URL now? You have a couple of different options:
  • Address the WebSphere Portal resolver framework directly via /wps/poc or /wps/mypoc.
  • Use any URL for WebSphere Portal that is known by the external application.
Following are some sample URLs:
  • Addressing the portal resolver framework directly:
http://host_name/wps/mypoc?urile=wcm%3Apath%3A/Web+Content/NewsUS/News1
This URL tells the portal to render the content item with the library path Web Content/NewsUS/News1. WebSphere Portal will look up the Web Content Page that is mapped to the NewsUS site area (Company News/US), redirect to that page, and set the context of that page to the content item library path.
  • http://host_name/wps/mypoc?urile=wcm%3Apath%3A/Web+Content/NewsUS/News1&mapping=/coolCars
This URL tells WebSphere Portal to render the content item the same way as the previous URL, but instead of doing the dynamic page look-up to do a redirect to the page /Products/Cars, which is mapped to the URL /coolCars

The complete syntax of these kind URL's is:
/wps/[my]poc[/vp]?urile=wcm:path:[path to WCM content][&page=[unique name or ID] | &mapping=[url mapping] | &current=true]
  • poc for un-authenticated access
  • mypoc for authenticated access
  • To address a virtual portal append the VP mapping. E.g.:
    /wps/mypoc/myvp
    /wps/poc/myvp
  • Alternatively to using the poc servlet you can also append the "urile" parameter on any Portal URL including URL that contain URL mappings e.g to address a specific portal page defined by the url mapping use /wps/[my]portal[/url mapping]?current=true&urile=wcm:path:[path to WCM content]
  • To address a specific portal page use one of the following parameters exclusively:
    • page=unique name or ID of page
    • mapping=url mapping label
    • current=true (To stay on the current page)
  • To leverage dynamic WCM page lookup: ommit any page parameter

There must be at least one JSR 286 web content viewer portlet on the target page and it must be configured to receive links from Other portlets and this portlet,

Note: You actually have two choices: you can specify "uri" or "urile." The difference is that if you use the uri scheme, you need to follow the URI encoding rules in addition the URL encoding rules, so the URL:
http://host_name/wps/portal/Company+News/NewsEurope?urile=wcm%3Apath%3A/Web+Content/NewsUS/News2&current=true

would look like this using the "uri" scheme:
http://host_name/wps/portal/Company+News/NewsEurope?uri=wcm%253Apath%253A%2FWeb%2BContent%2FNewsUS%2FNews2%26current%3Dtrue



Dynamic Portlet Title - Websphere Portal

There are two known alternatives to support dynamic titles in websphere portal.

First, the portlet content can be buffered into a stored response; then you can first transfer the title to the portal page output stream before the portlet response. This buffering solution has a big performance impact because all portlet content needs to be kept in memory for later access and once again transferred to the response from the buffer. Because of this performance impact, WebSphere Portal does not use this design for dynamic titles.


The second alternative is to use JavaScript, along with streaming (instead of buffering). JavaScript is browser-specific and is often seen as security risk; for this reason (and others) JavaScript is sometimes not accepted by some enterprises. However, if you can use JavaScript you can write the title to the output stream and replace it later in the browser. There is no noticeable performance impact. This solution is the recommended way to add dynamic title support with WebSphere Portal V6.

Beginning with Version 6 of WebSphere Portal, when a title is set by RenderResponse.setTitle(String title), it is transferred to the request attribute, com.ibm.portal.portlet.Constants.DYNAMIC_TITLE. Therefore, the dynamic title is available after the portlet content has been rendered using the portal tag portletRender. The skin JSP can access the portlet title (set by the portlet during run time), as soon as the portlet has finished rendering, using the DYNAMIC_TITLE request attribute.


Important: This attribute is not scoped by portlet; therefore, the title is lost as soon as the next portlet is rendered


Steps below explains to enable dynamic portlet titles using JavaScript

Step 1:  To enable the static title to be replaced later, the title needs to be marked within the portlet skin using the HTML elements <span> or <div>. The element must be uniquely identifiable by using the id attribute because it might appear multiple times on a portal page.



Step 2: Search for the portletTitle tag in your portlet skin that retrieves the static portlet title, and surround it with a span element as shown here.

<span id="title.<portal-skin:portletID/>">
<portal-fmt:portletTitle>
<portal-fmt:problem bundle="nls.problem"/>
</portal-fmt:portletTitle>
</span>

Step 3: At the end of the portlet skin, you can retrieve the title that was dynamically set during portlet rendering to replace this spanned static title fragment. You can use the DYNAMIC_TITLE request attribute to acces the dynamic title

script type="text/javascript">
var dynamicTitle =
"<%=request.getAttribute(com.ibm.portal.portlet.Constants.DYNAMIC_TITLE)%>";
var titleElement =
document.getElementById("title.<portal-skin:portletID/>");
if (titleElement != null) {
if (dynamicTitle != "" && dynamicTitle != "null")
titleElement.innerHTML = dynamicTitle;
}
</script>

Click here for additional resources

Accessing User Info in Portlets (PUMA API)

There are two ways you can access the user info in portlets,

1. Using PUMA API provided by websphere portal
2. By stetting the user attributes in portlet.xml

Approach 1:
a  Sample code to access the PUMA through portlet service
import com.ibm.portal.portlet.service.PortletServiceHome;
import com.ibm.portal.um.*;
import com.ibm.portal.um.exceptions.PumaException;
import com.ibm.portal.puma.User;
Context ctx=null;
Object homeObj=null;
User user=null;
try {
ctx = new InitialContext();
homeObj=ctx.lookup("portletservice/com.ibm.portal.um.portletservice.PumaHome");
PortletServiceHome serviceHome=(PortletServiceHome)homeObj;
PumaHome pHome =(PumaHome) serviceHome.getPortletService(PumaHome.class);
PumaProfile pProf=pHome.getProfile();
user=(User)pProf.getCurrentUser();
} catch (NamingException e) {
} catch (PumaException e) {
}

request.setAttribute("user", user.getObjectID());

b Accessing user attributes

//after you got the pumaHome like above
List attributeList=new ArrayList();
attributeList.add(“sn”);
attributeList.add(“givenName”);
attributeList.add(“uid”);
attributeList.add(“preferredLanguage”);

UserProfile profile=pumaHome.getProfile(portletRequest);
User user=profile.getCurrentUser();
Map attributesMap=profile.getAttributes(user,attributeList);

PrintWriter out=response.getWriter();
out.write(“Distinguished name is”+profile.getUserIdentifier(user));

for(Iterator itr=attributesMap.getKeySet().Iterator(); itr.hasNext();){
String attributeName=(String)itr.next();
String attributeValue=(String)attributesMap.get(attributeName);
}

c Using PUMA Locator
i To find user by attributes

PumaLocator locator= pumaHome.getLocator(portletRequest);
PumaProfile profile= pumaHome.getProfile(portletRequest);
List userList=locator.findUserByAttribute(“uid”, “sivavaka”);

User user=(User)userList[0];
Map attributesMap=profile.getAttributes(user,attributeList);//use above attributeList

ii To find user by distinguished name
PumaLocator locator= pumaHome.getLocator(portletRequest);
PumaProfile profile= pumaHome.getProfile(portletRequest);
List userList=locator.findUserByIdentifier(“uid=wasadmin,o=default”);

Approach 2:
Portal can access USER INFO in jsr168 portlet
a Add following elements in the portlet.xml
<user-attribute>
<description xml:lang="en">User Given Name</description>
<name>user.name.given</name>
</user-attribute>
<user-attribute>
<description xml:lang="en">User Last name</description>
<name>user.name.family</name>
</user-attribute>

b Write the following in portlet

Map userInfo=(Map)request.getAttribute(PortletRequest.USER_INFO);
if(userInfo != null){
String givenName = (String)userInfo.get("user.name.given");
String lastName =(String)userInfo.get("user.name.family");
response.getWriter().println("Hello " + givenName +" " + lastName);
}

Portlet Process Action is not gettnig called

Problem Description : Process Action of portlet is not getting called when clicked on the WPS link (action link generated using wps:urlgenration or portlet:action) it don’t call the processAction second time

Promblem Cause: Portal will call processAction only once using the url (i.e reasonable)  . For example if we have link that is action url and opening in new window , then only first time it will call the processAction and portal will mark that link as dirty as we have called processAction using that method once. ( If we are opening page in same window then there is no way you can call the processAction second time). It is expected behavior

Solution:

Use the doview or render URL instead or copy the following in portlet.xml

                      <init-param>
                      <name>wps.multiple.action.execution</name>
                      <value>true</value>
                      </init-param>