mc-script - and other stupid ideas
adrian.brock Jun 4, 2009 7:22 AMI 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.