Uploaded image for project: 'Struts 2'
  1. Struts 2
  2. WW-3091

Problems with sticky render parameters when creating urls in Oracle Portal

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Incomplete
    • Affects Version/s: 2.0.14
    • Fix Version/s: Future
    • Component/s: Plugin - Portlet
    • Labels:
      None
    • Environment:

      Oracle Portal

      Description

      > Hello all -
      >
      > We've had some trouble using Struts 2 portlets (2.0.14) with Oracle
      > Portal, and I wondered if anyone else had used this combination
      > successfully.
      >
      > The problems occur with portlets that have a form and submit buttons, and
      > the issue seems to be that Struts uses render parameters to pass
      > information (like action name) from the event phase to the render phase.
      > Oracle Portal keeps these values in the generated URL for the form action,
      > and so they persist for longer than Struts is expecting them to.
      >
      > An aside - this is also an issue with straight JSR 168 portlets in the
      > Oracle portal, but we can work around this by using session attributes to
      > pass data from event to render, rather than render params. However, as
      > Struts uses render params internally to figure out which action to invoke,
      > there's no similar workaround for Struts. I suspect the problem is in the
      > Oracle portal - the JSR 168 spec seems to indicate that render params are
      > for passing data from event phase to render phase, but I wanted to see if
      > anyone was aware of the issue and if there is a workaround. This all works
      > perfectly when running in Pluto.
      >
      > Here's an illustration of the problem - we are using a "redirectAction" to
      > get from event to render.
      >
      > I have a simple Struts action class "StrutsTest" which has these methods:
      >
      > public String execute(); // implements event phase processing
      > public String doView(); // implements render phase processing
      >
      > These methods do nothing except logging.
      >
      > My form has a single text input field called "pie" and a single submit.
      > Here's the relevant part of the struts config:
      >
      > <action name="init">
      > <result name="success">/WEB-INF/view/index.jsp</result>
      > </action>
      >
      > <action name="StrutsTestAction" class="struts2hello.StrutsTest">
      > <result name="input">/WEB-INF/view/index.jsp</result>
      > <result name="success" type="redirectAction" >
      > <param name="actionName">StrutsTestRender</param>
      > <param name="portletMode">view</param>
      > <param name="pie">${pie}</param>
      > </result>
      > </action>
      >
      > <action name="StrutsTestRender" class="struts2hello.StrutsTest"
      > method="doView">
      > <result name="success">/WEB-INF/view/index.jsp</result>
      > </action>
      >
      > Here's what happens, step by step:
      >
      > *** 1. First display. "init" action is invoked, which simply forwards to
      > the jsp. The form action url has this in it:
      > struts.portlet.action%3D%252Fview%252FStrutsTestAction%26struts.portlet.mode%3Dview
      >
      > *** 2. I enter "apple" in the pie field and submit. The event phase mthod
      > (execute) receives the value correctly and form is redisplayed .
      >
      > Logging shows this:
      >
      > 2009-04-16 09:32:31,581 INFO struts2hello.StrutsTest.execute - Begin
      > execute
      > 2009-04-16 09:32:31,583 INFO struts2hello.StrutsTest.execute - End execute
      > 2009-04-16 09:32:31,765 INFO struts2hello.StrutsTest.doView - Begin doView
      > A. Pie = apple
      > 2009-04-16 09:32:31,767 INFO struts2hello.StrutsTest.doView - doView B.
      > Phase: RENDER
      > 2009-04-16 09:32:31,768 INFO struts2hello.StrutsTest.doView - End doView
      >
      > This is all correct - the event phase action is invoked, and then the
      > render phase action (doView method) is invoked and the phase (from
      > PortletActionContext) is RENDER.
      >
      > But, on redisplay, the form action URL now has this embedded:
      >
      > pie%3Dapple%26struts.portlet.action%3D%252Fview%252FStrutsTestRender%26struts.portlet.mode%3Dview%26struts.portlet.eventAction%3Dtrue
      >
      > AND
      >
      > struts.portlet.action%3D%252Fview%252FStrutsTestAction%26struts.portlet.mode%3Dview
      >
      > I believe this is where things start to go wrong - Oracle has put the
      > render parameters (action name of "StrutsTestRender" and pie of "apple")
      > into the generated action url, and subsequent submits will see these
      > parameters.
      >
      > *** 3. Entering "cherry" into the pie field and submitting again shows
      > this in the log:
      >
      > 2009-04-16 09:33:40,502 INFO struts2hello.StrutsTest.doView - Begin doView
      > A. Pie = apple, cherry
      > 2009-04-16 09:33:40,505 INFO struts2hello.StrutsTest.doView - doView B.
      > Phase: EVENT
      > 2009-04-16 09:33:40,508 INFO struts2hello.StrutsTest.doView - End doView
      >
      > So we've now gone directly into the render method, but we're in the event
      > phase. Presumably because of struts.portlet.action value of
      > "StrutsTestRender" in the form's action URL.
      >
      > Also we now have both "apple" and "cherry" in the "pie" parameter values:
      > "apple" from being embedded in the URL, "cherry" from being entered in the
      > form.
      >
      the problem seems to be with JSR168DispatcherServlets ability to construct of /portletNamespace/modeNamespace/actionName
      the cause seems to come from session management inability to handle the attributes of PortletSession specifically t PORTLET_SCOPE
      This constant defines the scope of the session attribute to be private to the portlet and its included resources.

      As PortletSession is not being represented properly as implementations seem to be created by upcasted HttpSessions as evidenced here

      //WARNING DOWNCAST here
      HttpServletResponse dummyServletResponse =new PortletServletResponse(portlet_response);
      //WARNING DOWNCAST here
      HttpServletRequest dummyServletRequest =new PortletServletRequest(portlet_request, getPortletContext());

      PortletSession is tied to PortletServletRequest not HttpServletRequest any attempts to access or use cause InvalidState Exception thrown with the side effect that required elements for PortletSession such as /portletNamespace/modeNamespace are invalid or not avialable
      and are thus not properly serialised so the container can read the contents

      The proposed solution would be to fix JSR168DispatcherServlet to use PortletSession
      specifically allow PortletSession to be cognisant of which phase to use (EVENT_PHASE or RENDER_PHASE)
      http://portals.apache.org/pluto/portlet-1.0-apidocs/javax/portlet/PortletSession.html
      PortletRequest
      http://portals.apache.org/pluto/portlet-1.0-apidocs/javax/portlet/PortletRequest.html
      which has the ability to create PortletSession

      and finally PortletResponse
      http://portals.apache.org/pluto/portlet-1.0-apidocs/javax/portlet/PortletResponse.html

      MCG 17 April 2009 12:49 PM GMT

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              mgainty Martin Gainty
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: