2 Replies Latest reply on Sep 14, 2009 10:53 AM by ebephil

    How to obtain the current portlet instance?

    ebephil

      Hi,

      as the title says, I am looking for a way to get the current org.jboss.portal.core.model.instance.Instance from within a portlet.

      The goal is to store preferences on instance level (in the EDIT mode for example). By digging through the Admin portlet I figured out how to do that. What I could not figure out however is how to obtain the current instance to perform the setProperties() call on. The admin portlet iterates a list of all instances, while I just want to edit the current instance of the portlet.

      Currently, I am deriving the name of the instance from the window name, but that's just an ugly hack as it only works if portlet instances are created in a certain way (that is, if their name ends with 'Instance').

      I did find some posts regarding instance preferences, but none of them seemed to answer my question.

      I am aware that this is outside the scope of the JSR-168 spec and internal JBoss APIs could change at any time.

      I am using JBoss Portal 2.7.2 on top of JBoss 4.2.3, using PortletBridge 1.0.0.CR2 RichFaces 3.3.1.

      Thanks in advance
      Phil

      PS: I attached my existing code, maybe it helps clarifying my problem. My main concern is the getCurrentInstance() method.

       // This is the part I am trying to implement properly
       private Instance getCurrentInstance() {
       PortalNodeImpl currentNode = Navigation.getCurrentNode();
       Navigation.getPortalRuntimeContext().
       return getInstanceContainer().getDefinition(
       currentNode.getName().replaceAll("Window", "Instance"));
       }
      
       // this works perfectly fine, at least when used with the right portlet instance
       public boolean writePref(String prefKey, String newPrefValue) {
       Instance currentInstance = getCurrentInstance();
       if (null == currentInstance) {
       logger.error("<-- writePref() Current Instance is null, stopping.");
       return false;
       }
       try {
       List<PropertyChange> changeList = new ArrayList<PropertyChange>();
       PropertyChange change = PropertyChange.newUpdate(prefKey,
       newPrefValue);
       changeList.add(change);
       PropertyChange[] changeArray = changeList
       .toArray(new PropertyChange[changeList.size()]);
       logger.info("--> save()", " setting properties");
       currentInstance.setProperties(changeArray);
       } catch (PortletInvokerException e) {
       logger.error(e.toString());
       return false;
       } catch (Exception e) {
       logger.error(e.toString());
       return false;
       } catch (Throwable t) {
       logger.error(t.toString());
       return false;
       }
       return true;
       }
      


        • 1. Re: How to obtain the current portlet instance?
          ebephil

          I improved my guessing, but it's still just a guess. As long as administrators can enter custom window names (and I don't want to modify the admin portlet) I would have to show an Instance selection dialogue whenever my getCurrentInstance() fails.

          Any ideas anyone?

          • 2. Re: How to obtain the current portlet instance?
            ebephil

            It took more two afternoons, but I found a solution.

            The trick is to use the PortalObjectContainer to obtain the current PortalObject from the current PortalNode.

            Anyway, here's my code:

             private Instance getCurrentInstance() {
             PortalNodeImpl node = Navigation.getCurrentNode();
             if (node.getType() != PortalNode.TYPE_WINDOW) {
             return null;
             }
             PortalObjectId id = node.getObjectId();
             Window window = (Window) getPortalObjectContainer().getObject(id);
             PortletContent pc = (PortletContent) window.getContent();
             return getInstanceContainer().getDefinition(pc.getInstanceRef());
             }
            
             @Override
             public boolean writePref(String prefKey, String newPrefValue) {
             Instance currentInstance = getCurrentInstance();
            
             if (null == currentInstance) {
             logger.error("<-- writePref() Current Instance is null, stopping.");
             return false;
             }
            
             try {
             List<PropertyChange> changeList = new ArrayList<PropertyChange>();
             PropertyChange change = PropertyChange.newUpdate(prefKey,
             newPrefValue);
             changeList.add(change);
            
             PropertyChange[] changeArray = changeList
             .toArray(new PropertyChange[changeList.size()]);
            
             logger.info("--> save()", " setting properties");
             currentInstance.setProperties(changeArray);
            
             } catch (PortletInvokerException e) {
             logger.error(e.toString());
             return false;
             } catch (Exception e) {
             logger.error(e.toString());
             return false;
             } catch (Throwable t) {
             logger.error(t.toString());
             return false;
             }
            
             return true;
             }
            


            You need to inject the InstanceContainer and PortalObjectContainer via the jboss-portlet.xml:

            <portlet-app>
            ...
             <service>
             <service-name>PortalObjectContainer</service-name>
             <service-class>org.jboss.portal.core.model.portal.PortalObjectContainer</service-class>
             <service-ref>portal:container=PortalObject</service-ref>
             </service>
             <service>
             <service-name>InstanceContainer</service-name>
             <service-class>org.jboss.portal.core.model.instance.InstanceContainer</service-class>
             <service-ref>:container=Instance</service-ref>
             </service>
            ...
            </portlet-app>
            


            Then you can access them in your beans, I do it by injecting them via faces-config.xml:
            <faces-config>
            ...
             <managed-bean>
             <managed-bean-name>portletPreferencesHelper</managed-bean-name>
             <managed-bean-class>package.foo.PortletPreferencesHelperJBossImpl</managed-bean-class>
             <managed-bean-scope>session</managed-bean-scope>
             <managed-property>
             <property-name>instanceContainer</property-name>
             <value>#{applicationScope.InstanceContainer}</value>
             </managed-property>
             <managed-property>
             <property-name>portalObjectContainer</property-name>
             <value>#{applicationScope.PortalObjectContainer}</value>
             </managed-property>
             </managed-bean>
            ...
            </faces-config>
            


            And now I finally have InstancePreferences capsuled in a Bean. Btw: Reading the PortletPreferences works the usual way. As I never write user-level PortletPreferences, the Portal always falls back to the InstancePreferences.