Portals Bridges
  1. Portals Bridges
  2. PB-84

CCE in PortletWindowUtils.getPortletWindowId

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 1.0
    • Fix Version/s: None
    • Component/s: common
    • Labels:
      None
    • Environment:
      Mac OS, Wicket Portlets, OpenPortal Portlet Container

      Description

      I'm trying to get wicket portlet support working over OpenPortal. I've hacked together implementations of ServletContextProvider and PortletResourceURLFactory - just required exposing WicketFilter from the Application to get the necessary data. I can deploy a portlet, but...

      I'm getting this exception.

      java.lang.ClassCastException: java.lang.Double
      at org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:45)

      Looking at the code, this seems like a clear bug: The method casts to String here:
      (String)session.getAttribute(PORTLET_WINDOW_ID);

      and if null fills in the value with an instance of Double. If it's going to put a Double there, it should probably not expect a String - this exception will occur any time this method is called twice for a PortletSession, it will throw the CCE the second time it is called.

      Since the value is not used, probably simply changing it to
      Object portletWindowId = session.getAttribute(PORTLET_WINDOW_ID);

      would fix it.

      1. portals-bridges-common-1.0.4.jar
        21 kB
        Ate Douma
      2. utils.patch
        5 kB
        Antony Stubbs

        Issue Links

          Activity

          Tim Boudreau created issue -
          Hide
          Ate Douma added a comment - - edited

          The above is an incorrect assessment of how the code works.
          And, although this "issue" has been brought up before, in my view the CCE thrown by OpenPortal (as well as JBoss Portal AFAIK) is a bug in the portlet container, not this method.

          If you look at the rest of following code within this method, you'll notice the random generated Double object put in the session is put in there only for a for a very short time
          and replaced within the same method almost immediately with a String object.

          The whole point of this method is determining what the container provided PORTLET_WINDOW_ID is using a JSR-168 compliant "trick", in that PORTLET_SCOPE session attributes
          are stored within the session using a predefined format which includes the PORTLET_WINDOW_ID (see: JSR-168 spec PLT.15.3).

          For that purpose, a reasonably unique (double) value is generated using Math.random() and stored as a Double value within the session under PORTLET_SCOPE for an internal defined attribute name, "org.apache.portals.bridges.util.portlet_window_id".
          Thereafter, all the APPLICATION_SCOPE attributes are evaluated, looking again for this internal attribute name ("org.apache.portals.bridges.util.portlet_window_id") and (as an extra save guard)
          its value is checked against the previously generated Double value to be sure the correct attribute value (name) is found.

          Then, the temporary Double value is replaced with the real (String type) PORTLET_WINDOW_ID.

          If the portlet container is implemented and behaving compliant to JSR-168, the above routine should work as expected and the temporary Double value should always be replaced again with a String value within the same method.
          Also note: this part of the method is executed within a sychronized block so interference of other requests should not be possible either.

          The fact this method fails (sometimes?) on OpenPortal and JBoss Portal in my view is very suspicious.
          Somehow, the "org.apache.portals.bridges.util.portlet_window_id" attribute stored under PORTLET_SCOPE seems not be found correctly under APPLICATION_SCOPE, in which case this method will return null (this first time).
          Subsequently, the following call to this method will indeed cause a CCE, sure.

          Although I'd like to "fix" this problem, or even use a proper work around if possible, simply using the (obviously a Double) value as an Object won't help here.
          Note: this method is supposed to return a String value and specifically a PORTLET_WINDOW_ID.

          Until it is more clear what goes wrong here and why these portlet containers are not behaving as expected, I have no real solution available.

          Tim, as you're encountering this problem with OpenPortal, it would be great if you could try to determine in more detail what goes on here.
          I've created a modified version of the getPortletWindowId method which will produce some stack trace logging to the console which might tell us more (note: requires Java 1.5):

          public static String getPortletWindowId(PortletSession session)
          {
          System.out.println("getPortletWindowId for session: "session.getId()"(thread: "Thread.currentThread().getId()")");

          String portletWindowId = (String)session.getAttribute(PORTLET_WINDOW_ID);
          if ( portletWindowId == null )
          {
          synchronized (session)
          {
          System.out.println(" no portletWindowId yet - going to derive it. Current thread ("Thread.currentThread().getId()") call stack:");
          for (StackTraceElement st : Thread.currentThread().getStackTrace()) System.out.println(st);
          Double value = new Double(Math.random());
          session.setAttribute(PORTLET_WINDOW_ID, value);
          Enumeration names = session.getAttributeNames(PortletSession.APPLICATION_SCOPE);
          System.out.println(" looking for attribute "PORTLET_WINDOW_ID" in current APPLICATION_SCOPE attributes:");
          while (names.hasMoreElements())
          {
          String name = (String)names.nextElement();
          System.out.println(" found attribute: "+name);
          if (PortletSessionUtil.decodeAttributeName(name).equals(PORTLET_WINDOW_ID) && value.equals(session.getAttribute(name,PortletSession.APPLICATION_SCOPE)) )

          { portletWindowId = name.substring("javax.portlet.p.".length(),name.indexOf('?')); System.out.println(" --> found - PORTLET_WINDOW_ID = "+portletWindowId); session.setAttribute(PORTLET_WINDOW_ID, portletWindowId); break; }

          }
          if (portletWindowId == null) System.out.println(" --> error: failed to derive the portletWindowId");
          }
          }
          return portletWindowId;
          }

          For your convenience I've attached a modified version of the portlet-bridges-common-1.0.4.jar with the above changed method compiled in it (again: using it requires Java 5).

          I've run it myself (on Pluto/Jetspeed-2) which produces the following output (stack trace dump truncated for brevity):

          getPortletWindowId for session: FC9065541BED56975E35C1AD97BAB419(thread: 55)
          no portletWindowId yet - going to derive it. Current thread (55) call stack:
          java.lang.Thread.dumpThreads(Native Method)
          java.lang.Thread.getStackTrace(Thread.java:1383)
          org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:53)
          org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59)
          org.apache.portals.bridges.struts.StrutsPortlet.processRequest(StrutsPortlet.java:420)
          org.apache.portals.bridges.struts.StrutsPortlet.doView(StrutsPortlet.java:301)
          javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:247)
          javax.portlet.GenericPortlet.render(GenericPortlet.java:175)
          org.apache.jetspeed.factory.JetspeedPortletInstance.render(JetspeedPortletInstance.java:103)
          org.apache.jetspeed.container.JetspeedContainerServlet.doGet(JetspeedContainerServlet.java:277)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
          <snip/>
          looking for attribute org.apache.portals.bridges.util.portlet_window_id in current APPLICATION_SCOPE attributes:
          found attribute: javax.portlet.p.jp-2?org.apache.portals.bridges.util.portlet_window_id
          --> found - PORTLET_WINDOW_ID = jp-2

          If you could try the same and provide me with the debug output you get, maybe we can get somewhat further with this problem.

          Ate

          Show
          Ate Douma added a comment - - edited The above is an incorrect assessment of how the code works. And, although this "issue" has been brought up before, in my view the CCE thrown by OpenPortal (as well as JBoss Portal AFAIK) is a bug in the portlet container, not this method. If you look at the rest of following code within this method, you'll notice the random generated Double object put in the session is put in there only for a for a very short time and replaced within the same method almost immediately with a String object. The whole point of this method is determining what the container provided PORTLET_WINDOW_ID is using a JSR-168 compliant "trick", in that PORTLET_SCOPE session attributes are stored within the session using a predefined format which includes the PORTLET_WINDOW_ID (see: JSR-168 spec PLT.15.3). For that purpose, a reasonably unique (double) value is generated using Math.random() and stored as a Double value within the session under PORTLET_SCOPE for an internal defined attribute name, "org.apache.portals.bridges.util.portlet_window_id". Thereafter, all the APPLICATION_SCOPE attributes are evaluated, looking again for this internal attribute name ("org.apache.portals.bridges.util.portlet_window_id") and (as an extra save guard) its value is checked against the previously generated Double value to be sure the correct attribute value (name) is found. Then, the temporary Double value is replaced with the real (String type) PORTLET_WINDOW_ID. If the portlet container is implemented and behaving compliant to JSR-168, the above routine should work as expected and the temporary Double value should always be replaced again with a String value within the same method. Also note: this part of the method is executed within a sychronized block so interference of other requests should not be possible either. The fact this method fails (sometimes?) on OpenPortal and JBoss Portal in my view is very suspicious. Somehow, the "org.apache.portals.bridges.util.portlet_window_id" attribute stored under PORTLET_SCOPE seems not be found correctly under APPLICATION_SCOPE, in which case this method will return null (this first time). Subsequently, the following call to this method will indeed cause a CCE, sure. Although I'd like to "fix" this problem, or even use a proper work around if possible, simply using the (obviously a Double) value as an Object won't help here. Note: this method is supposed to return a String value and specifically a PORTLET_WINDOW_ID. Until it is more clear what goes wrong here and why these portlet containers are not behaving as expected, I have no real solution available. Tim, as you're encountering this problem with OpenPortal, it would be great if you could try to determine in more detail what goes on here. I've created a modified version of the getPortletWindowId method which will produce some stack trace logging to the console which might tell us more (note: requires Java 1.5): public static String getPortletWindowId(PortletSession session) { System.out.println("getPortletWindowId for session: " session.getId() "(thread: " Thread.currentThread().getId() ")"); String portletWindowId = (String)session.getAttribute(PORTLET_WINDOW_ID); if ( portletWindowId == null ) { synchronized (session) { System.out.println(" no portletWindowId yet - going to derive it. Current thread (" Thread.currentThread().getId() ") call stack:"); for (StackTraceElement st : Thread.currentThread().getStackTrace()) System.out.println(st); Double value = new Double(Math.random()); session.setAttribute(PORTLET_WINDOW_ID, value); Enumeration names = session.getAttributeNames(PortletSession.APPLICATION_SCOPE); System.out.println(" looking for attribute " PORTLET_WINDOW_ID " in current APPLICATION_SCOPE attributes:"); while (names.hasMoreElements()) { String name = (String)names.nextElement(); System.out.println(" found attribute: "+name); if (PortletSessionUtil.decodeAttributeName(name).equals(PORTLET_WINDOW_ID) && value.equals(session.getAttribute(name,PortletSession.APPLICATION_SCOPE)) ) { portletWindowId = name.substring("javax.portlet.p.".length(),name.indexOf('?')); System.out.println(" --> found - PORTLET_WINDOW_ID = "+portletWindowId); session.setAttribute(PORTLET_WINDOW_ID, portletWindowId); break; } } if (portletWindowId == null) System.out.println(" --> error: failed to derive the portletWindowId"); } } return portletWindowId; } For your convenience I've attached a modified version of the portlet-bridges-common-1.0.4.jar with the above changed method compiled in it (again: using it requires Java 5). I've run it myself (on Pluto/Jetspeed-2) which produces the following output (stack trace dump truncated for brevity): getPortletWindowId for session: FC9065541BED56975E35C1AD97BAB419(thread: 55) no portletWindowId yet - going to derive it. Current thread (55) call stack: java.lang.Thread.dumpThreads(Native Method) java.lang.Thread.getStackTrace(Thread.java:1383) org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:53) org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59) org.apache.portals.bridges.struts.StrutsPortlet.processRequest(StrutsPortlet.java:420) org.apache.portals.bridges.struts.StrutsPortlet.doView(StrutsPortlet.java:301) javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:247) javax.portlet.GenericPortlet.render(GenericPortlet.java:175) org.apache.jetspeed.factory.JetspeedPortletInstance.render(JetspeedPortletInstance.java:103) org.apache.jetspeed.container.JetspeedContainerServlet.doGet(JetspeedContainerServlet.java:277) javax.servlet.http.HttpServlet.service(HttpServlet.java:690) <snip/> looking for attribute org.apache.portals.bridges.util.portlet_window_id in current APPLICATION_SCOPE attributes: found attribute: javax.portlet.p.jp-2?org.apache.portals.bridges.util.portlet_window_id --> found - PORTLET_WINDOW_ID = jp-2 If you could try the same and provide me with the debug output you get, maybe we can get somewhat further with this problem. Ate
          Ate Douma made changes -
          Field Original Value New Value
          Attachment portals-bridges-common-1.0.4.jar [ 12388397 ]
          Hide
          Tim Boudreau added a comment -

          > If you look at the rest of following code within this method, you'll notice the random
          > generated Double object put in the session is put in there only for a for a very short time
          > and replaced within the same method almost immediately with a String object.

          Okay, now I understand what you're trying to do here - that helps. I now understand what the use of random is about, and
          portletWindowId = value;
          is definitely wrong.

          But portletWindowId is only reset if two tests are true -
          names.hasMoreElements()
          and
          PortletSessionUtil.decodeAttributeName(name).equals(PORTLET_WINDOW_ID) && value.equals(session.getAttribute(name,PortletSession.APPLICATION_SCOPE)

          • otherwise the Double remains there, and a subsequent call to the same method will trigger a CCE. From your description, it does not sound like you intend to leave the random Double there, but if either of the two tests above fails, that is what it will do. If either of the two tests failing means that the environment is completely unusable (I don't know portlets well enough to be sure if that's true or not), some kind of failure may be inevitable, but it would be better to restore the value and not have the failure look like it is in your code.

          I don't work on portal software at Sun(well, I spent six hours today inside OpenPortal's code, but that wasn't for Sun), so I don't know the history of why this is the way it is with JBoss or OpenPortal - I'm just trying to help Jon get some work done.

          I agree if the spec says it should be a string, then it should be a string; I could also believe that if the server is really putting it as some other type, that both companies might have customers who are depending on it being a Double (unless this is really just a result of this method being called twice and one of the tests failing), and be at risk if they break backward compatibility to comply with the spec.

          But my first assumption would be that this code is being called twice, the second time after putting a Double into the map and failing one of the tests in getPortletWindowId().

          I'll try your patch and post output here.

          Show
          Tim Boudreau added a comment - > If you look at the rest of following code within this method, you'll notice the random > generated Double object put in the session is put in there only for a for a very short time > and replaced within the same method almost immediately with a String object. Okay, now I understand what you're trying to do here - that helps. I now understand what the use of random is about, and portletWindowId = value; is definitely wrong. But portletWindowId is only reset if two tests are true - names.hasMoreElements() and PortletSessionUtil.decodeAttributeName(name).equals(PORTLET_WINDOW_ID) && value.equals(session.getAttribute(name,PortletSession.APPLICATION_SCOPE) otherwise the Double remains there, and a subsequent call to the same method will trigger a CCE. From your description, it does not sound like you intend to leave the random Double there, but if either of the two tests above fails, that is what it will do. If either of the two tests failing means that the environment is completely unusable (I don't know portlets well enough to be sure if that's true or not), some kind of failure may be inevitable, but it would be better to restore the value and not have the failure look like it is in your code. I don't work on portal software at Sun(well, I spent six hours today inside OpenPortal's code, but that wasn't for Sun), so I don't know the history of why this is the way it is with JBoss or OpenPortal - I'm just trying to help Jon get some work done. I agree if the spec says it should be a string, then it should be a string; I could also believe that if the server is really putting it as some other type, that both companies might have customers who are depending on it being a Double (unless this is really just a result of this method being called twice and one of the tests failing), and be at risk if they break backward compatibility to comply with the spec. But my first assumption would be that this code is being called twice, the second time after putting a Double into the map and failing one of the tests in getPortletWindowId(). I'll try your patch and post output here.
          Hide
          Tim Boudreau added a comment -

          Here is the logging with the patch above:

          PSPL_PAECSPPAI0012 : Portlet Initialized: GizmoDemo
          Command deploy executed successfully.
          PortalPack Message : Deployed Successfully.
          PSPL_PCCSPCPCI0002 : Invoking AppName:WelcomePortlet, PortletName:WelcomePortlet, PortletWindowName:WelcomePortlet.WelcomePortlet, Action:RENDER
          Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@35b0f::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@4f605d
          Set null::null
          PSPL_PCCSPCPCI0002 : Invoking AppName:PortletRssGizmoDemo, PortletName:GizmoDemo, PortletWindowName:PortletRssGizmoDemo.GizmoDemo, Action:RENDER
          Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@3f7a57::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@78e6e8
          getPortletWindowId for session: 45920bc9f47b303e7fb744fa9870(thread: 40)
          no portletWindowId yet - going to derive it. Current thread (40) call stack:
          java.lang.Thread.dumpThreads(Native Method)
          java.lang.Thread.getStackTrace(Thread.java:1401)
          org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:81)
          org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59)
          org.apache.wicket.protocol.http.portlet.WicketFilterPortletContext.setupFilter(WicketFilterPortletContext.java:63)
          org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:182)
          org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
          org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853)
          org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703)
          org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660)
          org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578)
          com.sun.portal.portletcontainer.portlet.impl.PortletRequestDispatcherImpl.include(PortletRequestDispatcherImpl.java:234)
          com.sun.portal.portletcontainer.portlet.impl.PortletRequestDispatcherImpl.include(PortletRequestDispatcherImpl.java:178)
          org.apache.wicket.protocol.http.portlet.WicketPortlet.processRequest(WicketPortlet.java:519)
          org.apache.wicket.protocol.http.portlet.WicketPortlet.doView(WicketPortlet.java:416)
          javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:328)
          javax.portlet.GenericPortlet.render(GenericPortlet.java:233)
          com.sun.portal.portletcontainer.appengine.PortletAppEngineServlet.service(PortletAppEngineServlet.java:382)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
          org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
          org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
          org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          com.sun.portal.portletcontainer.appengine.PortletAppEngineFilter.doFilter(PortletAppEngineFilter.java:105)
          org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
          org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853)
          org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703)
          org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660)
          org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578)
          com.sun.portal.portletcontainer.impl.PortletContainer.invokePAE(PortletContainer.java:787)
          com.sun.portal.portletcontainer.impl.PortletContainer.invokePAE(PortletContainer.java:670)
          com.sun.portal.portletcontainer.impl.PortletContainer.getMarkup(PortletContainer.java:208)
          com.sun.portal.portletcontainer.invoker.WindowInvoker.getPortletContent(WindowInvoker.java:371)
          com.sun.portal.portletcontainer.invoker.WindowInvoker.render(WindowInvoker.java:246)
          com.sun.portal.portletcontainer.driver.PortletContent.getContent(PortletContent.java:68)
          com.sun.portal.portletcontainer.driver.DesktopServlet.getPortletContents(DesktopServlet.java:296)
          com.sun.portal.portletcontainer.driver.DesktopServlet.getAllPortletContents(DesktopServlet.java:242)
          com.sun.portal.portletcontainer.driver.DesktopServlet.doGetPost(DesktopServlet.java:120)
          com.sun.portal.portletcontainer.driver.DesktopServlet.doGet(DesktopServlet.java:89)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
          org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
          org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
          org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)
          org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
          org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
          org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
          org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
          com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
          org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
          org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
          org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
          org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
          org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
          org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
          org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
          org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
          com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
          com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
          com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
          com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
          com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
          com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
          com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)
          com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
          com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
          looking for attribute org.apache.portals.bridges.util.portlet_window_id in current APPLICATION_SCOPE attributes:
          --> error: failed to derive the portletWindowId
          Set null::null
          PSPCD_CSPPD0022 : Number for Portlet Windows Displayed - thin: 0, thick: 2
          PSPL_PCCSPCPCI0002 : Invoking AppName:PortletRssGizmoDemo, PortletName:GizmoDemo, PortletWindowName:PortletRssGizmoDemo.GizmoDemo, Action:ACTION
          Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@ecb1e4::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@9317b3
          Process Action com.sun.portal.portletcontainer.portlet.impl.ActionRequestImpl@1d581e response=com.sun.portal.portletcontainer.portlet.impl.ActionResponseImpl@84549d application=
          getPortletWindowId for session: 45920bc9f47b303e7fb744fa9870(thread: 41)
          ApplicationDispatcher[/PortletRssGizmoDemo] PWC1231: Servlet.service() for servlet default threw exception
          java.lang.ClassCastException: java.lang.Double
          at org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:75)
          at org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59)
          at org.apache.wicket.protocol.http.portlet.WicketFilterPortletContext.setupFilter(WicketFilterPortletContext.java:63)
          at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:182)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
          at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853)
          at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703)
          at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660)
          at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578)
          at org.apache.wicket.protocol.http.portlet.WicketPortlet.processRequest(WicketPortlet.java:500)
          at org.apache.wicket.protocol.http.portlet.WicketPortlet.processAction(WicketPortlet.java:440)
          ....

          Show
          Tim Boudreau added a comment - Here is the logging with the patch above: PSPL_PAECSPPAI0012 : Portlet Initialized: GizmoDemo Command deploy executed successfully. PortalPack Message : Deployed Successfully. PSPL_PCCSPCPCI0002 : Invoking AppName:WelcomePortlet, PortletName:WelcomePortlet, PortletWindowName:WelcomePortlet.WelcomePortlet, Action:RENDER Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@35b0f::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@4f605d Set null::null PSPL_PCCSPCPCI0002 : Invoking AppName:PortletRssGizmoDemo, PortletName:GizmoDemo, PortletWindowName:PortletRssGizmoDemo.GizmoDemo, Action:RENDER Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@3f7a57::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@78e6e8 getPortletWindowId for session: 45920bc9f47b303e7fb744fa9870(thread: 40) no portletWindowId yet - going to derive it. Current thread (40) call stack: java.lang.Thread.dumpThreads(Native Method) java.lang.Thread.getStackTrace(Thread.java:1401) org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:81) org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59) org.apache.wicket.protocol.http.portlet.WicketFilterPortletContext.setupFilter(WicketFilterPortletContext.java:63) org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:182) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853) org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703) org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660) org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578) com.sun.portal.portletcontainer.portlet.impl.PortletRequestDispatcherImpl.include(PortletRequestDispatcherImpl.java:234) com.sun.portal.portletcontainer.portlet.impl.PortletRequestDispatcherImpl.include(PortletRequestDispatcherImpl.java:178) org.apache.wicket.protocol.http.portlet.WicketPortlet.processRequest(WicketPortlet.java:519) org.apache.wicket.protocol.http.portlet.WicketPortlet.doView(WicketPortlet.java:416) javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:328) javax.portlet.GenericPortlet.render(GenericPortlet.java:233) com.sun.portal.portletcontainer.appengine.PortletAppEngineServlet.service(PortletAppEngineServlet.java:382) javax.servlet.http.HttpServlet.service(HttpServlet.java:831) org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) com.sun.portal.portletcontainer.appengine.PortletAppEngineFilter.doFilter(PortletAppEngineFilter.java:105) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853) org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703) org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660) org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578) com.sun.portal.portletcontainer.impl.PortletContainer.invokePAE(PortletContainer.java:787) com.sun.portal.portletcontainer.impl.PortletContainer.invokePAE(PortletContainer.java:670) com.sun.portal.portletcontainer.impl.PortletContainer.getMarkup(PortletContainer.java:208) com.sun.portal.portletcontainer.invoker.WindowInvoker.getPortletContent(WindowInvoker.java:371) com.sun.portal.portletcontainer.invoker.WindowInvoker.render(WindowInvoker.java:246) com.sun.portal.portletcontainer.driver.PortletContent.getContent(PortletContent.java:68) com.sun.portal.portletcontainer.driver.DesktopServlet.getPortletContents(DesktopServlet.java:296) com.sun.portal.portletcontainer.driver.DesktopServlet.getAllPortletContents(DesktopServlet.java:242) com.sun.portal.portletcontainer.driver.DesktopServlet.doGetPost(DesktopServlet.java:120) com.sun.portal.portletcontainer.driver.DesktopServlet.doGet(DesktopServlet.java:89) javax.servlet.http.HttpServlet.service(HttpServlet.java:718) javax.servlet.http.HttpServlet.service(HttpServlet.java:831) org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288) org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577) com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577) org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571) org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632) org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577) org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571) org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080) org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272) com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637) com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568) com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813) com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341) com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263) com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214) com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380) com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265) com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106) looking for attribute org.apache.portals.bridges.util.portlet_window_id in current APPLICATION_SCOPE attributes: --> error: failed to derive the portletWindowId Set null::null PSPCD_CSPPD0022 : Number for Portlet Windows Displayed - thin: 0, thick: 2 PSPL_PCCSPCPCI0002 : Invoking AppName:PortletRssGizmoDemo, PortletName:GizmoDemo, PortletWindowName:PortletRssGizmoDemo.GizmoDemo, Action:ACTION Set com.sun.portal.portletcontainer.impl.PAERequestWrapper@ecb1e4::com.sun.portal.portletcontainer.impl.PAEResponseWrapper@9317b3 Process Action com.sun.portal.portletcontainer.portlet.impl.ActionRequestImpl@1d581e response=com.sun.portal.portletcontainer.portlet.impl.ActionResponseImpl@84549d application= getPortletWindowId for session: 45920bc9f47b303e7fb744fa9870(thread: 41) ApplicationDispatcher [/PortletRssGizmoDemo] PWC1231: Servlet.service() for servlet default threw exception java.lang.ClassCastException: java.lang.Double at org.apache.portals.bridges.util.PortletWindowUtils.getPortletWindowId(PortletWindowUtils.java:75) at org.apache.portals.bridges.util.ServletPortletSessionProxy.createProxy(ServletPortletSessionProxy.java:59) at org.apache.wicket.protocol.http.portlet.WicketFilterPortletContext.setupFilter(WicketFilterPortletContext.java:63) at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:182) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198) at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:853) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:703) at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:660) at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:578) at org.apache.wicket.protocol.http.portlet.WicketPortlet.processRequest(WicketPortlet.java:500) at org.apache.wicket.protocol.http.portlet.WicketPortlet.processAction(WicketPortlet.java:440) ....
          Ate Douma made changes -
          Attachment portals-bridges-common-1.0.4.jar [ 12388397 ]
          Hide
          Ate Douma added a comment -

          Thanks for testing it Tom, this was very helpful and confirms my suspicions.
          The fact that the internal attribute "org.apache.portals.bridges.util.portlet_window_id" just set as PORTLET_SCOPE session attribute is not returned from the APPLICATION_SCOPE enumeration of attributes clearly is not compliant with JSR-168 PLT.15.3.

          I have no idea how OpenPortal and JBoss Portal (see also: PB-77) are implementing their session attributes handling but IMHO this should be filed as a bug against both containers.

          Nonetheless, I've been thinking of an alternative solution which hopefully might work on these containers too.

          I've rewritten the getPortletWindowId() method as follows which works just as well on Pluto/Jetspeed-2 (which might even be a more optimal/efficient solution).
          If this works for OpenPortal I'm willing to replace the current solution with this new one:

          public static String getPortletWindowId(PortletSession session)
          {
          System.out.println("getPortletWindowId for session: "session.getId()" (thread: "Thread.currentThread().getId()")");

          String portletWindowId = (String)session.getAttribute(PORTLET_WINDOW_ID);
          if ( portletWindowId == null )
          {
          synchronized (session)
          {
          System.out.println(" no portletWindowId yet - going to derive it.");
          final String[] nameRef = new String[1];
          session.setAttribute(PORTLET_WINDOW_ID, new HttpSessionBindingListener()
          {
          public void valueBound(HttpSessionBindingEvent event)

          { nameRef[0] = event.getName(); }

          public void valueUnbound(HttpSessionBindingEvent event) {}
          });
          session.removeAttribute(PORTLET_WINDOW_ID);
          if (nameRef[0] != null)

          { portletWindowId = nameRef[0].substring("javax.portlet.p.".length(),nameRef[0].indexOf('?')); System.out.println(" --> found - PORTLET_WINDOW_ID = "+portletWindowId); session.setAttribute(PORTLET_WINDOW_ID, portletWindowId); }

          else

          { System.out.println(" --> error: failed to derive the portletWindowId"); }

          }
          }
          return portletWindowId;
          }

          Again, I've attached a portal-bridges-commons-1.0.4.jar (replacing the previous one) with this method compiled in. (FYI: this one is build for Java 1.4 again).
          I get the following (expected) output with Pluto/Jetspeed-2:

          getPortletWindowId for session: F8DB1E64E9C8227B0CA4A10BDB6E231A (thread: 53)
          no portletWindowId yet - going to derive it.
          --> found - PORTLET_WINDOW_ID = jp-2

          Can you please again try this one out on OpenPortal and report back if this works.

          Also note: as you can see I'm now removing the PORTLET_WINDOW_ID attribute again regardless if a the SessionBindingListener solution works,
          so you should no longer encounter a CCE with this version, but won't get the requested PortletWindowId either (which then probably will break other depending code...)

          Show
          Ate Douma added a comment - Thanks for testing it Tom, this was very helpful and confirms my suspicions. The fact that the internal attribute "org.apache.portals.bridges.util.portlet_window_id" just set as PORTLET_SCOPE session attribute is not returned from the APPLICATION_SCOPE enumeration of attributes clearly is not compliant with JSR-168 PLT.15.3. I have no idea how OpenPortal and JBoss Portal (see also: PB-77 ) are implementing their session attributes handling but IMHO this should be filed as a bug against both containers. Nonetheless, I've been thinking of an alternative solution which hopefully might work on these containers too. I've rewritten the getPortletWindowId() method as follows which works just as well on Pluto/Jetspeed-2 (which might even be a more optimal/efficient solution). If this works for OpenPortal I'm willing to replace the current solution with this new one: public static String getPortletWindowId(PortletSession session) { System.out.println("getPortletWindowId for session: " session.getId() " (thread: " Thread.currentThread().getId() ")"); String portletWindowId = (String)session.getAttribute(PORTLET_WINDOW_ID); if ( portletWindowId == null ) { synchronized (session) { System.out.println(" no portletWindowId yet - going to derive it."); final String[] nameRef = new String [1] ; session.setAttribute(PORTLET_WINDOW_ID, new HttpSessionBindingListener() { public void valueBound(HttpSessionBindingEvent event) { nameRef[0] = event.getName(); } public void valueUnbound(HttpSessionBindingEvent event) {} }); session.removeAttribute(PORTLET_WINDOW_ID); if (nameRef [0] != null) { portletWindowId = nameRef[0].substring("javax.portlet.p.".length(),nameRef[0].indexOf('?')); System.out.println(" --> found - PORTLET_WINDOW_ID = "+portletWindowId); session.setAttribute(PORTLET_WINDOW_ID, portletWindowId); } else { System.out.println(" --> error: failed to derive the portletWindowId"); } } } return portletWindowId; } Again, I've attached a portal-bridges-commons-1.0.4.jar (replacing the previous one) with this method compiled in. (FYI: this one is build for Java 1.4 again). I get the following (expected) output with Pluto/Jetspeed-2: getPortletWindowId for session: F8DB1E64E9C8227B0CA4A10BDB6E231A (thread: 53) no portletWindowId yet - going to derive it. --> found - PORTLET_WINDOW_ID = jp-2 Can you please again try this one out on OpenPortal and report back if this works. Also note: as you can see I'm now removing the PORTLET_WINDOW_ID attribute again regardless if a the SessionBindingListener solution works, so you should no longer encounter a CCE with this version, but won't get the requested PortletWindowId either (which then probably will break other depending code...)
          Ate Douma made changes -
          Attachment portals-bridges-common-1.0.4.jar [ 12388429 ]
          Ate Douma made changes -
          Link This issue duplicates PB-77 [ PB-77 ]
          Hide
          Tim Boudreau added a comment -

          The attached JAR works with OpenPortal - no CCEs.

          Thanks!

          Show
          Tim Boudreau added a comment - The attached JAR works with OpenPortal - no CCEs. Thanks!
          Hide
          Ate Douma added a comment -

          Right, no CCEs for sure, but what about the PortletWindowId?
          Did you check the console output and was the PortletWindowId actually determined, or did you only get a null value returned?
          In the latter case, the CCE might be gone but still the functionality is broken and then you still don't have a valid solution...
          I'd rather keep the old solution then and have the OpenPortal (and JBoss Portal) team fix the bug in their containers.

          Show
          Ate Douma added a comment - Right, no CCEs for sure, but what about the PortletWindowId? Did you check the console output and was the PortletWindowId actually determined, or did you only get a null value returned? In the latter case, the CCE might be gone but still the functionality is broken and then you still don't have a valid solution... I'd rather keep the old solution then and have the OpenPortal (and JBoss Portal) team fix the bug in their containers.
          Hide
          Antony Stubbs added a comment -

          Hi Ate,
          I've just hit this same problem with Pluto trunk no less... Am looking further into it now.

          Show
          Antony Stubbs added a comment - Hi Ate, I've just hit this same problem with Pluto trunk no less... Am looking further into it now.
          Hide
          Ate Douma added a comment -

          Now this is getting interesting
          Can you give some instruction steps how to reproduce this, and with which (Wicket?) application did you test it with?

          Show
          Ate Douma added a comment - Now this is getting interesting Can you give some instruction steps how to reproduce this, and with which (Wicket?) application did you test it with?
          Hide
          Antony Stubbs added a comment -

          Ok, the new code that you posted seems to do better, but I seem to have a problem where

          portletWindowId = nameRef[0].substring("javax.portlet.p.".length(),
          						nameRef[0].indexOf('?'));
          

          throws StringIndexOutOfBoundsException, because the value of nameRef[0] comes back just as PORTLET_WINDOW_ID

          i.e. "org.apache.portals.bridges.util.portlet_window_id" not "javax.portlet.p.*" as the code implies

          getPortletWindowId for session: CC465B39BA9199712DEEF690F90AE2C2 (thread: 15)
           no portletWindowId yet - going to derive it.
          17/10/2008 15:44:23 org.apache.catalina.core.ApplicationDispatcher invoke
          SEVERE: Servlet.service() for servlet default threw exception
          java.lang.StringIndexOutOfBoundsException: String index out of range: -17
          
          Show
          Antony Stubbs added a comment - Ok, the new code that you posted seems to do better, but I seem to have a problem where portletWindowId = nameRef[0].substring( "javax.portlet.p." .length(), nameRef[0].indexOf('?')); throws StringIndexOutOfBoundsException, because the value of nameRef [0] comes back just as PORTLET_WINDOW_ID i.e. "org.apache.portals.bridges.util.portlet_window_id" not "javax.portlet.p.*" as the code implies getPortletWindowId for session: CC465B39BA9199712DEEF690F90AE2C2 (thread: 15) no portletWindowId yet - going to derive it. 17/10/2008 15:44:23 org.apache.catalina.core.ApplicationDispatcher invoke SEVERE: Servlet.service() for servlet default threw exception java.lang.StringIndexOutOfBoundsException: String index out of range: -17
          Hide
          Antony Stubbs added a comment -

          actually, come to think of it, the StringIndexOutOfBoundsException was probably the reason why the Double wasnt being replaced, as the code threw the exception before it got to that stage, and subsequent requests were retrieving the Double and getting the class cast exceptions.

          But regardless, your new implementation does seem to clarify the issues.

          Show
          Antony Stubbs added a comment - actually, come to think of it, the StringIndexOutOfBoundsException was probably the reason why the Double wasnt being replaced, as the code threw the exception before it got to that stage, and subsequent requests were retrieving the Double and getting the class cast exceptions. But regardless, your new implementation does seem to clarify the issues.
          Hide
          Antony Stubbs added a comment -

          P.s. its just a basic hello world portlet application, nothing to it, deployed to pluto installed on tomcat using pluto:install .

          Show
          Antony Stubbs added a comment - P.s. its just a basic hello world portlet application, nothing to it, deployed to pluto installed on tomcat using pluto:install .
          Hide
          Antony Stubbs added a comment -

          Ok, trying to track this down, think I've found something.

          Why does the Pluto PorletSessionImpl#setAttribute use application shop in the following situation? This really needs explanation ala javadoc etc. Because in the spec, it clearly says that setAttribute should use PORTLET_SCOPE as it does in the else block. This seems to be cause the session attributes set in getWindowId in the Apache Bridges to fail in detecting the container assigned window id, because of course the attribute gets put into APPLICATION_SCOPE and a window id is never created.

              public void setAttribute(String name, Object value, int scope) {
              	ArgumentUtility.validateNotNull("attributeName", name);
              	if (scope == PortletSession.APPLICATION_SCOPE) {
              		httpSession.setAttribute(name, value);
              	} else {
              		httpSession.setAttribute(createPortletScopedId(name),  value);
              	}
              }
          

          Ok, yup, changing the setAttribute calls from PortletWindowUtils#getWindowId to call the explicit version of setAttribute(name,value,scope) and pass PortletSession.PORTLET_SCOPE lets the Apache Bridges function work correctly.

          This points towards a Pluto issue now, not a bridges issue, so I will create another jira issue for pluto.

          For a work around, I have changed getWindowId to use

          session.setAttribute(PORTLET_WINDOW_ID, ...., PortletSession.PORTLET_SCOPE); 
          

          in both places where it is used, and the windowId now appears to be generated on the attribute, and detected correctly.

          I have created a Pluto issue here:
          https://issues.apache.org/jira/browse/PLUTO-516

          Show
          Antony Stubbs added a comment - Ok, trying to track this down, think I've found something. Why does the Pluto PorletSessionImpl#setAttribute use application shop in the following situation? This really needs explanation ala javadoc etc. Because in the spec, it clearly says that setAttribute should use PORTLET_SCOPE as it does in the else block. This seems to be cause the session attributes set in getWindowId in the Apache Bridges to fail in detecting the container assigned window id, because of course the attribute gets put into APPLICATION_SCOPE and a window id is never created. public void setAttribute( String name, Object value, int scope) { ArgumentUtility.validateNotNull( "attributeName" , name); if (scope == PortletSession.APPLICATION_SCOPE) { httpSession.setAttribute(name, value); } else { httpSession.setAttribute(createPortletScopedId(name), value); } } Ok, yup, changing the setAttribute calls from PortletWindowUtils#getWindowId to call the explicit version of setAttribute(name,value,scope) and pass PortletSession.PORTLET_SCOPE lets the Apache Bridges function work correctly. This points towards a Pluto issue now, not a bridges issue, so I will create another jira issue for pluto. For a work around, I have changed getWindowId to use session.setAttribute(PORTLET_WINDOW_ID, ...., PortletSession.PORTLET_SCOPE); in both places where it is used, and the windowId now appears to be generated on the attribute, and detected correctly. I have created a Pluto issue here: https://issues.apache.org/jira/browse/PLUTO-516
          Hide
          Antony Stubbs added a comment -

          While we're at improving this code, may I also suggest something along the following lines? To help with error resolution...

          	/** The portlet scope namespace as defined in PLT. 15.3. */
          	private static final String PORTLET_SCOPE_NAMESPACE = "javax.portlet.p.";
          
          	/**
          	 * The attribute name of the portlet winow id test, to be stored in the portlet session.
          	 */
              public static String PORTLET_WINDOW_ID = "org.apache.portals.bridges.util.portlet_window_id";
              
          

          and

          ...
          					final String[] nameRef = new String[1]; // array so that it can be accessed within anonymous class yet changed later
          ...
          					// check that the attribute name was prefixed properly / as expected
          					if (nameRef[0].startsWith(PORTLET_SCOPE_NAMESPACE) && nameRef[0].contains("?"))
          					{
          						portletWindowId = nameRef[0].substring(PORTLET_SCOPE_NAMESPACE.length(),
          							nameRef[0].indexOf('?'));
          						System.out.println(" --> found - PORTLET_WINDOW_ID = " + portletWindowId);
          						session.setAttribute(PORTLET_WINDOW_ID, portletWindowId,
          							PortletSession.PORTLET_SCOPE);
          					}
          					else
          					{
          						throw new RuntimeException(
          							"Window ID attribute not prefixed with PORTLET_SCOPE_NAMESPACE. "
          								+ "Make sure the portlet container stores the attribute in PORTLET_SCOPE_NAMESPACE "
          								+ "and prefix's the name with the PORTLET NAMESPACE.");
          					}
          
          Show
          Antony Stubbs added a comment - While we're at improving this code, may I also suggest something along the following lines? To help with error resolution... /** The portlet scope namespace as defined in PLT. 15.3. */ private static final String PORTLET_SCOPE_NAMESPACE = "javax.portlet.p." ; /** * The attribute name of the portlet winow id test, to be stored in the portlet session. */ public static String PORTLET_WINDOW_ID = "org.apache.portals.bridges.util.portlet_window_id" ; and ... final String [] nameRef = new String [1]; // array so that it can be accessed within anonymous class yet changed later ... // check that the attribute name was prefixed properly / as expected if (nameRef[0].startsWith(PORTLET_SCOPE_NAMESPACE) && nameRef[0].contains( "?" )) { portletWindowId = nameRef[0].substring(PORTLET_SCOPE_NAMESPACE.length(), nameRef[0].indexOf('?')); System .out.println( " --> found - PORTLET_WINDOW_ID = " + portletWindowId); session.setAttribute(PORTLET_WINDOW_ID, portletWindowId, PortletSession.PORTLET_SCOPE); } else { throw new RuntimeException( "Window ID attribute not prefixed with PORTLET_SCOPE_NAMESPACE. " + "Make sure the portlet container stores the attribute in PORTLET_SCOPE_NAMESPACE " + "and prefix's the name with the PORTLET NAMESPACE." ); }
          Hide
          Ate Douma added a comment -

          FYI: PLUTO-516 has been fixed, see: https://issues.apache.org/jira/browse/PLUTO-516?focusedCommentId=12641680#action_12641680

          That issue very much relates to this one and if you can read in my comment on PLUTO-516, I suspect the reported errors on PB-84 and PB-77 on other containers like JBoss and OpenPortal
          might very well be caused by the exact same implementation mistake.
          From that POV, I'm even less inclined now to spend much time trying to find a reliable work around as that most likely just won't be possible if those other containers indeed made the same mistake.
          The earlier work around I proposed above (https://issues.apache.org/jira/browse/PB-84?focusedCommentId=12623333#action_12623333) definitely won't work.
          As I haven't received the needed feedback for validation on that work around I already concluded it to be invalid, and now I'm even more sure about it.

          So, unless someone can come up with another explanation and possible solution for those containers, I'll probably close this issue in the near future as Incomplete/Won't Fix

          Show
          Ate Douma added a comment - FYI: PLUTO-516 has been fixed, see: https://issues.apache.org/jira/browse/PLUTO-516?focusedCommentId=12641680#action_12641680 That issue very much relates to this one and if you can read in my comment on PLUTO-516 , I suspect the reported errors on PB-84 and PB-77 on other containers like JBoss and OpenPortal might very well be caused by the exact same implementation mistake. From that POV, I'm even less inclined now to spend much time trying to find a reliable work around as that most likely just won't be possible if those other containers indeed made the same mistake. The earlier work around I proposed above ( https://issues.apache.org/jira/browse/PB-84?focusedCommentId=12623333#action_12623333 ) definitely won't work. As I haven't received the needed feedback for validation on that work around I already concluded it to be invalid, and now I'm even more sure about it. So, unless someone can come up with another explanation and possible solution for those containers, I'll probably close this issue in the near future as Incomplete/Won't Fix
          Hide
          Antony Stubbs added a comment -

          Still, applying the changes suggested so far will at least make it easier for people to debug, rather than the CCE.

          Show
          Antony Stubbs added a comment - Still, applying the changes suggested so far will at least make it easier for people to debug, rather than the CCE.
          Antony Stubbs made changes -
          Attachment utils.patch [ 12392788 ]
          Ate Douma made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolution Won't Fix [ 2 ]

            People

            • Assignee:
              Unassigned
              Reporter:
              Tim Boudreau
            • Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development