Sign in to edit and +1 items.
Login required
Download

ICEfaces - JSF Integration

(2)
Author(s) Stephane MALDINI
Current Release 0.3   (1 year ago)
Grails Version 1.2.0 > *
Tags
Dependency
compile ":icefaces:0.3"
Last updated by smaldini 2 years ago
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.
Last updated by smaldini 2 years ago

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.
There is also a JSF 2 port available.

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
*UPDATED on release 0.1 (+) el "#{valueExpression}" : resolve EL expression

_ This is an Early Release, be cool if bugging ;) Main objective was JSF Icefaces integration. JSF 2 impl coming.

Sample code

Use of create-bean package.Class will do this :

package app

class 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.
Here the text.jspx page (called via configured extension, by default text.iface)

<?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" />

From bean you can use

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

Sample redirect convention

redirect url:"www.google.fr"
redirect action:"test"
render action:"test.redirect"
<ice:commandLink action="test.redirect" />

Greets

Last updated by smaldini 2 years ago

What is a bean by convention ?

A groovy/java class placed in grails-app/beans using XxxxBean.java/.groovy conventionnal name.

How can I access to these beans from EL expression ?

Simply use property styled name : XxxBean becomes #{xxxBean}

Where do I put my jspx ?

In grails-app views or in web-app.

Can I still use faces-config.xml ?

Yes, you find it in web-app/web-inf/faces-config.xml. Update already established parameters if you know what you do :) Note the old managed bean are not resolved automatically. Use FacesContext at init method to set these ones.

What is icefaces scaffolding ?

From a grails domain class (@entity or domain/domainClass), you can generate a bean and 4 pages in grails-app/views/entityName/ : list.jspx, create.jspx, edit.jspx, show.jspx. For this complete generation, type "grails generate-all-icefaces <package>.<Entity>". A simple collaborative CRUD will be generated.

What is Contextual Push ?

ICEfaces allows server initiated push (use dynamic method "push" in beans). If your users page scoped bean get some UI properties (selected for instance) and you want to force their beans to refresh these ones after some actions, contextual push is your solution. PushInvoke and pushInvokeinBean provide the possibility to interact with each registered context. You can set a property at false for each bean connected, refreshing each view with new values before rendering.

Is there some limitations ?

Yes unfortunnely, as initiated server push is not a true request you can't access to these properties ("request","session","webrequest", "params"...). I advise to clearly separate push methods from action/actionListener method.
Last updated by smaldini 2 years ago