3 Replies Latest reply on Jun 4, 2009 11:22 AM by Ales Justin

    mc-script - and other stupid ideas

    Adrian Brock Master

      I got a bit bored yesterday so I decided to write an example that shows how
      easy it is to extend the microctonainer's value system.
      (Actually the example really shows off JBossXB's xml any handling).

      By way of a stupid example, I decided to write a new ValueMetaData that
      determines its values using the Java6 script engine stuff.
      (As usual change svn to anonsvn if you don't have a jboss.org account).
      https://svn.jboss.org/repos/jbossas/projects/mc-script/trunk/src/main/java/org/jboss/beans/script/ScriptValueMetaData.java

      You should be able to work out how to use it from the xsd
      https://svn.jboss.org/repos/jbossas/projects/mc-script/trunk/src/main/resources/schema/
      or the tests
      https://svn.jboss.org/repos/jbossas/projects/mc-script/trunk/src/test/resources/org/jboss/test/beans/script/test/

      Here I'll explain how it works.

      The extension point is that a property (or parameter or collection element) configuration
      takes any ValueMetadata because it is defined in the xml to be an xsd:any element.

      Using the JBossXB annotations to define an xml group
      (you don't actually need the group, a plain type with a getter/setter marked @XmlAnyElement will also work if it is not of type DOM element)

      @JBossXmlGroup
      ({
       @JBossXmlChild(name="array", type=AbstractArrayMetaData.class),
       @JBossXmlChild(name="collection", type=AbstractCollectionMetaData.class),
       @JBossXmlChild(name="inject", type=AbstractInjectionValueMetaData.class),
       @JBossXmlChild(name="list", type=AbstractListMetaData.class),
       @JBossXmlChild(name="map", type=AbstractMapMetaData.class),
       @JBossXmlChild(name="null", type=AbstractValueMetaData.class),
       @JBossXmlChild(name="set", type=AbstractSetMetaData.class),
       @JBossXmlChild(name="this", type=ThisValueMetaData.class),
       @JBossXmlChild(name="value", type=StringValueMetaData.class),
       @JBossXmlChild(name="value-factory", type= AbstractValueFactoryMetaData.class)
      })
      @JBossXmlGroupText(wrapper= StringValueMetaData.class, property="value")
      
      // HERE!
      
      @JBossXmlGroupWildcard(wrapper= AbstractValueMetaData.class, property="value")
      public interface ValueMetaData extends JBossInterface, MetaDataVisitorNode
      

      and in the xsd
      
      
       <xsd:group name="valueGroup">
      
      
      <snipped/>
      
      
       <xsd:any namespace="##other" processContents="strict">
      
       <xsd:annotation>
      
       <xsd:documentation>An extension value</xsd:documentation>
      
       </xsd:annotation>
      
       </xsd:any>
      
       </xsd:choice>
      
       </xsd:group>
      


      This means I can create a new subclass of ValueMetaData in its own xml namespace
      and use it anywhere a "ValueGroup" is defined in the xml (or equivalently a property
      is of type ValueMetaData - or a collection of them).

      This is what I've done with the ScriptValueMetaData that invokes a script
      to determine the value.

      @JBossXmlSchema(namespace="urn:jboss:bean-deployer:script:2.0", elementFormDefault=XmlNsForm.QUALIFIED)
      @XmlRootElement(name="script")
      @XmlType(name="scriptType", propOrder="parameters")
      public class ScriptValueMetaData extends AbstractValueMetaData
      


      The example is slightly more complicated than it needs to be since I added an
      extra feature so you can pass parameters (including injections from other beans)
      which means it has to handle visiting the children of the metadata (the parameters)
      and a few other bits and pieces like making the "controllerContext" available as a
      variable to the script.

      Without those complications, you can see that all the work is just in getValue(TypeInfo, ClassLoader).

      There are a number of other places within the microcontainer and deployment
      or classloader metadata that can be extended in this way, e.g. the classloader
      requirement/capabilities.