[
https://issues.apache.org/jira/browse/PB-49?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12463790
]
Ate Douma commented on PB-49:
-----------------------------
Hi James,
After testing out your patch with my above described changes I found out it
still didn't work correctly.
Neither the solution for handling mode switches (PB-38), nor for multiple
instances on a single page (this issue).
But, I think I found different solutions for both which work reasonable, albeit
with some caveats.
I'll try to explain both issues and the problems here.
First the handling the mode switches (PB-38).
The problem comes from the last part of the Portlet Specification rule
PLT.11.1.1.lii (page 43), which says:
"Commonly, portals provide controls to change the portlet mode and the window
state of portlets.
The URLs these controls use are generated by the portal.
Client requests triggered by those URLs must be treated as render URLs and the
existing render parameters must be preserved."
This means that when a user switches mode using one of these control icons,
only the mode changes.
So, when the Struts Bridge is in view mode with (Struts) PAGE render parameter
/show/shoppingcard.do, and the user switches to edit mode,
the PAGE render parameter still points to /show/shoppingcard.do.
In your patch you cater for this issue by storing the current mode in the
session, and when a mode switch occurs, you ignore the PAGE render url
and render the edit mode default page instead, as well as store the new mode in
the session.
BUT: the PAGE render parameter still points to /show/shoppingcard.do.
If thereafter the user refreshes the page or interacts with a different portlet
on the page, the Struts portlet will render again but this time
it won't see a mode switch anymore (as there is none) and use the PAGE render
parameter *still* pointing to /show/shoppingcard.do and render the
wrong page in edit mode.
While I can imagine the reason why the JSR-168 spec team decided to require
that the existing render parameters must be preserved when switching
mode through the portal provided controls, this really poses a non-solvable
problem when you use the same (named) render parameters in different modes.
This not only affects the bridge behavior itself, but any portlet logic
depending on render parameters when using multiple modes.
Effectively, this rule requires one to use distinctly named render parameters
for each mode.
So, I've written a "solution" for this by indeed using different PAGE render
parameters for each mode,PAGE+request.getPortletMode.toString().
For action PAGE parameters this isn't needed as its a single invocation process.
This also removes the need to check for mode changes during rendering and
saving the current mode in the session.
Still, its not a perfect solution because once you switch modes *and* interact
with the portlet in this new mode, you will "lose" the PAGE render parameter
for the previous mode and switching back to that mode thereafter will result in
falling back to the default page.
So, this solution will only "remember" your current PAGE in the previous mode
if you switch back immediately.
Going further than this, for instance by keeping each mode PAGE parameter in
the session, introduces lots of other potential problems and complexities I
don't have the time right now to investigate and solve, so for now this has to
do.
If you or someone else needs a more complete solution please do send in
additional patches and I will try to evaluate and apply them if possible of
course.
Then there is the problem of handling multiple struts portlets on a single page
(this issue).
I'm sorry to say but after trying out your solution with the JPetstore demo
application it broke down immediately.
This is because your solution properly separates session form beans by storing
them under a unique (generated) name, but thereby also makes them unfindable
for non-form tag based code which tries to look them up, like a bean:define tag.
And this is never solvable this way as someone can just as well have written
java code in an Action trying to lookup a form bean directly from the session
too.
Or what about other, custom (non Struts framework related) session attributes?
Using those will also result in thrashing interactions when using multiple
instances on the same page.
So, the only proper solution to this is forcing the whole of the Struts portlet
code to use the PortletSession in PORTLET_SCOPE.
That way, each instance will have its own isolated "namespace" within the
global application session without fear of trashing each others (session) state.
I did write an implementation for this by providing a (proxy based) wrapping of
the session given to the StrutsServlet.
It works perfectly and requires little or no change to the Struts Bridge code.
There is one (possibly) big caveat though...
If the Struts portlet also needs separate, client invoked servlet interaction
which also depends on its session state, this will break down.
Consider rendering a pdf based on session state (like checking a security
ticket or whatever). That cannot be done directly from a portlet so one needs
to generate a link (or client-side) javascript which will call back from the
client browser to a servlet.
That servlet won't be able to "connect" with the portlet (instance) session
anymore without knowledge of the namespace (PortletWindow id) with which the
session attributes are encoded. So, existing code, unaware of the new
"namespacing" of the Struts portlet instance session is going to break because
of this.
On the other hand, having two Struts portlet instances on a single page when
trying to use a feature like this is likewise going to fail anyway too.
Because of this caveat, I'm planning to provide this solution as a optional,
configurable and non-default new feature.
By providing a portlet init parameter portletScopeStrutsSession=true, or
extending the protected boolean StrutsPortlet.getPortletScopeStrutsSession()
method (which will only be invoked during the init() method) you can override
the default behavior.
Furthermore, I'll provide an PortletWindowUtils class (in the bridges common
jar) through which you can retrieve the current instance PortletWindowId,
as well as get the full application scope session attribute name for a portlet
scoped session attribute name.
By providing a portletWindowId to a separately, client browser invoked, servlet
(as a query string parameter for instance), such a servlet will be able to
"connect" with the portlet/struts instance session again, but of course you
will be required to modify existing code to be able to make use of it.
I plan to commit this feature as well as my solution for PB-38 this weekend.
Regards, Ate
> Multiple instances of a struts portlet should be able to coexist on a single
> page.
> ----------------------------------------------------------------------------------
>
> Key: PB-49
> URL: https://issues.apache.org/jira/browse/PB-49
> Project: Portals Bridges
> Issue Type: Bug
> Components: struts
> Affects Versions: 1.0
> Environment: Any.
> Reporter: James May
> Assigned To: Ate Douma
> Attachments: patch-2007-01-04.zip, patch.zip
>
>
> When including multiple instances of a struts portlet on a page, form data
> for the portlet instances gets clobbered because there is a single form bean
> that is shared by all instances. Each portlet instance should be able to
> maintain its state independently of other instances.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]