|
From: John L. <jl...@un...> - 2007-05-22 22:30:22
|
Whew! That is a long and complicated set of questions.
I apologize for not weighing in on the forums -- the vBulletin platform
doesn't lend itself to a "monitoring" role.
Let me see if we can make some progress here:
Issue 1:
First, please realize that the concrete Controller hierarchies that come
with Spring Portlet MVC (and Spring Web MVC, for that matter) are
designed for certain common usage patterns. While they are very
flexible, it is certainly possible to come up with a way of operating
that does not lend itself to using these controller directly. It sound
like this might be the case in your instance.
>From what I can tell from your description, it sounds like you might
want to factor out the display of the search results from the form
controller that edits search criteria in order to make things simple.
So, I might recommend redesigning things slightly as follows:
1. Use two objects in the user session: one that contains your search
criteria and another that contains your view configuration. Write a
simple AbstractController (let's call it "TableViewController") that
only has a render phase that will show the results based on these two
objects in the session.
2. To enter/change the search criteria, create a SimpleFormController
(let's call it "TableViewCriteriaController") that provides a form to
edit the query criteria object. Override the formBackingObject method
to retrieve the object from the session if it exists and create a new
one if it does not. Override an onSubmitAction method to store the
modified object back into the session. Have it forward its render phase
to TableViewController.
3. Create another SimpleFormController (let's call it
"TableViewConfigController") to do the same thing for the view
configuration.
You'll need to handle the case of the first render of the portlet either
by having TableViewCriteriaController be the default mapping or by
having TableViewController do something intelligent if the session
objects do not exist yet (perhaps a default set of criteria?).
Issue 2:
I agree there is no easy mechanism to detect if values in the command
object have in fact changed. There are a few server-side optionsI can
think of:
- Use all custom PropertyEditors in the DataBinder, register
PropertyChangeListeners and react to PropertyChangeEvents. This is all
really intended for GUI programming, but could be used here. Yuck.
- Create some kind of custom PortletRequestDataBinder that will watch
for changes in value -- add this to your controllers by overriding the
createBinder method. Also not pretty.
Anyway, I agree this is a good idea. I added it to my list of thing to
implement someday. You should go create a JIRA item for this feature.
Issue 3:
This really isn't a portlet question at all -- this is a straight JSP
problem. On first review I'm not sure how best to address the issue. I
wanted to send the email on the first two issues as soon as possible.
Maybe someone else can help on this issue.
Let me know what follow-up questions you have.
John Lewis
Joerg Heinicke wrote:
> Hello,
>
> in my habit to use libs/frameworks as best as possible I often drive them to
> their extremes and come across some issues in them or at least questions others
> might not have had and can't answer me. That's the case at the moment with
> Spring Portlet MVC. I have posted them in the forum [1, 2, 3], but nobody could
> really give answers to them. And since Spring developers were rarely seen in the
> forum I decided to ask those questions here again. :-)
>
> All the questions are related and result from a feature I implemented in the
> last two weeks: a generic table view. That means you have a search form, this
> fills a criteria and the result is shown as table. Since this is very common
> functionality I built an abstraction of it. There is a TableViewConfig
> configuring the final result table (columns to view, order of columns, order of
> rows). There is an object the form is bound to and with which the result is
> retrieved using criteria by example. The last part is done by a CriteriaProvider
> (creating Hibernate's DetachedCriteria for example) and a DAO.
>
> The Portlet MVC part consists of two controllers: TableViewController for
> displaying the search form and the result. And TableViewConfigController for
> displaying a form for configuring the TableViewConfig, i.e. where you can change
> the order of the columns or switch on or off the one or the other column. The
> default view (actually view mode) is the TableViewController, you put your
> criteria into the search form and get the result. If you want to change the
> TableViewConfig you can switch to the edit mode and the
> TableViewConfigController comes into play. On saving the TableViewConfig I want
> to switch back to the view mode and show the new result according to the new
> TableViewConfig.
>
> =====
>
> Issue 1 [1] I have (which is also not much related to my particular use case) is
> the usage of two different controllers for action and render phase. This is made
> easy by Spring since the HandlerMapping is executed for each phase.
> Unfortunately it seems not well-supported since you are more or less forced to
> use the same command object for both controllers. In the use case on saving the
> TableViewConfig (action request and form submit) I want to switch to
> TableViewController and render the result as it were a form submit in the same
> controller (isFormSubmission() returning true). But that's not possible since I
> need a different form backing object for this controller. In the case of
> isFormSubmission() returning true Spring Portlet MVC expects the form backing
> object to be found in the PortletSession (getRenderCommand(RenderRequest)). Only
> when isFormSubmission() does not return true a new form backing object is
> created. So with
>
> response_.setRenderParameter(getFormSubmitParameterName(), "false");
>
> in the TableViewConfigController I force the TableViewController to create its
> own form backing object, but can't display the search result immediately since
> I'm no longer in form submission rendering.
>
> =====
>
> The second issue is about missing value change listeners [2] or something like
> this. On changing the order of the columns (TableViewConfigController) I want to
> redisplay the form, i.e. go into form change processing. But it seems impossible
> to determine changes to the form backing object in Spring MVC. I worked around
> it by setting a parameter on such form submits on the client with Javascript and
> trigger on this one in isFormChangeRequest(). A better solution is welcome.
>
> =====
>
> The third issue consists of multiple parts. It comes with using selects in the
> search from and not only plain text inputs. My TableViewConfig actually has a
> list of TableViewColumns, of which each has for example a property "path",
> "name", "type" ("input", "select"). For selects there is additionally
> "optionsPath", "itemValue" and "itemLabel" matching the attribute names of
> Spring's form taglib. Normally it would look like
>
> <form:select path="company">
> <form:options items="${companies}" itemValue="id" itemLabel="name"/>
> </form:select>
>
> With my abstraction it would be
>
> <!-- context set to tableView.columns[i] via spring:nestedPath -->
> <form:select path="${path}">
> <form:options items="${${optionsPath}}" itemValue="${itemValue}"
> itemLabel="${itemLabel}"/>
> </form:select>
>
> First problem with it is ${${, so nested property evaluation, which is not
> supported by JSTL. Lucky me, Spring's OptionsTag allows to pass an expression,
> so that I only need to prevent JSTL from interpreting the nested expression. I
> do it with something like (don't have access to the code at the moment)
>
> <c:set var="optionsPathExpr" value="${'${'}${optionsPath}${'}'}"/>
> <form:options items="${optionsPathExpr}" itemValue="${itemValue}"
> itemLabel="${itemLabel}"/>
>
> This works due to Spring's resolving of the "optionsPathExpr". But it's awkward
> and nicer solutions are welcome. I'll also come back to it later since it gets
> an issue again ...
>
> Now there is the requirement to style the item labels and I'm at [3] or [4].
> <form:select> and <form:options> only allow to set plain itemLabel and
> itemValue. It can again be an expression, but the result of it is interpreted as
> property of the bean. I can not construct complex labels, while a kind of a
> template would be nice as shown in [4] and [5].
>
> Workaround up to now, e.g. for i18n, is to use <c:forEach> and <form:option> as
> shown in [3] since <form:option> can be any JSP stuff. I COULD use it, it would
> stay as generic as the other solution, it's only a bit longer. BUT (coming back
> to the nested expression evaluation) I lose Spring's resolving of the
> "optionsPathExpr". I don't see a way to rewrite
>
> <form:select path="${path}">
> <c:forEach items="${${optionsPath}}">
> <form:option value="${item}"><!--complex label--></form:option>
> </c:forEach>
> </form:select>
>
> Nested expressions don't work and using the "workaround" from above <c:forEach>
> would try to iterate on the string "${optionsPathExpr}". That problem is not
> related to Spring directly, but if anybody knows a solution I'll be happy.
>
> While [4] for others is just a shorter way of writing for me it's the only
> option I see at the moment.
>
> =====
>
> Thank you for still reading this lengthy post. I appreciate any input and help
> on my problems.
>
> Regards
> Joerg
>
> [1] http://forum.springframework.org/showthread.php?t=38451
> [2] http://forum.springframework.org/showthread.php?t=38499
> [3] http://forum.springframework.org/showthread.php?t=38795
> [4] http://opensource.atlassian.com/projects/spring/browse/SPR-3484
> [5] http://opensource.atlassian.com/projects/spring/browse/SPR-2659
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by DB2 Express
> Download DB2 Express C - the FREE version of DB2 express and take
> control of your XML. No limits. Just data. Click to get it now.
> http://sourceforge.net/powerbar/db2/
>
>
|