ICEfaces - JSF Integration
Dependency :
compile ":icefaces:0.3"
Summary
Installation
Type :
install-plugin icefaces
When icefaces-plugin is starting, a copy of the generated web.xml is done into /web-app/web-inf/web.xml. This is due to a tomcat plugin bug when fetching webXmlLocation property. Do a backup of your file or include it in your src/template/web.xml.
Description
Purpose
The plugin try to simplify JSF ICEfaces ( http://www.icefaces.org ) development and smooth JSF to Grails migration. It could be adapted for other frameworks but ICEfaces brings easy AJAX/AJAX push for today applications. JSF is like Spring before Grails, lot of xml. The plugin solves this by using multiple conventions for managed beans, el context, message bundle and detected navigation-case. You could also start project with this plugin by using static scaffolding provided. From some domain classes you can generate collaborative CRUD.- The base of this work is a work in progress migration of iceScrum ( http://www.icescrum.org ), an agile project management open source tool.
- You can see it as an alternative to integrated JSF frameworks such as JBOSS Seam.
- If you want to leverage groovy&grails power with grails plugins like spring web flow even using controllers/services to serve fragments or webservices, this one if your solution.
JSF-Icefaces-Facelet integration
- Bean By convention (no need for faces-config)
- Bean access to controller parameters (session,request,params...)
- Navigation Case by convention (extension auto added, local path searched, .redirect extension)
- Beans dynamic methods for navigation redirect(action?,bean?,view?,uri?,url?) and render(action?,view?,bean?),
- Automatic bean and service properties resolution
- 'void init()' called at bean initialization if present
- 'void dispose()' called at bean destruction if present
- ICEfaces Extended request scope ('page')
- 'RealTime changes' in dev mode : updates of your Beans and Views are pushed to browsers while running
- Access to web.xml-config configuration via IcefacesConfig.groovy
- Access to faces-config generated in web-app/faces-config.xml
- Converters for locale, currency, timezone
- i18n ready, fast access with #{msg['key']}
- create-bean script
- generate-bean, generate-views-icefaces, generate-all-icefaces : scaffolding for JSF collaborative application
- "Contextual push", allowing method invokation from target user contexts (manage session-page objects in minutes)
- Hibernate session managed from view rendering to view response
- Execute groovy code in EL expression ( #{ice.groov[' def i = 2; 3.times{ i++ }; i; ']} )
- easy access to ExpressionLanguage in beans : el "#{valueExpression}"
Extra methods for beans :
- push(String group?) - render target group (default:all),
- pushJavascript(String group?, String js) - call javascript on target group users (default:all),
- pushInvoke(String group?, Closure meth) - call closure from target group user contexts (default:all),
- pushInvokeInBean(String group?, Closure meth) - call closure from target group user bean contexts (default:all),
- javascript(String js) - call javascript on the actual request,
- redirect(action?,bean?,view?,uri?,url?),
- render(action?,view?,bean?)
- msg(code,default?,args?,locale?) - Bundle bindning
- joinChannel(String group) - join push channel
- leftChannel(String group) - left push channel
Sample code
Use of create-bean package.Class will do this :package appclass DummyBean{ def static scope = 'page' //['page' (icefaces special request scope),'request','session','globalSession' (portlet),'conversation'(swf),'flow'(swf)] def property = "hi" def oldProperty = "bye" //def otherBean (autowired bean) void init(){ //called when bean starts } void dispose(){ //called when bean stop } /*String action() { }*/ void say(javax.faces.event.ActionEvent ae) { pushJavascript "alert('${property}!');" // render "test2.iface" change view // redirect "test.iface" redirect view, forcing page scoped bean clean } void change(javax.faces.event.ActionEvent ae) { pushInvokeInBean { def changed = property property = oldProperty oldProperty = changed } } }
- "pushJavascript" is a new method you can use to broadcast javascript.
- "pushInvokeInBean" will replicate as many dummyBean registered (so as many page opened with option icefaces concurrent view at true). Note that closure resolve strategy is delegate first and the delegate is set on the specific target bean.
<?xml version='1.0' encoding='utf-8'?> <f:view xmlns:ice="http://www.icesoft.com/icefaces/component" xmlns:f="http://java.sun.com/jsf/core"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> </head> <body> <ice:form> <ice:outputText value="#{dummyBean.property}"/> <ice:commandButton value="say #{dummyBean.property}" actionListener="#{dummyBean.say}"/> <ice:commandButton value="prepare #{dummyBean.oldProperty}" actionListener="#{dummyBean.change}"/> </ice:form> </body> </html> </f:view>
Navigation by convention
Here some equivalents methods<ice:commandLink action="/bean/test.iface" /> <ice:commandLink action="/bean/test" /> <ice:commandLink action="test" /> <ice:commandLink action="test.iface" />
render action:"/bean/test.iface" //and the equivalents seen before render "/bean/test.iface" // == render action:* render view:"test" // == /bean/test.iface render bean:"bean2" // /bean2/index.iface render bean:"bean2",view:"test" :// /bean2/test.iface
redirect url:"www.google.fr" redirect action:"test" render action:"test.redirect" <ice:commandLink action="test.redirect" />
Greets
- Thanks to Grails team for the work they do ! http://www.grails.org
- Thanks to ICEsoft team for the fantastic UI framework ! http://www.icefaces.org
- This is a contribution offered by my consulting company doc4web : http://www.doc4web.com
- This is on behalf of a work in progress with iceScrum : http://www.icescrum.org