Tuesday 25 March 2014

PrimeFaces, JSF and Groovy integration

What to do if you want to add code dynamically to Jave EE application but you don't want to reload application every time? The answer is smiple add Groovy to your application. You don't have to learn Groovy language. Groovy's scripts can be written just in Java.

Suppose we want to implement in Groovy script p:commandButton action property and use it like this:


where beanTestowy is a Java Bean, groovyObject is type of Object and action is a method we want to implement in Groovy script.

The only requirement: Groovy class has to be derived from Java class. In other words yout have to create java class with interface you want to implement later in Groovy.

AikCmsBeanMethod.java

public class AikCmsBeanMethod implements Serializable
{
    /**
     * Serial version UID
     */
    private static final long serialVersionUID = -228352962604439051L;
    /**
     * Logger object
     */
    static Logger logger = Logger.getLogger(AikCmsBeanMethod.class);
    /**
     *
     */
    protected BasicWidgetBean bean;

    /**
     * Default constructor
     */
    public AikCmsBeanMethod()
    {

        super();

        logger.debug("AikCmsBeanMethod object has been created");
    }
    /**
     * @param bean
     */
    public AikCmsBeanMethod(BasicWidgetBean bean)
    {

        this();

        this.bean = bean;
    }
    /**
     * Action method
     * @return
     */
    public String action()
    {

        logger.debug("Default action() called");

        return null;
    }
    /**
     * @param argument
     * @return
     */
    public String action(Object argument)
    {
        logger.debug("Default action(Object arg) called");

        return null;
    }
    /**
     * @param arg
     * @param arg1
     * @return
     */
    public String action(Object arg, Object arg1)
    {
        logger.debug("Default action(Object arg, Object arg1) called");
        return null;
    }
    /**
     * @param arg
     * @param arg1
     * @param arg2
     * @return
     */
    public String action(Object arg, Object arg1, Object arg2)
    {
        logger.debug("Default action(Object arg, Object arg1, Object arg3) called");
        return null;
    }
    /**
     * @param vce
     */
    public void valueChangeListener(ValueChangeEvent vce)
    {
        logger.debug("valueChangeListener called");
        logger.debug("Old value: " + vce.getOldValue() + " New value: " + vce.getNewValue());
    }
    /**
     * PrimeFaces p:ajax listener
     */
    public void pAjaxListener()
    {
        logger.debug("Defautl PF ajax listener called");
    }
    /**
     * PrimeFaces p:ajax listener
     * @param argument
     */
    public void pAjaxListener(Object argument)
    {
        logger.debug("Default PF ajax listner caledd pAjaxListener(Object arg)");
    }
    /**
     * JSF native f:ajax listener
     * @param event
     */
    public void jsfAjaxListener(AjaxBehaviorEvent event)
    {
        logger.debug("Default jsfAjaxListener called jsfAjaxListener(AjaxBehaviorEvent event)");
    }
    /**
     * @return the bean
     */
    public BasicWidgetBean getBean()
    {
        return bean;
    }
    /**
     * @param bean the bean to set
     */
    public void setBean(BasicWidgetBean bean)
    {
        this.bean = bean;
    }
    /**
     * @param event
     */
    public void treeNodeSelectEvent(NodeSelectEvent event)
    { 
    }
    /**
     * @param event
     */
    public void treeNodeUnselectEvent(NodeUnselectEvent event)
    {
    }
    /**
     * @param event
     */
    public void treeNodeCollapseEvent(NodeCollapseEvent event)
    { 
    }
    /**
     * @param event
     */
    public void treeNodeExpandEvent(NodeExpandEvent event)
    { 
    }

Above class is from my AIK CMS project. The next step is to create Groovy script GroovyTestBean.groovy.

GroovyTestBean.groovy

public class GroovyTestBean extends aik.cms.widget.bean.method.AikCmsBeanMethod
{
    public String action()
    {
        println 'Action called'
        return super.action();
    }
    public void pAjaxListener()
    {
        println 'PrimeFaces ajax listener called'
    }
}
In order to use our Groovy scirpt like this:



we need access to Groovy object in java bean. In other words we have to load GroovyTestBean object from the script.

 public Object getGroovyObject()
 {
        Object myObject = null;

        try
        {
            String            groovy      = AikCms.getInstance().getValue(AikCms.AIK_CMS_PATH) +   File.separator + "aik" + File.separator + "groovy" + File.separator;
            FileInputStream   inputStream = new FileInputStream(groovy + "GroovyTestBean.groovy");
            String            everything  = IOUtils.toString(inputStream);
            GroovyClassLoader gcl         = new GroovyClassLoader();
            Class             clazz       = gcl.parseClass(everything, "GroovyTestBean.groovy");
            Object            aScript     = clazz.newInstance();
            myObject                      = aScript;           
        }
        catch (ResourceException | ScriptException | IOException | InstantiationException | IllegalAccessException e)
        {
            logger.error(e.getMessage());
        }       

        return myObject; // This is our Groovy object
} 
 
myObject - is our GroovyTestBean object loaded from GroovyTestBean.groovy script.

This is a short video from my YouTube channel. It shows that it works ;) http://youtu.be/WPW53GZkHDE