Issue Details (XML | Word | Printable)

Type: Improvement Improvement
Status: Resolved Resolved
Resolution: Fixed
Priority: Minor Minor
Assignee: msnicklous
Reporter: msnicklous
Votes: 0
Watchers: 0

If you were logged in you would be able to see more operations.

Issue in GenericPortlet Annotation Processing

Created: 03/May/13 01:38 PM   Updated: 19/Aug/13 01:12 PM   Resolved: 16/Aug/13 08:15 AM
Component/s: JSR 286 Portlet Specification Errata
Affects Version/s: None
Fix Version/s: None

Time Tracking:
Not Specified

Participants: msnicklous and Neil Griffin

 Description  « Hide

This problem is a bit esoteric, and I hope I can adequately present it.
It has to do with Action dispatching using annotations in the case of inheritance.

Working Document 3 (22.04.13) Section "PLT. Action Dispatching", beginning at line 8
on page 48, it states:
For a received action the processAction method in the GenericPortlet class tries
to dispatch to public methods annotated with the tag
@ProcessAction(name=<action name>), where the action name must be set on the
ActionURL ...

An attempt was made to use this feature in the following manner:
class PortletA extends GenericPortlet { @ProcessAction(name="actionA") void processMyActionAinA(ActionRequest req, ActionResponse resp) throws PortletException,; };

class PortletB extends PortletA { @ProcessAction(name="actionA") void processMyActionAinB(ActionRequest req, ActionResponse resp) throws PortletException,;};

Now the question is, for portlet B, which "processMyActionA" is called when actionA occurs?

We would want it to be "processMyActionAinB", I believe.

However, GenericPortlet uses .getClass().getMethods() to obtain the methods for annotation processing.

The javadoc for Class.getMethods() states:
Returns an array containing Method objects reflecting all the public member methods of the
class or interface represented by this Class object, including those declared by the class
or interface and those inherited from superclasses and superinterfaces. Array classes
return all the (public) member methods inherited from the Object class. The elements in the
array returned are not sorted and are not in any particular order.

Since GenericPortlet doesn't do any particular processing to handle methods inherited from
superclasses, it turns out that the actual method for PortletB called when actionA occurs
is not deterministic. It can be either "processMyActionAinB" or "processMyActionAinA", depending on
how .getMethods() happens to order the method array.

We may want to look into this at some point.

Neil Griffin added a comment - 14/May/13 04:03 AM

I think a simple fix for the private GenericPortlet.cacheAnnotatedMethods() method would be to call Method.getDeclaringClass() to see if if that is the same as this.getClass(). If true, then it should "win" over all other candidate methods in the array.

msnicklous added a comment - 16/Aug/13 08:15 AM - edited

updated Code change only; no apidoc change. See:

Test portlet: PORTLETSPEC3_15 from portletbox.