楼主: Sky-Tiger

JSF 2 : Event handling, JavaScript, and Ajax

[复制链接]
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
21#
 楼主| 发表于 2009-7-24 22:13 | 只看该作者
Adding GMaps4JSF to your Maven2 application

    * all what you should do is adding this to your pom.xml:

          <repositories>
              ...
              <repository>
                  <id>googlecode.com</id>
                  <url>http://gmaps4jsf.googlecode.com/svn/trunk/gmaps4jsf-repo</url>
              </repository>
              
          </repositories>   

          <dependencies>
              ...   
              <dependency>
                  <groupId>com.googlecode.gmaps4jsf</groupId>
                  <artifactId>gmaps4jsf-core</artifactId>
                  <version>1.1.1</version>
              </dependency>  
          </dependencies>

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
22#
 楼主| 发表于 2009-7-24 22:13 | 只看该作者
Notes

    * GMaps4JSF do not lock the door in the Javascript face as it allows accessing the map from Javascript by providing the (jsVariable) attribute in the components.
    * GMaps4JSF supports Facelets.
    * GMaps4JSF supports Portlets.
    * All the GMaps4JSF features are shown in the Demo http://mashups.s43.eatj.com/gmaps4jsf-examples/home.jsf.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
23#
 楼主| 发表于 2009-7-24 22:14 | 只看该作者
Online Demos

    * http://mashups.s43.eatj.com/gmaps4jsf-examples/home.jsf, It demonstrates the library features.
    * http://mashups.s43.eatj.com/gmaps4jsf-examples/pages/mashups.jsf, It shows the power of Apache Tomahawk + Ajax4JSF + GMaps4JSF.
    * http://mashups.s43.eatj.com/gmap ... dad/faces/demo.jspx, It shows the power of Apache Trinidad PPR + GMaps4JSF 1.1.1.
    * http://mashups.s43.eatj.com/gmap ... dad/faces/demo.jspx, It shows the power of Apache Trinidad PPR + GMaps4JSF 1.1.2.
    * http://mashups.s43.eatj.com/gmaps4jsf1.1.1-facelets/, It shows the power of Facelets + GMaps4JSF.
    * http://mashups.s43.eatj.com/gmaps4jsf-push/, It shows GMaps4JSF working with Ajax PUSH.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
24#
 楼主| 发表于 2009-7-24 22:14 | 只看该作者
Including scripts in JSF 2 Ajax requests
Posted by driscoll on July 18, 2009 at 03:39 PM | Permalink | Comments (0)

I'd wanted to blog some time ago about including scripts in your JSF ajax requests, but Hazem Saleh beat me to it. Hazem is the creator of the nifty Google Maps component for JSF, gmaps4jsf.

So, go and follow the link, but I'll just add three short comments to Hazem's blog:

    * In many popular ajax solutions for JSF, <script> tags were simply interpreted in place. This is not, for whatever reason, part of the JSF spec right now - so you'll have to use one of the two ways that Hazem describes, in order for it to be a portable solution.
    * The first solution Hazem notes uses the event system for JSF client side - it simply adds an event listener that's called every time a page is updated, and calls the eval for any includes scripts.
    * The second solution is the "preferred" way that specified in the spec - simply return the script you want to execute as part of the xml that goes to the client.

Hope this note helps someone trying to execute an arbitrary script on a JSF client page.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
25#
 楼主| 发表于 2009-7-24 22:14 | 只看该作者
JSF 2 Beta 2 released
Posted by driscoll on July 16, 2009 at 12:21 PM | Permalink | Comments (0)

The Mojarra team are proud to announce the release of our Beta 2 version of Mojarra 2.0, implementing the PFD version of the JavaServer Faces 2.0 spec.

You can find it on our downloads page, as well as in the GlassFish Update Center. And as always, be sure to check the release notes for more information.

We're targeting the FCS release of JSF 2 to coincide with Java EE 6, so expect that to happen in a few months.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
26#
 楼主| 发表于 2009-7-24 22:14 | 只看该作者
A tale of two components (JSF2)
Posted by driscoll on July 03, 2009 at 12:44 PM | Permalink | Comments (0)

Today, I'd like to take a look at two different ways to create a poll component. Poll components are a way to periodically update a page with new information. We'll take a look at examples of these in a second, but first, a caveat: I've assumed throughout my blogs on Ajax components in JSF that you have at least a passing familiarity with JavaScript. This post assumes a bit more knowledge of JavaScript than some other posts. I'll try to explain what I'm doing as I go along, but if you find yourself mystified by closures, I'd like to suggest the book JavaScript: The Good Parts. It's a wonderful book, and quite short. Check it out.

With that out of the way, here's how you'd use these two poll components within a page:

Count:<br/>
<hutputText id="target" value="#{count.count}"/><br/>
<ezolltag id="poll" interval="200" timeout="5000" render=":form:target"/>
<hutputText id="target2" value="#{count.count2}"/>
<ezoll id="poll2" interval="1000" timeout="10000" render="form:target2"/>

Let's go over what this does: We have a two components, polltag and poll. They each have three attributes, interval (how often to refresh the target), timeout (when to stop), and render (the target we'll refresh). These tags are identical in function, with the only difference being the format of their render attribute (more on that momentarily) and the method they use to make the Ajax call. Run this page, and you'll see the numbers increment - one quickly, and the other more slowly (count.count just increments every time it's accessed).

Let's start by taking a look at the polltag component. I decided to start with just a quick, naive component that uses the Ajax tag. Let's take a look at what that tag looks like (resources/poll/polltag.xhtml):

<cc:implementation>
    <span id="#{cc.clientId}">
    <hutputScript name="poll/polltag.js" target="head" />
        <h:commandButton id="hidden" type="button" style="display: none;">
            <f:ajax render="#{cc.attrs.render}"/>
        </h:commandButton>
    </span>
    <script type="text/javascript">
        jsfdemo.polltag.init("#{cc.clientId}","#{cc.attrs.interval}", "#{cc.attrs.timeout}";
    </script>
</cc:implementation>

For those of you following my previous blogs, much of this isn't new: We wrap the whole component to get a span on the page with the supplied id. We include a script (resources/poll/polltag.js) which adds the backing JavaScript. We also inject a small script which calls that backing JavaScript function. And that injected script includes the necessary context to allow multiple tags to be placed in the page.

But the new thing here is that we're including a hidden button, and attaching an Ajax tag to it. That Ajax tag will then inject code that activates when the button is clicked. Since the button is hidden, we'll "click" the button programatically, inside the init function. Let's take a look at that backing JavaScript.

if (!window.jsfdemo) {
    var jsfdemo = {};
}

if (!jsfdemo.polltag) {
    jsfdemo.polltag = {};
}

if (!jsfdemo.polltag.init) {
    jsfdemo.polltag.init = function init(id, inc, to) {
        var componentID = id;
        var increment = inc;
        var timeout = to;
        var elapsed = 0;
        var token = null;

        // If increment isn't set, or it's less than some reasonable value (50) default to 200ms
        if (isNaN(increment) || increment <= 50) {
            increment = 200;
        }
        // If timeout isn't set, default to no timeout
        if (isNaN(timeout) || timeout == 0) {
            timeout = -1;
        }

        var poll = function poll() {
            var hiddenID = componentID + ":" + "hidden";
            var hidden = document.getElementById(hiddenID);
            hidden.click();  // this executes the ajax request
            if (timeout != -1) {
                // Not an accurate timeout - but simple to compute
                elapsed += increment;
                if (elapsed > timeout) {
                    window.clearInterval(token);
                }
            }
        }

        token = window.setInterval(poll, increment);
    }
}

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
27#
 楼主| 发表于 2009-7-24 22:14 | 只看该作者
OK, this is a little long, let's break it down to see what's going on here.

First, we do namespacing: by creating objects, and placing the function onto that object, we make sure that we don't accidentally have two init() functions in a page - such as when we're creating two different poll tags with init functions. We also need to check if those objects already exist before creating them - after all, we may want to have multiple namespaces placed onto the "jsfdemo" object.

Then, we define a module - we have an init() function, and inside that init() function, we also define a poll() function. The poll() function has access to the variables inside the init() function, but calling the init function multiple times results in multiple contexts. This is a pretty common pattern in JavaScript, but it does look awkward to folks coming from Java.

At the end of the file, after setting up the poll() function, we have the line:

token = window.setInterval(poll, increment);

Which sets up the poll - we're simply using the JavaScript setInterval function to periodically call the poll() function, every increment milliseconds.

When the poll function is called, we find the button, and click it. This will, in turn, trigger the Ajax call. Then, we determine if the timeout time has come, and if it has, we turn off the timer with the clearInterval call.

OK, a little kludgy - but it works, after a fashion. There are some problems with this approach: Since we're using the f:ajax tag, we need to use the UIComponent.findComponent syntax for locating the target to update - some may prefer this, some won't. And while having a button that you could "unhide" to restart the poll might be handy, in general it's just cluttering up your page. Also, if the server stops responding for some reason, you'll get pummeled with error alerts if you're in development mode.

So, let's go ahead and rewrite this to instead use the jsf.ajax.request function, provided by jsf.js in JSF 2.

We'll only have to make a few quick changes to do this, as well as adding error handling. First, in the component page, we'll say add an output script call. And, we'll also change the call to init to be wrapped inside a jsf.ajax.addOnError function call. This will add a function to the list of listeners that get called if there's an error on the page. Note that the init function itself is not the function that will get added - rather, it's return value will be what's added. And we'll make that return value be a function (you'll see it in a second). We also remove all the markup associated with the button.

<cc:implementation>
    <span id="#{cc.clientId}">
        <hutputScript name="jsf.js" library="javax.faces" target="head"/>
        <hutputScript name="poll/poll.js" target="head" />
    </span>
    <script type="text/javascript">
        /* <![CDATA[ */
        jsf.ajax.addOnError(jsfdemo.poll.init("#{cc.clientId}","#{cc.attrs.interval}", "#{cc.attrs.timeout}", "#{cc.attrs.render}");
        /* ]]> */
    </script>
</cc:implementation>

In the backing JavaScript, we're going to have to make two changes. We'll have to change the poll function, and we'll have to add a return value to the init function. Here's the entirety of the backing JavaScript file:

if (!window.jsfdemo) {
    var jsfdemo = {};
}

if (!jsfdemo.poll) {
    jsfdemo.poll = {};
}

if (!jsfdemo.poll.init) {
    jsfdemo.poll.init = function init(id, inc, to, rend) {
        var componentID = id;
        var increment = inc;
        var timeout = to;
        var elapsed = 0;
        var token = null;
        var render = rend;

        // If increment isn't set, or it's less than some reasonable value (50) default to 200ms
        if (isNaN(increment) || increment <= 50) {
            increment = 200;
        }
        // If timeout isn't set, default to no timeout
        if (isNaN(timeout) || timeout == 0) {
            timeout = -1;
        }

        var poll = function poll() {
            jsf.ajax.request(componentID, null, {render: render});
            if (timeout != -1) {
                // Not an accurate timeout - but simple to compute
                elapsed += increment;
                if (elapsed > timeout) {
                    window.clearInterval(token);
                }
            }
        }

        token = window.setInterval(poll, increment);

        return function cancelPoll(data) {
            if (data.source.id == componentID) {
                window.clearInterval(token);
            }
        }
    }
}

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
28#
 楼主| 发表于 2009-7-24 22:15 | 只看该作者
Let's look at the return value first:

return function cancelPoll(data) {
    if (data.source.id == componentID) {
        window.clearInterval(token);
    }
}

We add this at the end of the init function - which means that init will return this function as it's return value, and that this function will be what's added to the list of listeners that get called when there's an error. Because this function will get called regardless of what component causes the error, we add a check to make sure that the current component is the one that got the error. And, as in the poll function, because this function is defined inside init, it has access to all of the context that's there when init is called - in this case, the componentID variable, passed in by the script tag in the component.

The changes for the poll function to use jsf.ajax.request are relatively straightforward:

var poll = function poll() {
    jsf.ajax.request(componentID, null, {render: render});
    if (timeout != -1) {
        // Not an accurate timeout - but simple to compute
        elapsed += increment;
        if (elapsed > timeout) {
            window.clearInterval(token);
        }
    }
}

Much simpler than the corresponding code surrounding the tag method.

As always, this code can be found in the jsf-demo/ajax-components directory of the Project Mojarra codebase. You'll find this and much more code there, including most of the code I've blogged about in the past.

If you have questions, please let me know in the comments section.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
29#
 楼主| 发表于 2009-7-24 22:15 | 只看该作者
Automatic compression of jsf.js
Posted by driscoll on July 03, 2009 at 10:45 AM | Permalink | Comments (2)

Just a quick note that we've now added automatic compression of the jsf.js file served by JSF 2. The file size of jsf.js, 71k uncompressed, comes to about 16k compressed (there are a lot of comments in there).

There is no user action required to make this happen: If the Project stage is Development, the file is served uncompressed (for ease in debugging with something like Firebug), but if the Project stage is anything else, then the file is compressed (and essentially unreadable, since besides stripping all comments, variable names are stripped, as well as all line breaks).

To enable Project Stage as Development, place the following in your web.xml file:

    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
30#
 楼主| 发表于 2009-7-24 22:15 | 只看该作者
Learning JSF 2
Posted by driscoll on June 17, 2009 at 06:07 PM | Permalink | Comments (5)

Not too long ago, I heard someone complain that the JSF tutorial wasn't ready yet. Now, that's not surprising - the tutorial writing process (for that matter, the book writing process) doesn't actually start until the spec is more or less final, and the implementation is at least Beta (meaning feature complete).

But that raises the question: Suppose you're eager to get started. How do you learn about JSF 2 before all the user-friendly books have been written?

I suggest you go about it the way I do - here's the resources that you can use now, while waiting for the books that will come out.

Read online articles and blogs: This is probably the most obvious suggestion, if you're already here - just paging backward in this blog will get you some good information. But that really only gives you a very limited set of examples.

Read the PDL docs: Here's one that surprises me - most folks don't seem to know that every standard tag is documented in the PDL Docs. While the language of these docs can be a little overspecific and dry, of all of the standard JSF documetation, I find this the most useful.

Read the JSDocs: Not a surprising is that most folks don't realize that we have a standard set of documentation for the JavaScript API for JSF. Again, it's a bit overspecific (it's written that way, in part, because it serves as formal specs in addition to docs), but it does have a lot of good information.

There's also the JavaDocs and the Spec itself, but if often difficult to find something in there unless you know what you're looking for, so instead I recommend you...

Check out the demos: Project Mojarra has a bunch of demo programs, and many of them are really, really simple examples of things you can do with JSF 2. There's also a fair bit of cruft in there, waiting for us to clean it up, but it's probably worth your while. I recommend checking out any demo with "basic" or "ajax" in it's name, as a start. To do this, of course, you'll have to check out the Project Mojarra Source Code (check in the directory marked "jsf-demo"), but that's not such a high bar - it's not necessary to build it to get something out of the demos.

And of course, most importantly:
Ask questions: There's the mail alias, webtier@dev.glassfish.java.net - which requires subscription, but you'll want to see other people's questions anyway. I promise you, the entire dev team reads that alias. There's the JSF Forum - where a lot of really savvy users hang out, helping each other. There's an IRC channel too, ##jsf at irc.freenode.net - where you'll often find folks from all over the JSF world.

So, to sum up, if you're a bit adventurous and ready to start right now, there's a lot of things that'll get you going. And the books will be along shortly, never fear.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表