You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Laurie Harper <la...@holoweb.net> on 2006/01/06 00:17:27 UTC

[shale] DefaultViewControllerMapper limitations

Thanks to my unusual use of view identifiers carrying path-extra-info 
information, I've discovered a bit of a limitation with 
DefaultViewControllerMapper: if the result of applying the mapping 
algorithm isn't legal as a value binding expression, you get an ugly 
stack trace. I triggered this because I have view identifiers which may 
include spaces or other 'special' characters which, to be fair, the 
Javadoc explicitly states you shouldn't do :-)

Looking at the bigger picture, any mapper implementation that's not 
well-behaved (in terms of returning a value that can be turned into a 
value binding) is going to cause this behavior.

I thought it'd be a simple case of catching the exception when the value 
binding expression is created (ReferenceSyntaxException from 
createValueBinding() or EvaluationException from getValue()), but it 
looks like the EL implementation I'm using (from Facelets) is throwing 
an implementation exception rather than the correct, documented 
exception -- I'm getting a com.sun.faces.el.impl.ElException from 
createValueBinding() (using the RI).

Is there any clean way to deal with this, since catching 
com.sun.faces.el.impl.ElException in Shale isn't really appropriate...

L.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Re: [shale] DefaultViewControllerMapper limitations

Posted by Laurie Harper <la...@holoweb.net>.
Craig McClanahan wrote:
> On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
>> Craig McClanahan wrote:
>>> On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
>>>> Thanks to my unusual use of view identifiers carrying path-extra-info
>>>> information, I've discovered a bit of a limitation with
>>>> DefaultViewControllerMapper: if the result of applying the mapping
>>>> algorithm isn't legal as a value binding expression, you get an ugly
>>>> stack trace. I triggered this because I have view identifiers which may
>>>> include spaces or other 'special' characters which, to be fair, the
>>>> Javadoc explicitly states you shouldn't do :-)
>>>
>>> There are some alternative ways to code a VB expression that might deal
>> with
>>> some of these issues.  It centers around the fact that, in EL
>> expressions
>>> (as in JavaScript), the following two expressions do the same thing:
>>>
>>>     foo.bar
>>>
>>>     foo['bar']
>>>
>>> so if the "bar" part of your expression has characters that would mess
>> you
>>> up ... a period is the most common one that I've run into ... use the
>> latter
>>> syntax.  This is paticularly handy, for example, when using
>> <f:loadBundle>,
>>> where the message keys in your properties file have periods in them:
>>>
>>>     <f:loadBundle name="messages" bundleName="com.mycompany.MyBundle"/>
>>>     ...
>>>     <h:outputLabel ... value="#{messages['username.label']}" .../>
>>>
>>> Looking at the bigger picture, any mapper implementation that's not
>>>> well-behaved (in terms of returning a value that can be turned into a
>>>> value binding) is going to cause this behavior.
>>>>
>>>> I thought it'd be a simple case of catching the exception when the
>> value
>>>> binding expression is created (ReferenceSyntaxException from
>>>> createValueBinding() or EvaluationException from getValue()), but it
>>>> looks like the EL implementation I'm using (from Facelets) is throwing
>>>> an implementation exception rather than the correct, documented
>>>> exception -- I'm getting a com.sun.faces.el.impl.ElException from
>>>> createValueBinding() (using the RI).
>>>>
>>>> Is there any clean way to deal with this, since catching
>>>> com.sun.faces.el.impl.ElException in Shale isn't really appropriate...
>>>
>>> See above.
>> You're talking about either changing what's in the view ID, or changing
>> how it's mapped. Both of those will fix the problem on a case-by-case
>> basis, sure.
>>
>> What I was getting at was more, can we make it so that a 'bad' view
>> controller name doesn't cause a blow-up? What I was going to propose was
>> changing ShaleViewController's setupViewController() method (and other
>> places which use the mapping manager) something like this:
>>
>>          // Retrieve an existing instance, or one created and configured
>> by
>>          // the managed bean facility
>> -       ValueBinding vb =
>> -           context.getApplication().createValueBinding("#{" + viewName
>> + "}");
>>          ViewController vc = null;
>>          try {
>> +           ValueBinding vb =
>> +               context.getApplication().createValueBinding("#{" +
>> viewName             Object vcObject = vb.getValue(context);
>>              if (vcObject == null) {
>>                  log.warn(messages.getMessage("view.noViewController",
>>                                               new Object[] { viewId,
>> viewName }));
>>                  return;
>>              }
>>              vc = (ViewController) vcObject;
>>          } catch (ClassCastException e) {
>>              log.warn(messages.getMessage("view.notViewController",
>>                                           new Object[] { viewId,
>> viewName }));
>>              return;
>> +       } catch (ReferenceSyntaxException e) {
>> +           // ... log an error/warning and return
>> +       } catch (EvaluationException e) {
>> +           // ... log an error/warning and return
>>          }
>>
>> The rationale is that
>>
>> a) Shale users may plug in a naive or broken mapper; it'd be nicer to
>> fail gracefully, letting them know what the problem is, rather than
>> throw an exception
>>
>> b) Third-party component libraries may (I think?) include navigation
>> rules in their bundled faces-config that point to view IDs which don't
>> conform to the constraints of whatever mapper may be installed
> 
> 
> Something like this does make sense ... let's be as explicit as we can when
> we run into probems.
> 
> That being said, in this case its still something *we* (Shale) are doing, by
> composing a value binding expression that might not be valid.  It's also
> worth figuring out if we can use an alternate syntax so that a vew
> identifier like "foo.bar" would still work.
> 
> But ... wait ... its even easier than that.  We should be using the
> VariableResolver directly, instead of composing a value binding expression.
> This won't care about the syntax, and will be a bit more efficient to boot.

So the variable resolver can look up variable names that contain 
arbitrary strings? That might work better.

Something that doesn't work as a value binding expression isn't going to 
be useble in your views for referencing the view controller, of course, 
but that's already a problem and at least it's probably a little more 
clear what's wrong then.

> I guess it could just be 'catch Exception' but that seems a little
>> over-protective ;-)
> 
> +1 ... exceptions from the view controller's constructor are the user's
> problem :-).

Heh :) Well, this isn't in the user's view controller, it's in 
ShaleViewController, but I take your point :-)

L.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Re: [shale] DefaultViewControllerMapper limitations

Posted by Craig McClanahan <cr...@apache.org>.
On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
>
> Craig McClanahan wrote:
> > On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
> >> Thanks to my unusual use of view identifiers carrying path-extra-info
> >> information, I've discovered a bit of a limitation with
> >> DefaultViewControllerMapper: if the result of applying the mapping
> >> algorithm isn't legal as a value binding expression, you get an ugly
> >> stack trace. I triggered this because I have view identifiers which may
> >> include spaces or other 'special' characters which, to be fair, the
> >> Javadoc explicitly states you shouldn't do :-)
> >
> >
> > There are some alternative ways to code a VB expression that might deal
> with
> > some of these issues.  It centers around the fact that, in EL
> expressions
> > (as in JavaScript), the following two expressions do the same thing:
> >
> >     foo.bar
> >
> >     foo['bar']
> >
> > so if the "bar" part of your expression has characters that would mess
> you
> > up ... a period is the most common one that I've run into ... use the
> latter
> > syntax.  This is paticularly handy, for example, when using
> <f:loadBundle>,
> > where the message keys in your properties file have periods in them:
> >
> >     <f:loadBundle name="messages" bundleName="com.mycompany.MyBundle"/>
> >     ...
> >     <h:outputLabel ... value="#{messages['username.label']}" .../>
> >
> > Looking at the bigger picture, any mapper implementation that's not
> >> well-behaved (in terms of returning a value that can be turned into a
> >> value binding) is going to cause this behavior.
> >>
> >> I thought it'd be a simple case of catching the exception when the
> value
> >> binding expression is created (ReferenceSyntaxException from
> >> createValueBinding() or EvaluationException from getValue()), but it
> >> looks like the EL implementation I'm using (from Facelets) is throwing
> >> an implementation exception rather than the correct, documented
> >> exception -- I'm getting a com.sun.faces.el.impl.ElException from
> >> createValueBinding() (using the RI).
> >>
> >> Is there any clean way to deal with this, since catching
> >> com.sun.faces.el.impl.ElException in Shale isn't really appropriate...
> >
> >
> > See above.
>
> You're talking about either changing what's in the view ID, or changing
> how it's mapped. Both of those will fix the problem on a case-by-case
> basis, sure.
>
> What I was getting at was more, can we make it so that a 'bad' view
> controller name doesn't cause a blow-up? What I was going to propose was
> changing ShaleViewController's setupViewController() method (and other
> places which use the mapping manager) something like this:
>
>          // Retrieve an existing instance, or one created and configured
> by
>          // the managed bean facility
> -       ValueBinding vb =
> -           context.getApplication().createValueBinding("#{" + viewName
> + "}");
>          ViewController vc = null;
>          try {
> +           ValueBinding vb =
> +               context.getApplication().createValueBinding("#{" +
> viewName             Object vcObject = vb.getValue(context);
>              if (vcObject == null) {
>                  log.warn(messages.getMessage("view.noViewController",
>                                               new Object[] { viewId,
> viewName }));
>                  return;
>              }
>              vc = (ViewController) vcObject;
>          } catch (ClassCastException e) {
>              log.warn(messages.getMessage("view.notViewController",
>                                           new Object[] { viewId,
> viewName }));
>              return;
> +       } catch (ReferenceSyntaxException e) {
> +           // ... log an error/warning and return
> +       } catch (EvaluationException e) {
> +           // ... log an error/warning and return
>          }
>
> The rationale is that
>
> a) Shale users may plug in a naive or broken mapper; it'd be nicer to
> fail gracefully, letting them know what the problem is, rather than
> throw an exception
>
> b) Third-party component libraries may (I think?) include navigation
> rules in their bundled faces-config that point to view IDs which don't
> conform to the constraints of whatever mapper may be installed


Something like this does make sense ... let's be as explicit as we can when
we run into probems.

That being said, in this case its still something *we* (Shale) are doing, by
composing a value binding expression that might not be valid.  It's also
worth figuring out if we can use an alternate syntax so that a vew
identifier like "foo.bar" would still work.

But ... wait ... its even easier than that.  We should be using the
VariableResolver directly, instead of composing a value binding expression.
This won't care about the syntax, and will be a bit more efficient to boot.

I guess it could just be 'catch Exception' but that seems a little
> over-protective ;-)


+1 ... exceptions from the view controller's constructor are the user's
problem :-).

L.


Craig

Re: [shale] DefaultViewControllerMapper limitations

Posted by Laurie Harper <la...@holoweb.net>.
Craig McClanahan wrote:
> On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
>> Thanks to my unusual use of view identifiers carrying path-extra-info
>> information, I've discovered a bit of a limitation with
>> DefaultViewControllerMapper: if the result of applying the mapping
>> algorithm isn't legal as a value binding expression, you get an ugly
>> stack trace. I triggered this because I have view identifiers which may
>> include spaces or other 'special' characters which, to be fair, the
>> Javadoc explicitly states you shouldn't do :-)
> 
> 
> There are some alternative ways to code a VB expression that might deal with
> some of these issues.  It centers around the fact that, in EL expressions
> (as in JavaScript), the following two expressions do the same thing:
> 
>     foo.bar
> 
>     foo['bar']
> 
> so if the "bar" part of your expression has characters that would mess you
> up ... a period is the most common one that I've run into ... use the latter
> syntax.  This is paticularly handy, for example, when using <f:loadBundle>,
> where the message keys in your properties file have periods in them:
> 
>     <f:loadBundle name="messages" bundleName="com.mycompany.MyBundle"/>
>     ...
>     <h:outputLabel ... value="#{messages['username.label']}" .../>
> 
> Looking at the bigger picture, any mapper implementation that's not
>> well-behaved (in terms of returning a value that can be turned into a
>> value binding) is going to cause this behavior.
>>
>> I thought it'd be a simple case of catching the exception when the value
>> binding expression is created (ReferenceSyntaxException from
>> createValueBinding() or EvaluationException from getValue()), but it
>> looks like the EL implementation I'm using (from Facelets) is throwing
>> an implementation exception rather than the correct, documented
>> exception -- I'm getting a com.sun.faces.el.impl.ElException from
>> createValueBinding() (using the RI).
>>
>> Is there any clean way to deal with this, since catching
>> com.sun.faces.el.impl.ElException in Shale isn't really appropriate...
> 
> 
> See above.

You're talking about either changing what's in the view ID, or changing 
how it's mapped. Both of those will fix the problem on a case-by-case 
basis, sure.

What I was getting at was more, can we make it so that a 'bad' view 
controller name doesn't cause a blow-up? What I was going to propose was 
changing ShaleViewController's setupViewController() method (and other 
places which use the mapping manager) something like this:

         // Retrieve an existing instance, or one created and configured by
         // the managed bean facility
-       ValueBinding vb =
-           context.getApplication().createValueBinding("#{" + viewName 
+ "}");
         ViewController vc = null;
         try {
+           ValueBinding vb =
+               context.getApplication().createValueBinding("#{" + 
viewName             Object vcObject = vb.getValue(context);
             if (vcObject == null) {
                 log.warn(messages.getMessage("view.noViewController",
                                              new Object[] { viewId, 
viewName }));
                 return;
             }
             vc = (ViewController) vcObject;
         } catch (ClassCastException e) {
             log.warn(messages.getMessage("view.notViewController",
                                          new Object[] { viewId, 
viewName }));
             return;
+       } catch (ReferenceSyntaxException e) {
+           // ... log an error/warning and return
+       } catch (EvaluationException e) {
+           // ... log an error/warning and return
         }

The rationale is that

a) Shale users may plug in a naive or broken mapper; it'd be nicer to 
fail gracefully, letting them know what the problem is, rather than 
throw an exception

b) Third-party component libraries may (I think?) include navigation 
rules in their bundled faces-config that point to view IDs which don't 
conform to the constraints of whatever mapper may be installed

I guess it could just be 'catch Exception' but that seems a little 
over-protective ;-)

L.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Re: [shale] DefaultViewControllerMapper limitations

Posted by Craig McClanahan <cr...@apache.org>.
On 1/5/06, Laurie Harper <la...@holoweb.net> wrote:
>
> Thanks to my unusual use of view identifiers carrying path-extra-info
> information, I've discovered a bit of a limitation with
> DefaultViewControllerMapper: if the result of applying the mapping
> algorithm isn't legal as a value binding expression, you get an ugly
> stack trace. I triggered this because I have view identifiers which may
> include spaces or other 'special' characters which, to be fair, the
> Javadoc explicitly states you shouldn't do :-)


There are some alternative ways to code a VB expression that might deal with
some of these issues.  It centers around the fact that, in EL expressions
(as in JavaScript), the following two expressions do the same thing:

    foo.bar

    foo['bar']

so if the "bar" part of your expression has characters that would mess you
up ... a period is the most common one that I've run into ... use the latter
syntax.  This is paticularly handy, for example, when using <f:loadBundle>,
where the message keys in your properties file have periods in them:

    <f:loadBundle name="messages" bundleName="com.mycompany.MyBundle"/>
    ...
    <h:outputLabel ... value="#{messages['username.label']}" .../>

Looking at the bigger picture, any mapper implementation that's not
> well-behaved (in terms of returning a value that can be turned into a
> value binding) is going to cause this behavior.
>
> I thought it'd be a simple case of catching the exception when the value
> binding expression is created (ReferenceSyntaxException from
> createValueBinding() or EvaluationException from getValue()), but it
> looks like the EL implementation I'm using (from Facelets) is throwing
> an implementation exception rather than the correct, documented
> exception -- I'm getting a com.sun.faces.el.impl.ElException from
> createValueBinding() (using the RI).
>
> Is there any clean way to deal with this, since catching
> com.sun.faces.el.impl.ElException in Shale isn't really appropriate...


See above.

L.


Craig