[jsr-314-open] h:outputScript doesn't work inside composite components

Alexandr Smirnov asmirnov at EXADEL.COM
Mon May 18 18:04:46 EDT 2009


This is a problem because built-in resources handled on static way only.
We have a dynamic resource handler in the RichFaces project that allows
to put EL-expressions into CSS or JavaScript body, performs compressions
 and so on. To avoid using of session or other scope beans and make
resources cacheable parameters could be encoded into URL body. I'm going
to extend JSF 2.0 resource loading to support these features, therefore
it may be contributed into the JSF 2.1.

David Geary wrote:
> 
> 
> 2009/5/11 Jim Driscoll <Jim.Driscoll at sun.com <mailto:Jim.Driscoll at sun.com>>
> 
>     On 5/11/09 9:30 AM, David Geary wrote:
> 
>         2009/5/11 Ryan Lubke <Ryan.Lubke at sun.com
>         <mailto:Ryan.Lubke at sun.com> <mailto:Ryan.Lubke at sun.com
>         <mailto:Ryan.Lubke at sun.com>>>
> 
> 
>            On 5/11/09 7:40 AM, David Geary wrote:
> 
>                I have a login composite component that looks like this:
> 
>                <composite:interface>...</composite:interface>
>                ...
>                <composite:implementation>
>                <script type="text/javascript">
>                                function checkForm(form) {
>                                  var name =
>         form['#{cc.clientId}:name'].value;
>                                  var pwd =
>         form['#{cc.clientId}:password'].value;
> 
>                                  if (name == "" || pwd == "") {
>                                    alert("Please enter name and password.");
>                                    return false;
>                                  }
>                                  return true;
>                                }
>                </script>
>                  ...
>                </composite:implementation>
> 
>                I have components with "name" and "password" component
>         ids in a
>                form in the ... part of the implementation. That works fine.
> 
>                However, if I pull the JS out into its own file, and do this:
> 
>                <composite:interface>...</composite:interface>
>                ...
>                <composite:implementation>
>                <h:outputScript library="components/login" name="login.js"/>
>                  ...
>                </composite:implementation>
> 
>                h:outputScript puts the JS in the page, but the JS no longer
>                works because the expression cc.clientId evaluates to an
>         empty
>                string.
> 
>                That's a bug, is it not?
> 
>            No, I don't believe it is.  The javascript file will be
>         served in a
>            separate request.  There is no way to determine the
>            component at that time.
> 
> 
>         That's what I figured, but that's not going to be obvious to the
>         average
>         developer. This is a pretty serious violation of the principle
>         of least
>         astonishment, and JSF has enough of those violations, IMO.
> 
>         If there's no way to make it work, it should be documented,
>         preferably
>         in the pdl (or is it vdl now?) docs that h:outputScript will not
>         work
>         when the corresponding JS references a composite component.
> 
> 
>     I agree that we should document how to do this:  Which is why I
>     wrote a demo that does this (basic-ezcomp/spinner-final) - and
>     blogged about it
>     http://weblogs.java.net/blog/driscoll/archive/2008/11/jsf_20_writing.html
> 
>     The problem is not solvable the way that you think it is:  I
>     struggled with this too, until Ryan walked me through it.  The
>     problem is one of the web, not one of the JSF, exactly.
> 
>     So, look at it this way:  The JavaScript file is served ONCE, from
>     ONE known address.  This is good - it allows us to cache the
>     javascript file.  This is bad - because we do the # variable
>     substitution *before* we serve the file, we can't do #{cc}
>     substitutions in it, that file could (and will) be shared across
>     views - and even across different websurfing sessions, after all,
>     that's the whole point of the resource mechanism...  Efficient use
>     of caching for resources.
> 
>     So, how to address this?  One way is in the demo - just set the
>     cc.clientId as a context, and use that context in the function calls.
>     In a different demo (ajax-switchlist) I save that context into
>     state, and use that in each call.  Either way works, and both
>     require about four lines of (javascript) code.
> 
>     If you make it so that we make those substitutions into the
>     javascript file, then you also need to output that javascript file
>     with a view unique name.  And that's probably a bad idea for most
>     uses, since that shoots caching in the head.  We could add a
>     "perview" attribute to each resource, I guess, but since the
>     workaround is so easy, once you know it, and the cost is the loss of
>     caching, I'd argue this isn't a good idea.
> 
>     I urge you to run through the demos I wrote (basic-ajax,
>     basic-ezcomp, basic-ajax-edittext, ajax-switchlist)  - they're all
>     small, and in each of them, I try to tackle one small problem and
>     solve it.  In many of them, I ran into problems just like this, and
>     worked through them. They're not documented (except in blogs), but
>     they are all small pieces of code.
> 
> 
> Okay, I'll do that. Thanks for the insights--I hadn't stopped to think
> about caching.
> 
> 
> david
> 
> 
> 
>     Jim
> 
> 




More information about the jsr-314-open-mirror mailing list