|
From: <jas...@ma...> - 2005-04-21 08:35:57
|
I had a couple of beers last night with Huw Roberts, an old colleague I
keep bumping into at lots of different companies over the last 15 years
or so - and the subject of configuration came up. The topic was touched
on recently & Rod's mentioned its something to think about for 1.3
(e.g. see the thread 'integrating custom XML spring dialects into the
standard Spring XML config file')
Right now the spring configuration mechanism rocks for developers; but
could be much better for end users who know nothing of the codebase &
available POJOs and their properties/constructors etc. So the idea is
to support a custom XML format for specific applications or service
which has its own self-documented XSD so that configuration tools (or
any decent XML tool) can provide a rich user interface for managing the
configuration (so end users don't have to know anything about beans or
their APIs, just use a UI which groks what options are allowed etc);
yet keep Spring's immense flexibility of allowing any old Java code to
be integrated and configured using the bean/constructor/property type
route.
i.e. the best of both worlds; constrained, concise, validated,
introspectable configuration for rich UIs and tools for end users
rather than developers - or great, flexible generic bean/property stuff
for when developers wanna wire anything into the spring configuration.
So instead of the normal Spring which is hard to validate (in an XML
way for end users unaware of the Java code) and can be a little verbose
<bean id="foo" class="Bar">
<property name="foo" value="1234"/> ....
<property name="whatnot" value="1234"/> ....
we could have something like this. We add some annotations to our
POJOs..
package org.acme.xyx;
// the @Xml annotation is optional, we can default to 'Bar' if not
present
// also namespace can be defaulted from the package
@Xml(element="bar")
class Bar {
@Mandatory
public String getFoo() {....}
// assumed optional if no mandatory
public int getWhatnot() {...}
@Cardinality(min=1, max=100000)
public List<Cheese> getCheeses() {...}
}
which would auto-generate the 'mapping configuration' for spring so we
could use this in any spring.xml...
<beans xmlns="http://xyz.acme.org">
<bar foo="1234" whatnot="1234">...
We can then auto-generate an XSD file that can be used when editing
documents using the new <bar> element - including all of the
optional/mandatory and cardinality validation logic (along with XSD
data type validation etc). So then we can give really good error
messages to users who edit <bar> and miss off mandatory properties
before we even start creating and wiring the POJOs together.
Then from the annotations we could also auto-generate the 'mapping'
code so that the standard Spring XmlBeanFactory can auto-detect the new
elements available (<bar> in this case). e.g. we could autogenerate
some META-INF/services/spring/xyz/acme/org.mapping file which contains
the mapping configuration details of how the <bar> element (with
namespace) maps to the fully qualified Bar class etc. The schema could
also be introspectable on the classpath at
META-INF/services/spring/xyz/acme/org.xsd.
This would allow components to provide their own XML mappings and
inbuilt XSD for validation as parts of their build & folks could use
them if they wish without explicit registration in the spring.xml. Neat
eh :)
To avoid components clashing (e.g. having the same element name in
different components) namespaces are used at the XSD and XML level -
and using the Java package names (maybe with a version postfix) would
seem the simplest default unless folks override this in the
annotations.
The only downside with heavily namespaced XML is its a bit ugly and
verbose to read - so maybe we could add a 'namespace alias' tag to
Spring to allow Spring to map non-namespaced elements into namespaced
elements under the covers.
e.g. here's a regular Spring.xml which uses this new namespaced XML
above using aliases...
<beans>
< namespaceAlias uri="http://xyz.acme.org">
<!-- we can now use the <bar> element without any namespace stuff... -->
<bar foo="1234" whatnot="1234">...
</beans>
without the <namespaceAlias> tag we'd have to use fully qualified
namespaces instead - which is OK as often namespaces will be used for
one tree of configuration stuff, but sometimes lots of namespaces in a
document can be a little messy...
<beans>
<bar xmlns="http://xyz.acme.org" foo="1234" whatnot="1234">...
</beans>
I guess using namespaces for different component/service libraries is
no biggie really. Its definitely better to start with full namespace
support then see if/how to hide it later on rather than the other way
around and get clashes etc.
In the above, coming up with the annotations and tool to auto-generate
the XSD is pretty simple - the only tricker part is modifying the
XmlBeanFactory to be able to auto-detect the 'custom mappings' which I
hope could just be some XML configuration file we can find on the
classpath (or on the file system in the usual spring way) which defines
which beans map to elements and what properties map to attributes etc.
To start with we don't need to support particularly complex mappings of
XML <-> POJOs; just aliasing beans to specific element names,
properties to elements or attributes and support for XSD validation
would do - further down the road we might wanna get more clever &
flexible.
Thoughts?
James
-------
http://radio.weblogs.com/0112098/
|