Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portlet 2.0 (JSR 286) support in Spring MVC [SPR-4259] #8937

Closed
spring-projects-issues opened this issue Dec 14, 2007 · 13 comments
Closed

Portlet 2.0 (JSR 286) support in Spring MVC [SPR-4259] #8937

spring-projects-issues opened this issue Dec 14, 2007 · 13 comments
Assignees
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

John Lewis opened SPR-4259 and commented

I've updated the description of this issue to change it to a general place to work out Portlet 2.0 (JSR 286) support for Spring MVC. I think a general approach to this larger issue will result in a resolution to the original point of this issue.

Original Description: Add support for Portlet WindowState to org.springframework.web.bind.annotation.RequestMapping


Affects: 2.5 final

25 votes, 19 watchers

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

John, in practice, I suppose window states are only really mapped differently for render requests... I can only really imagine action requests to differ per portlet mode (which is usually the differentiator between entire controllers) but not per window state - in particular since the window state may change without the action re-executing, just with a different render request issued. As far as I can imagine, action methods would - if it all - just take the window state into account for details of their processing but not for the entire action method mapping...

So I was wondering whether we should support an @Render annotation that takes an optional window state value - serving both for clearly annotating render methods (despite the implicit autodetection) and for specifying a window state mapping. We could complement this with an @Action annotation for action methods, taking an optional action name value for Portlet 2.0, and @Event with an event name for Portlet 2.0 events. All of those would typically be relative to an @RequestMapping annotation, mapping a portlet mode at the controller type level, or could be augmented with method-level @RequestMapping annotations that map specific modes and/or parameters.

We could be reusing Portlet 2.0's @ProcessAction and @ProcessEvent, I guess. However, Portlet 2.0's @RenderMode is really designed for portlet mode mappings, which is not what we typically want, since the mode is almost always specified at the controller type level. What we want is rather a similar annotation that either takes a window state or no value at all, applied relative to the controller's mode mapping.

What do you think?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

John Lewis commented

Here are some notes from on email on initial thoughts for Portlet 2.0 support in Spring MVC:

Mapping and dispatching all the varied request types that exist in JSR 286 may well best be done via the new Controller Annotations introduced in Spring 2.5.

There are some annotations specified in JSR 286, but they are only for use within GenericPortlet. We may want to do something similar in the new Controller annotation set. Our DispatcherPortlet does descent from GenericPortlet, so we can use them in our implementation if we want to. There are only three annotations for GenericPortlet:

@ProcessAction(name=<actionname>) : GenericPortlet will attempt to dispatch action phase calls to methods with this annotation. The action name must be set on the URL with the parameter "javax.portlet.action".

@ProcessEvent(name=<eventname>) or @ProcessEvent(qname=<eventname>) : GenericPortlet will attempt to dispatch event phase calls to methods with this annotation. The name must be declared in the portlet deployment descriptor and matches the name from the setEvent methods from the ActionResponse or RenderResponse.

@RenderMode(name=<portletmode>) : GenericPortlet will attempt to dispatch render phase calls to methods with this annotation. The portletmode must match the PortletMode of the request.

So, while these are nice, they certainly aren't a complete set.

To have good flexible annotation-based dispatcher mapping for Portlet 2.0, we should support at least the following as mapping criteria:

  • requestType
  • portletMode
  • windowState
  • parameter(s)

There is now a request attribute named LIFECYCLE_PHASE ("javax.portlet.lifecycle_phase") that will indicate the type of request: ACTION_PHASE, EVENT_PHASE, RENDER_PHASE, RESOURCE_SERVING_PHASE. This will only be present in JSR 286, so we will still have to rely on other methods (such as instanceOf checking) in the JSR 168 world.

Here are some other things we could consider using for the mapping criteria and/or method parameters:

PortletRequest:

  • request attributes
  • session attributes
  • portlet preferences
  • request properties (portal-specific data)
  • content type

ActionRequest:

  • special support for the ACTION_NAME parameter (probably a must-have since GenericPortlet does this)
  • method (GET, PUT, POST, etc.)

EventRequest:

  • Event.name or Event.qname (probably a must-have since GenericPortlet does this)
  • method (GET, PUT, POST, etc.)

RenderRequest:

  • RENDER_PART request attribute (RENDER_HEADERS, RENDER_MARKUP) -- may be needed for properly setting cookies, response headers, portlet title, next possible portlet modes, markup head elements)

ResourceRequest:

  • resourceId (not in GenericPortlet, but really probably should be supported)
  • method (GET, PUT, POST, etc.)

@spring-projects-issues
Copy link
Collaborator Author

John Lewis commented

Instead of adding a number of new annotations, what about making the @RequestMapping annotation massively flexible with a number of possible arguments for things like request type, portlet mode, window state, parameters, etc.?

Then we could do things like this:

@RequestMapping(portletMode = PortletMode.VIEW, requestType = PortletRequest.RENDER_PHASE, windowState = WindowState.MAXIMIZED)

@RequestMapping(requestType = PortletRequest.ACTION_PHASE, params = "action=delete")

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This is exactly what I'm wondering about: Do we need special-purpose annotations here or should we try to provide a one-size-fits-all annotation that is capable of expressing everything...

Keep in mind that @RequestMapping is reused between Servlet and Portlet environments. Its present design is generic enough to allow for both. If we wanted to do highly portlet-specific stuff there, we'd probably have to create a dedicated @PortletRequestMapping annotation. However, since annotations do not support inheritance, that would have to duplicate @RequestMapping's basic attributes... Anyway.

I tend to like dedicated @Render and @Action annotations that also describe the annotated method's role nicely. This also plays together nicely with the (very common) pattern of mapping the portlet mode at the controller type level.

@Controller
@RequestMapping("VIEW")
public MyController {

@Render
public String showMainPage(Model model) {
...
return "myView";
}

@Render("MAXIMIZED")
public String showMainPageLarge(Model model) {
...
return "myView";
}

@Action("search")
public void processSearch(ActionRequest request, ActionResponse response) {
...
}
}

Generic @(Portlet)RequestMapping attributes would be significantly more verbose here. Supporting specific stuff like action names or event names would be quite unclean there as well. Which is why I wondered whether the specific annotations are the better choice, in particular given that stuff like window states only really makes sense for render requests too...

Of course, @Render / @Action and @RequestMapping could be combined on the same method as well, for example to express a general parameter mapping:

@Action
@RequestMapping(params = "action=search")
public void processSearch(ActionRequest request, ActionResponse response) {
...
}

@Render
@RequestMapping(params = "action=search")
public String showSearchResult(Model model) {
...
}

This is very close to the present Portlet MVC approach, just annotating action/render methods explicitly. With Portlet 1.0, these would be attribute-less descriptive annotations only (with the exception of @Render possibly having a window state attribute). For Portlet 2.0, we would then introduce an action name attribute in @Action, as well as corresponding annotations for events and resource requests.

Essentially, I'd like to keep @RequestMapping in its present design: expressing an HTTP method mapping ("method=") and/or parameter mapping ("params="), and additionally a convenient 'primary' mapping through its value - @RequestMapping("..."). The latter is a request path for Servlet controllers and a Portlet mode for Portlet controllers. More specific Portlet-only concerns would be expressed through the 'special' @Action / @Render annotations, possibly combined with @RequestMapping's method and/or parameter mappings.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

John Lewis commented

Sorry for the slow response -- too much "real" work to do around here...

Okay -- I think that all makes sense. You certainly know the internal structure of the annotations better than I do at this point and those considerations are valid.

One assumption I would be careful with is just how common the pattern of mapping the portlet mode at the controller type level will be. In the past few weeks I've talked with a number of portlet developers about the annotations and this assumption was a big turn-off for them because they feel like they have some portlets complicated enough that they would not want to pull all their controller code for the view mode into a single class. Any chance of loosening this restriction on the portlet side somehow? I can see that it makes sense for HTTP paths, but I agree it is overly restrictive for portlet modes.

So as to what potential portlet-specific annotations (and their optional elements) might look like, what about something like this:

@Render
windowState

@Action
name (specific request parameter "javax.portlet.action" - constant ACTION_NAME in the JSR 286 javax.portlet.ActionRequest Interface)

@Event
name (local part of the event name)
qname (full event qname)

@Resource
id (resource identifier set in the ResourceURL)

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

John, thanks for the feedback... No hurry at this point, but it'll be good to make up our mind before things become urgent :-)

Those special annotations look good to me, except for @Resource which unfortunately clashes with the JSR-250 @Resource annotation (for injection of JNDI components). I do like the short anntoation names otherwise, so I'm not sure how to resolve this...

With respect to mapping the same portlet mode onto different controllers: We can certainly aim for relaxing that. Would you like to see parameter mappings expressed there, similar to PortletModeParameterHandlerMapping? The @RequestMapping annotation does support that already - however, just at the method level, throwing an exception when using the params attribute at the type level. We'd simply need to relax that. I'll consider that for Spring 2.5.2 already.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

John Lewis commented

Juergen,

Good point about the @Resource annotation clash. Here are some options for slightly more verbose names:

@RenderPhase, @ActionPhase, @EventPhase, @ResourcePhase
@RenderMapping, @ActionMapping, @EventMapping, @ResourceMapping
@ProcessRender, @ProcessAction, @ProcessEvent, @ProcessResource (two of these are the same as in GenericPortlet, although I don't see that as a problem)

I think I like the first one the best, but I don't have a strong preference.

I think it would be nice to allow @RequestMapping to specify parameter mappings at the type level if possible, although I don't think its critical as long as we can specify the same portlet mode at the type level in multiple classes and then specify different parameter mappings at the method level.

Here is another question for you. From a usage stand point, it would be cleaner if the method level annotations mentioned above were also capable of expressing request parameters in addition to their special

@RenderPhase(windowState="maximized", params = "action=search")
public void displaySearch(...) { ... }

Instead of having to do this:

@RenderPhase(windowState = "maximized")
@RequestMapping(params = "action=search")
public void displaySearch(...) { ... }

I suppose this largely gets back to my original suggestion, but with special annotations for each portlet phase instead of overloading the single @RequestMapping annotation. Admittedly I haven't implemented annotations yet, so I'm not fully aware of the inheritance limitations. Is there some way to factor out the logic for handling request parameters so this would be a reasonable approach?

Thanks!
John

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

John,

I've done some revisions for the 2.5.2 release already: @RequestMapping's "params" attribute is supported at the type level for Portlets now, mapping mode+params onto specific handlers. You may also specify the same mode for multiple handlers, differentiating by params at the handler method level. This will be available in tonight's 2.5.2 snapshot!

As for the Portlet 2.0 support, I guess I prefer dedicated @RenderMapping / @ActionMapping / @ResourceMapping / @EventMapping annotations at the method level, supporting specific attributes for their purpose within a type-level portlet mode mapping. Those four annotations could also feature @RequestMapping's general params attribute... There is no way to inherit an annotation attribute but we can simply duplicate it and share the processing logic between all of those mapping annotations.

So in Spring 3.0, people could keep using the general @RequestMapping for portlet requests, allowing to treat different kinds of requests within the same general handler method (if desired) or to differentiate through the handler method signatures (with the parameter types indicating the request type to be handled). This will also work for Portlet 2.0 resource and event requests.

Alternatively, the special @RenderMapping / @ActionMapping / @ResourceMapping / @EventMapping annotations can be used, explicitly indicating the type of request to handle and allowing for fine-grained narrowing through specific attributes (such as window state, action name, resource id and event name, respectively). I prefer the XxxMapping naming over XxxPhase, since stuff like resource requests isn't really just about different phases of the same request but rather about fundamentally different request types to begin with.

Does that sound like a plan? BTW, any updates when containers with compliant Portlet 2.0 previews will be available?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

John Lewis commented

Sounds good to me. Glad to hear the changes are already in place for 2.5.2 -- I think they will help a lot with adoption of the annotations by portlet developers.

I agree the "Phase" metaphor is kind of broken, although it is consistent with terminology from the specification itself. XxxMapping is certainly fine by me. Sharing the annotation attribute processing logic sounds like a good approach -- I definitely like having them be shorter.

Anyway, it all definitely sounds like a good plan.

The reference implementation for JSR 286 is supposed to be Pluto 2.0 -- development there is definitely slow and I have no idea when it will be released. I have been bugging some of the JSR 286 Expert Group about this lately.

On the other hand, JBoss has just released a Beta 1 of their JSR 286 Portlet Container (http://labs.jboss.com/portletcontainer/). I even put up a quick blog entry about it (http://www.unicon.net/node/957). This may well be the best place to do early testing.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

I'll schedule this for 3.0 M2, since we intend to do an early 3.0 M1 with core container and core MVC updates first. Actual implementation work on Portlet 2.0 support is likely going to start in June.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Johan Eltes commented

Is there any chance we could see a supported integration with Spring WebFlow + Facelets /JSF + JSR 286 that works for the MyFaces as well as RI of JSF? WebFlow + Facelets /JSF + JSR 186 only support portlet VIEW state and MyFaces, and ist still tagged "experimental".

@spring-projects-issues
Copy link
Collaborator Author

Patrick W. McMichael commented

As you're thinking about annotation support for 3M2, I'm reminded of an issue I have even in Spring 2.5. For the most part, you try to parallel spring portlet mvc with spring web mvc. In spring web mvc, we typically can get by with a single central dispatcher servlet (i.e. front controller). Bean-name to URL mapping provides ample flexibility.

With portlet mvc, however, when mapping by mode / parameter combinations, that is tougher to do. I understand that @RequestMapping now allows further refinement by parameter at the type level, not just the method level. When you configure/deploy a portlet, however, a given container may not allow special url query parameters to be specified for initial render. The container simply accesses the portlet by name and triggers the initial render in VIEW mode. At action handling time, request parameters may be used, thus allowing us to tap into the @RequestMapping params to serve as limiters at the method or type level.

If I could get the container to do the initial render/VIEW of the portlet with a specified parameter, it would be possible to use a parameter at the type level in addition to the portlet mode to narrow down to a specific handler. As such, it would be possible to go back to using a single dispatcher. That capability outstanding, it seems I'm left with (a) configuring multiple dispatchers, and (b) going with one of the other handler mapping strategies (non-annotation based, mode, parm, or combo).

Am I missing a way to have a central dispatcher portlet in a multi-portlet application?

pwm

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

A first cut of Portlet 2.0 support is ready for M2. This includes @Action/Render/Resource/EventMapping annotations at the handler method level, as well as extended Resource/EventAwareController interfaces. The HandlerInterceptor, HandlerAdapter and HandlerExceptionResolver facilities have support for resource/event requests as well now.

It turned out that it would have been quite convoluted to support Portlet 2.0 and 1.0 side by side. I eventually decided to do a full update to Portlet 2.0, which significantly simplified the code in the annotation processing and in particular in the general DispatcherPortlet. I preserved full Portlet 1.0 / Spring 2.5 compatibility in the "portlet.mvc" package, with decomposed interfaces etc, since that is what 99% of the user's code typically implements or derives from. This means that, in general, user code should keep working. However, the underlying portal server / portlet container will have to be updated to Portlet API 2.0 in order to run Spring 3.0 on top of it.

Juergen

@spring-projects-issues spring-projects-issues added type: enhancement A general enhancement has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.0 M2 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants