Screenshots •  Videos •  Demos •  Documentation •  Tutorials •  Articles •  Knowledge Base •  Zone


Spring, Scripting, POJOs and more

Adding scripting support to XUI

Scripting should be a natural complement to XUI. With most of the plumbing taken care of by the framework there is normally very little Java code, but even so having the extra capabilities of a language such as Groovy should be useful in simplifying application development in certain domains.

Being able to modify and execute quickly without reloading the application could be a real time saving during development. However XUI's support for scripting is not just about saving development time, but it is also part of the effort to better support html based rendering for XUI applications. For the html support JavaScript support will be extended in much the same way as the Groovy support has been integrated.

It is possible that a common scripting framework based upon JSR 223 will be added, but before we do that we will need to create a Java 6 build and that creates its own problems. XUI already supports several JDKs and this is quite an overhead and in some case a restriction on what can be achieved.

One option is to make more extensive use of programming through interfaces and dependancy injection as this would allow for more plugability, much as Spring uses dependancy injection. The downside of this is that it may require multiple implementations and hence as much or more code than the current implementation, but this may be inevitable.

XUI has had scripting support for some time, but it was limited to the valuation of attributes and scripts invoked via the attribute evaluation. With the new scripting support the complete page functionality can be implemented by a script and not only is this support more extensive but it is also simpler as the script methods do not need to be explicitly identified as script methods within the page XML. The new scripting support extends the script engine approach used in XUI 3 and it should not be a huge leap to provide JSR 223 support.

An example of this new support is shown below:

PojoPanels

XUI 3.0 introduced support for POJOs and within the editor plugins panels or forms could be generated for the POJOs semi automatically. XUI 4 provides this support at runtime, for example the following XML


<?xml version="1.0" encoding="UTF-8"?>
	<XPage w="1016" h="734" class="com.myproject.MyController">
	    <Components>
	        <Panel title="My Form" border="0" layout="border">
	          <PojoPanel 
	              name="myForm" 
	              constraint="center" 
	              style="base" 
	              pad="6" 
	              spacing="4" 
	              numCols="2" 
	              dataPath="pojo/myModel/myDataObject" 
	              alwaysDirty="true" 
	              methods="save"
	              fieldValidationRule="MyValidationRule"
	              class="com.myproject.transfer.MyDataObject"
	              fieldOrder="a,c,d,b,f"/>            
	          <Panel constraint="south" layout="flow" 
                    align="center" style="base" 
                    hgap="6" vgap="6">            
	            <Button name="saveBtn" content="Save"/>            
	          </Panel>
	        </Panel>
	    </Components>
	    <Events>
	      <Event target="saveBtn" 
              method="${pojo/myModel.saveStuff(pojo/model/myDataObject)}" 
	            type="com.xoetrope.pojo.SaveBeforeActionHandler"/>
	    </Events>
	        <Validations>
	            <Validation rule="MyValidationRule" 
              target="myForm" 
              dataPath="pojo/myModel/myDataObject"/>
	        </Validations>
   </XPage>

takes a POJO and creates a form, binding the UI components to the input fields and validates inputs (see wiki for details). The above xml gets rendered as:

Spring support

Leveraging the POJO support and runtime form generation enables XUI to used effectively for Spring applications. Spring's remoting technology can expose beans to a remote client and XUI can pick these beans up and create forms and tables for the beans. The PojoPanel described above makes it possible to quickly and easily configure the UI for these beans with little or no coding.

Going one step further it is also possible to provide hints to the panel generation to control various aspects of the UI including styling other attributes of the appearance and behavior. At the core of the support for Spring is the use of reflection and bean inspectors to determine the field types and bean methods. However additional glue logic is provided on the basis that the beans and their attributes are named and handled consistently. Therefore a bean can be bound to UI component and validated against other Spring beans provided that this use of property names is consistent.

With so much provided by XUI creating a Spring based application requires little other than wiring the beans together. The most important requirement in this process is to wire the Spring beans into XUI's data model. Normally an application will have some class of root access point, service facade or some object that ties the various beans together into a session or context of some sort. XUI needs this object to be mapped into the XUI data model, and this can be done as follows:


public class MyPojoRoot extends XPojoContext implements PojoValidator
{
  ...
  
  /**
   * Instantiated by the POJO bindings at startup.
   */
  public MyPojoRoot()
  {
    try {
      applicationContext = new ClassPathXmlApplicationContext( new String[] { 
        "spring-config-file-A.xml", 
        "spring-config-file-B.xml" } 
      );
      
      serviceInterface = (SomeBean)applicationContext.getBean( "someBean" );
    } 
    catch ( BeansException be ) {
      be.printStackTrace();
    }
  }
    
  public static MyPojoRoot getInstance( XProject project )
  {        
    MyPojoRoot rootPojo = (MyPojoRoot)project.getObject( "MyPojoRoot" );    
    if ( rootPojo == null ) 
      rootPojo = new MyPojoRoot();
    
    rootPojo.setProject( project );
    
    return rootPojo;
  }

  public Object getRoot()
  {
    return getInstance( project );
  }

  public void setProject( XProject p )
  {
    project = p;
    pageMgr = project.getPageManager();
    project.setObject( "MyPojoRoot", this );  
  }

  public void configure( URL configFileURL )
  {
    rootModel = project.getModel();    
  }
  
  public void modelLoaded()
  {
  }
  //---------------------------------------------------------------------------
 
  /**
   * Lookup some other bean
   */
  public IOtherBean getOther()
  {
    if ( other == null )
      other = (IOtherBean)serviceInterface.getOtherBean();

    return other;
  }  

  //-Validation----------------------------------------------------------------
  /**
   * Validate the pojo
   * @param obj
   * @return the validation result
   */
  public Object validate( Object obj )
  {
    return serviceInterface.validate( obj );
  }

  /**
   * Validate a field/property of the pojo
   * @param obj
   * @param fieldName
   * @return the validation result
   */
  public Object validate( Object obj, String fieldName )
  {
    return serviceInterface.validate( obj, fieldName );
  }
}

The above code also handles the interface to the validation of POJOs.

Once the root of the POJO model has been added it may be convenient to wrap the root POJO with some additional access functions so that various nodes can be more eassily accessed. For example an application often uses the concept of a current node or current object and this may not be provided explicitly by the POJOs. The root node or model nodes hanging of the root might be a good point to wrap the POJOs and add additional functionality. The root node is also a good point to load Spring's configuration files