You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by simon <sk...@apache.org> on 2007/08/18 10:43:23 UTC

[orchestra] ViewController stuff

Hi All,

Orchestra currently includes "ViewController" code to implement
callbacks on backing beans for different "lifecycle events", eg on
creation of view (init), and pre-render.

These kinds of callbacks are very useful, but is Orchestra really the
right place for this?

There is already an implementation of this sort of thing in the Shale
project's view-controller module:
  http://shale.apache.org/shale-view/index.html

I see from a brief look at the Orchestra code that the orchestra version
does have some conversation-related stuff in there too, but perhaps it
would be better to add that as a layer on top of another view-controller
implementation than to rewrite one?

If the orchestra view-controller code is significantly different from
shale (I don't know the shale code very well) then perhaps it could be
merged into Tomahawk rather than exist in Orchestra? 

And separately, both Shale and Orchestra ViewController implementations
depend upon having managed beans with names that "match" viewIds in
order for the controller to figure out which bean to invoke methods on.
I'm not very enthusiastic about this approach as it seems fragile:
rename a view and the callbacks silently stop happening. I would rather
see something based on the JSF12 approach of phase-listeners attached to
views. This also limits callbacks to one bean (though I suppose it is
possible to write a bean to proxy calls to other beans).

In JSF12, the UIViewRoot component can now have phase listeners attached
to it, and they get invoked for processing phases. These listeners are
attached by adding f:phaseListener tags to the page. As a convenience,
there are also attributes on f:view to configure a default
phaseListener:
  <f:view
    beforePhase="#{backingBean.doBeforePhase}"
    afterPhase="#{backingBean.doAfterPhase}">

    <f:phaseListener 
          binding="#{backingBeanPhaseListener}"/>

Something similar to the f:phaseListener tag should be pretty easy to
emulate in JSF1.1; just have a tag that adds phaselisteners to the
attribute map for a UIViewRoot, and then have a PhaseListener that
retrieves them and invokes them.

This approach keeps the mapping between view and bean in the page, so
renaming a page doesn't break the association. It is also clear to the
reader of the page what callbacks are occurring when that view is
executed, rather than then having to search the managed bean defs for
beans whose names "match" the viewId.

Note that although the f:phaseListener tag does require the target to
implement PhaseListener, I'm not suggesting that this point directly at
the backing bean. Requiring a backing bean to implement PhaseListener is
not very nice. There are a number of possible solutions to this that I
can post if people think this approach is worth investigating further.

Regards,

Simon


Re: [orchestra] ViewController stuff

Posted by Mike Kienenberger <mk...@gmail.com>.
On 8/19/07, Mario Ivankovits <ma...@ops.co.at> wrote:
> Hi!
> >> If, we have to use the (never ;-) ) upcoming myfaces-commons project.
> >> Are you willing to volunteer?
> >>
> >
> > What, is tomahawk dead? I must check the myfaces archives....
> >
> No, tomahawk is not dead, it is just that tomahawk should be a component
> library only while myfaces-commons has something like validators,
> phase-listeners, etc but no components.
> One might argue this should be part of Shale .... I don't know.

That's not quite true.   The stated goal for a "myfaces-commons" was
to collect anything that was renderkit-independent which might be of
value to another component set.

That would include validators, phase-listeners, converters, and
non-rendering components, or anything else that could safely be used
with any arbitrary component set.

Re: [orchestra] ViewController stuff

Posted by Mario Ivankovits <ma...@ops.co.at>.
Hi!
>> If, we have to use the (never ;-) ) upcoming myfaces-commons project.
>> Are you willing to volunteer?
>>     
>
> What, is tomahawk dead? I must check the myfaces archives....
>   
No, tomahawk is not dead, it is just that tomahawk should be a component
library only while myfaces-commons has something like validators,
phase-listeners, etc but no components.
One might argue this should be part of Shale .... I don't know.

>> We also have the AnnotationsViewControllerManager which uses the
>> @ViewController annotation where you can configure which view-ids the
>> bean belongs to.
>>     
>
> Hmm..this really tightly couples the source code of the bean to the
> current JSP structure. Moving a JSP page means changing the source code
> for a class...
>   
I think the whole separation between page author and bean developer
works as long as you have beans just providing a "service" and a page
uses many different beans to render its output.
If you have a controller bean which gathers all the data required for
the page they are coupled .... whatever you'll do.
> It still feels a little wrong to me though.
</snip>
> An alternate solution would be to force a page to "declare" all the
> beans it uses at the top of the page, and for it to be an error for any
> EL expression to reference a variable that has not been "declared". The
> declarations could then be inspected to find beans to invoke lifecycle
> methods on. However that's not part of the JSF spec.
>   
Ok, so what we can try is to create a jsf tag which allows one to
configure (all) the bean-name(s) acting as view-controller for the page.
> Now as the "page author" is the one who knows what views exist, surely
> it must be this person who is also responsible for defining the
> view-to-bean mappings. How can the "application developer" who writes
> the backing beans do this when the views (theoretically) are not written
> until later?
>   
It is a question of what happens first :-)
I think first a view will be created acting as prototype and later the
bean will be developed.
But I won't get cumbersome on this.

> Am I right that the whole point of this ViewController stuff is just to
> allow the dynaForm component to work? If so, maybe what we need to do is
> not debate the ViewController stuff but look at whether dynaForm can be
> implemented in a way that doesn't need it..
>   
No, the ViewController stuff in Orchestra is just to have a simple
ViewController and based on this the @ConversationRequire annotation
working.
The dynaForm do not require it.

Ciao,
Mario


Re: [orchestra] ViewController stuff

Posted by simon <sk...@apache.org>.
On Sat, 2007-08-18 at 13:37 +0200, Mario Ivankovits wrote:
> If, we have to use the (never ;-) ) upcoming myfaces-commons project.
> Are you willing to volunteer?

What, is tomahawk dead? I must check the myfaces archives....

> 
> > And separately, both Shale and Orchestra ViewController
implementations
> > depend upon having managed beans with names that "match" viewIds in
> > order for the controller to figure out which bean to invoke methods
on.
> > I'm not very enthusiastic about this approach as it seems fragile:
> >   
> We also have the AnnotationsViewControllerManager which uses the
> @ViewController annotation where you can configure which view-ids the
> bean belongs to.

Hmm..this really tightly couples the source code of the bean to the
current JSP structure. Moving a JSP page means changing the source code
for a class...

In JSF, pages reference beans via EL expressions. There is no avoiding
the fact that the presentation layout depends upon the code that
provides the actual data to present.

But backing beans don't reference pages except in corner cases, like
explicit lookups of components by their id. JSF encourages the approach
of data being "pulled" from backing beans, then updates being "pushed"
to backing beans. This approach means that the dependency is only
one-way, ie backing beans don't care what views they are used in.

In practice, I guess it's only an optional feature that people can use
or ignore. When the backing bean author and the page author are the same
person I suppose it's ok (which is the case much of the time). JPA
annotations have the same theoretical problems (having the database
table names etc hard-coded on the bean) but in practice work for many
people.

It still feels a little wrong to me though.

> 
> > I would rather
> > see something based on the JSF12 approach of phase-listeners
attached to
> > views.
> Ah, I should finally take some time to have a look at the new stuff in
> JSF12 (- any good summary about that somewhere?)
> 
> > In JSF12, the UIViewRoot component can now have phase listeners
attached
> > to it, and they get invoked for processing phases. These listeners
are
> > attached by adding f:phaseListener tags to the page. As a
convenience,
> > there are also attributes on f:view to configure a default
> >   
> Woho .... I wonder why the page designer should bother invoking the
> right phase methods on the backing bean.
> Isn't it the same (let's say) "wrong" concept than the t:saveState
where
> every now and then people arguing that this has nothing to do in the
view?

The JSF spec defines a number of "roles" for people involved in creating
an app:
* Page Authors
* Component Writers
* Application Developers

Yes, in the purist approach a "page author" should be able to create
view and lay data out within them without caring about anything but
where to fetch the relevant data from, and which action methods to
invoke. In particular, they shouldn't really need to know that a backing
bean's lifecycle methods need to be invoked.

The perfect solution would be for JSF to automatically figure out what
beans are referenced by a particular view, then invoke lifecycle methods
on them. That's quite tricky to implement, however. Maybe a custom
VariableResolver could somehow keep track of what beans are referenced
in a page and invoke the right lifecycle methods on them, but I wouldn't
want to be the one to implement that :-).

An alternate solution would be to force a page to "declare" all the
beans it uses at the top of the page, and for it to be an error for any
EL expression to reference a variable that has not been "declared". The
declarations could then be inspected to find beans to invoke lifecycle
methods on. However that's not part of the JSF spec.

So in *practice* someone has to manually create a list of the beans that
need to have lifecycle methods invoked on them for a particular view.
Now as the "page author" is the one who knows what views exist, surely
it must be this person who is also responsible for defining the
view-to-bean mappings. How can the "application developer" who writes
the backing beans do this when the views (theoretically) are not written
until later?

With the approach of mapping view lifecycle events to backing bean
methods via magic bean names, or external files, the "page author" then
needs to mess with faces-config files or similar which seems ugly to me.
Allowing them to define these mappings directly in the views they are
already creating only seems logical. The "page author" will presumably
be referencing some documentation created by the "application designer"
that lists what backing beans exist, what properties they expose, and
what action methods are available. So for this documentation to also
specify that certain property getters or action methods cannot be
invoked unless certain lifecycle methods are configured for that backing
bean doesn't seem unreasonable.

BTW, t:saveState tags don't seem unreasonable to me either. Again, only
the page author knows how many views are part of a conversation, and
what backing beans those pages want to access. So surely it is the page
author that needs to associate the needed backing beans with the
conversation scope. And as the page author is already editing pages, why
should this (bean, conversation) coupling be defined anywhere else?

> 
> > Note that although the f:phaseListener tag does require the target
to
> > implement PhaseListener, I'm not suggesting that this point directly
at
> > the backing bean. Requiring a backing bean to implement
PhaseListener is
> > not very nice. There are a number of possible solutions to this that
I
> > can post if people think this approach is worth investigating
further.
> >   
> However, if people think this is the way to go, I am sure it is easy
to
> create such a JSF tag too.


Am I right that the whole point of this ViewController stuff is just to
allow the dynaForm component to work? If so, maybe what we need to do is
not debate the ViewController stuff but look at whether dynaForm can be
implemented in a way that doesn't need it..

Regards,

Simon



Re: [orchestra] ViewController stuff

Posted by Mario Ivankovits <ma...@ops.co.at>.
Hi!
> There is already an implementation of this sort of thing in the Shale
> project's view-controller module:
>   http://shale.apache.org/shale-view/index.html
>   
I do not have any good argument why I didn't go the shale way. Maybe I
was just to shy to convince the shale people about the surely required
API change which might have been resulted in an huge patch ....
And I just doesn't know at the time of writing this stuff what the exact
API changes in Shale would have been.

I'd say, Orchestras implementation is just a lightweight variant of the
shale stuff.
If we would like to go the shale way, we have to add the shale,
shale-view and shale-tiger jar to the project which requires the view
controller stuff.
Doesn't really help in lowering the stack required to startup an
Orchestra application, does it?

> If the orchestra view-controller code is significantly different from
> shale (I don't know the shale code very well) then perhaps it could be
> merged into Tomahawk rather than exist in Orchestra? 
>   
If, we have to use the (never ;-) ) upcoming myfaces-commons project.
Are you willing to volunteer?

> And separately, both Shale and Orchestra ViewController implementations
> depend upon having managed beans with names that "match" viewIds in
> order for the controller to figure out which bean to invoke methods on.
> I'm not very enthusiastic about this approach as it seems fragile:
>   
We also have the AnnotationsViewControllerManager which uses the
@ViewController annotation where you can configure which view-ids the
bean belongs to.

> I would rather
> see something based on the JSF12 approach of phase-listeners attached to
> views.
Ah, I should finally take some time to have a look at the new stuff in
JSF12 (- any good summary about that somewhere?)

> In JSF12, the UIViewRoot component can now have phase listeners attached
> to it, and they get invoked for processing phases. These listeners are
> attached by adding f:phaseListener tags to the page. As a convenience,
> there are also attributes on f:view to configure a default
>   
Woho .... I wonder why the page designer should bother invoking the
right phase methods on the backing bean.
Isn't it the same (let's say) "wrong" concept than the t:saveState where
every now and then people arguing that this has nothing to do in the view?

> Note that although the f:phaseListener tag does require the target to
> implement PhaseListener, I'm not suggesting that this point directly at
> the backing bean. Requiring a backing bean to implement PhaseListener is
> not very nice. There are a number of possible solutions to this that I
> can post if people think this approach is worth investigating further.
>   
However, if people think this is the way to go, I am sure it is easy to
create such a JSF tag too.

Ciao,
Mario