5 Replies Latest reply on Jan 31, 2008 8:05 AM by Antoine Herzog

    Clear/reset render parameters or re-initialise all portlets

    Allan Dewar Newbie

      Hi there

      I would like to know if it is possible to clear the render parameters of each portlet on a page such that the view rendered for each portlet is that of their initial state when the user first logged in the portal.

      The reason I would like to do this is a user is able to change his or her context within our application after which all portlets need to be shown in their initial state. We could check for this event or change in context when rendering each and every portlet we create within our application, but if it is at all possible to reset the render parameters ( reinitialise) all portlets in the container this would be the preferred solution.

      Any help or guidance would be much appreciated.

      Thanks

      Allan

        • 1. Re: Clear/reset render parameters or re-initialise all portl
          Allan Dewar Newbie

          Just to clarify further:

          When the user changes context, it is in the action phase of the context selector that I would imagine I wouldhave to use one of the JBoss apis to re-initialise all the portlets in the portal.

          • 2. Re: Clear/reset render parameters or re-initialise all portl
            Antoine Herzog Master

            Hi,

            in the JSR-168, the portlets of a portal are not supposed to know what the other portlets are doing...

            so, this cannot be done with the jboss portal (or any) that is compliant with jsr 168.

            well, you can go further than the jsr.

            looking at the api of jboss portal may be a way.
            but looks to me quite tricky... as you must be sure not to disturb the whole mechanism, and it may be a problem when you upgrade etc...

            you can do it with some communication between portlets of a portal : IPC (Inter Portlet Communication).
            with this, you modify things only at the portlet level : you don't modify the inner engine...

            IPC is planned for version 2 of the jsr.
            some things have been done yet in jboss portal and in some add on libraries.

            so, the way I would do that :
            - set some IPC (Inter Portlet Communication) between the selector portlet and the portlets that need to reset their state and render the new state.
            - in the action phase of the portlet, send a message to the involved portlets, so they re-initialize their state
            - in their render phase, the catch the message, and reset the parameter (that is where you are out of the jsr : this kind of thing should be done only in the action phase of the portlet... )
            - then they will render, with the new state definition.
            - also, think to clear the cache
            - be aware that with ajax feature, the whole page rendering is not triggered, that is some portlet rendering is not triggered (with JB Portal 2.6 and pages/portlets with ajax feature...like the dashboard, etc...)

            about the IPC :
            You need IPC "by message", and not by triggering an event.
            You need to dispatch the signal to several portlets, so message can do that, and as far as I remember, event cannot (only one portlet for destination).

            I don't know how far the JB Portal is now about IPC.
            look at the samples (version 2.6 recommended...).
            for what was in the very begining of it with 2.4, it was some IPC by events.

            look at the Michelle Osmond feature and library :
            http://mus.purplecloud.net/portlets/thesis/ipc.php
            I use it... it is a very good help for IPC (both theory and library).
            It is better to implement your own storage mechanism of messages, but you can still start with the things she provide... (and later make your own strong feature for production reliability).

            look for the posts on this forum about that.

            for the cache :
            It is necessary to keep some cache feature : would be bad for performance to get rid of it in the portlet descriptor.
            so, you have to implement a way to clear the cache of all the portlets.
            I have not done it yet (stand by for this feature in my portal), but I had seen how to do it... it can be done... and not so complicated.
            you must override the cache management JMX service with yours, and add your feature (clear all portlet cache when asked by the selector).
            may be you do that as a contribution to the jboss portal ?
            ask Thomas Heute for advice for that (or may be developper forum).
            I would appreciate... less to do for me...
            idem : look for the posts on this forum on how to manage the cache of portlets.

            ajax features : idem, the ajax features may add some complication if you want all the portlet to be re-rendered with the new state...
            don't know exactly how to manage that... it will depend on your portal and portlets...

            • 3. Re: Clear/reset render parameters or re-initialise all portl
              Allan Dewar Newbie

              Hi Antoine

              Thanks for your post. I must say I'm banging my head against a brick wall on this one.

              Our enviroment is pretty fixed namely: JBoss AS 4.04 and JBoss portal 2.4

              With regards to using IPC as approach:

              I need to notify each of the portlets on the page about the change in context and I'm not sure exactly how to do this. Do you have an example of IPC involving more than two portlets in JBoss Portal 2.4?

              (What complicates matters further for us is most of our application makes use of Springs Portlet MVC framework which uses Springs DispatcherPortlet so all our customer code takes place in spring controllers as opposed to portlets).

              The other approach I have been playing around with (without success) is to
              create an interceptor and add it jboss-portal.sar/META-INF/jboss-service.xml

              The biggest problem I am having with this approach is how the interceptor running in jboss-portal.sar can detect a context change from our portlet application which is running in a separate war file which means we can't share information via the HttpSession.

              There must be mechanisms to achieve this using PortalNodeEvent (or similar).

              Any thoughts on this?

              • 4. Re: Clear/reset render parameters or re-initialise all portl
                Allan Dewar Newbie

                Right, for anybody interested I eventually solved my problem and I don't think for one minute that it's elegant but it does the job.

                EssentiallyI created a custom CommandInterceptor (see code below). The interceptor clears the navigational state of all portlet windows in the portal if there there is an action request to the portlet window called "DNSCustomerContextSelectionPortletWindow". Fortunately in my scenario an action request targetting this portlet window will mean I need to clear the navigational state of all portlet windows in the portal.

                The interceptor needs to be built to a jar file and the jar file placed in :

                /jboss-4.0.4.GA/server/default/deploy/jboss-portal.sar/lib/
                


                The interceptor then needs to be added to the Command interceptor stack defined in
                /jboss-4.0.4.GA/server/default/deploy/jboss-portal.sar/META-INF/jboss-service.xml
                
                


                This is done as follows:

                 <mbean
                 code="com.dns.jboss.portal.interceptor.DNSCustomerContextChangeInterceptor"
                 name="portal:service=Interceptor,type=Command,name=DNSCustomerContextChangeCheck"
                 xmbean-dd=""
                 xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
                 <xmbean/>
                 </mbean>
                
                <mbean
                 code="org.jboss.portal.server.impl.invocation.JBossInterceptorStack"
                 name="portal:service=InterceptorStack,type=Command"
                 xmbean-dd=""
                 xmbean-code="org.jboss.portal.common.system.JBossServiceModelMBean">
                 <xmbean/>
                 <depends-list optional-attribute-name="InterceptorNames">
                 <depends-list-element>portal:service=Interceptor,type=Command,name=PortalNode</depends-list-element>
                 <depends-list-element>portal:service=Interceptor,type=Command,name=PolicyEnforcement</depends-list-element>
                 <depends-list-element>portal:service=Interceptor,type=Command,name=PageNavigation</depends-list-element>
                 <depends-list-element>portal:service=Interceptor,type=Command,name=EventBroadcaster</depends-list-element>
                 <depends-list-element>portal:service=Interceptor,type=Command,name=DNSCustomerContextChangeCheck</depends-list-element>
                 </depends-list>
                 </mbean>
                
                

                
                
                package com.dns.jboss.portal.interceptor;
                
                import java.util.Collection;
                import java.util.Iterator;
                
                import org.apache.log4j.Logger;
                import org.jboss.portal.common.invocation.InvocationException;
                import org.jboss.portal.core.command.CommandInterceptor;
                import org.jboss.portal.core.command.ControllerCommand;
                import org.jboss.portal.core.command.InvokeWindowActionCommand;
                import org.jboss.portal.core.model.portal.Page;
                import org.jboss.portal.core.model.portal.Window;
                import org.jboss.portal.server.ServerInvocation;
                
                
                public class DNSCustomerContextChangeInterceptor extends CommandInterceptor
                {
                 private static final Logger log = Logger.getLogger( DNSCustomerContextChangeInterceptor.class );
                
                 public void invoke( ControllerCommand cmd ) throws Exception, InvocationException
                 {
                 if ( customerContextChange( cmd ) )
                 clearPortalNavigationalState( (InvokeWindowActionCommand)cmd );
                 cmd.invokeNext();
                 }
                
                 private boolean customerContextChange( ControllerCommand command )
                 {
                 if (command instanceof InvokeWindowActionCommand)
                 {
                 InvokeWindowActionCommand iwac = (InvokeWindowActionCommand)command;
                 if ( iwac.getWindow().getName().equals( "DNSCustomerContextSelectionPortletWindow" ) )
                 return true;
                 }
                 return false;
                 }
                
                 private void clearPortalNavigationalState( InvokeWindowActionCommand iwac )
                 {
                 Collection portalChildren = iwac.getPortal().getChildren();
                
                 for( Iterator i = portalChildren.iterator(); i.hasNext(); )
                 {
                 Object portalChild = i.next();
                 if ( portalChild instanceof Page )
                 {
                 Page page = (Page)portalChild;
                 Collection pageChildren = ( (Page) portalChild ).getChildren();
                 for ( Iterator j = pageChildren.iterator(); j.hasNext(); )
                 {
                 Object pageChild = j.next();
                 if ( pageChild instanceof Window )
                 {
                 Window window = (Window)pageChild;
                 if ( !window.equals( iwac.getWindow() ) )
                 {
                 ServerInvocation sinv = iwac.getContext().getExecutionContext().getServerInvocation();
                 log.debug( "CLEARING NAV STATE OF WINDOW: " + window.getName() );
                 sinv.getRequest().getNavigationContext().setNavigationalState(window.getInstanceRef(), null );
                
                 //WindowNavigationalState windowNavState = (WindowNavigationalState)sinv.getRequest().getNavigationContext().getNavigationalState( window.getId() + "_window");
                 //windowNavState = new WindowNavigationalState();
                 //sinv.getRequest().getNavigationContext().setNavigationalState(window.getId() + "_window", windowNavState);
                 }
                 }
                 }
                 }
                 }
                 }
                
                }
                
                


                • 5. Re: Clear/reset render parameters or re-initialise all portl
                  Antoine Herzog Master

                  Yeah !
                  that's great.
                  using the interceptor is nice.
                  just clearing the other portlets navigationnal state is not clean job (JSR is shouting : "don't do that !"... but...).

                  nice example of how to use the interceptors to plug a behavior around the portlets engine and commands...

                  thanks for reporting this solution.

                  about IPC, the global way of doing this is to have a communication mean between the several parts of the application.
                  so they can communicate with each other : the portal pieces (portlets, portal main engine),
                  as well as backoffice application that are behind the portlets.
                  you can use the HttpSession for that, but this is not really meant for this.
                  or you can use some messaging. This is a quite heavy solution, but the most reliable and clean architecture.

                  your solution is enough for this need... so the best...