8/30/2008
Architecture Management vs. Architecture Development
Architecture management in some more or less small form is a necessary evil of every architect. There is a level of documentation and public work which is absolutely needed to keep an architecture on living. But it's no candidate for a cult. Sure it's much easier to manage compared to development (he? not only concerning the architecture, I guess ;-)), but it's very deadly for an architecture.
Just imagine a building architect which has never made a plan for a building or it'a sanitation. Got him? He will end up sitting in a government office writing things like: "in our village all roofs have to be orange and must have the same form. Tear down your house to fit our standards now!" Know what I mean? This is management.
Those of us who mentally quakes imaging such a rubbish know what architecture development is: creative work, technology scouting, permanent improvement, pilot subprojects to proove a concept, prototypes and fights for admission to go on etc.
So, please don't misuse the terms architecture or architect only to have them being written on your business card. If you are managing an architecture developed by somebody else or even by yourself a long time ago, use smth. like standards manager or so. If you don't develop the architecture with a very hands-on part there is nothing to be called architecture in your function.
8/25/2008
Using XInclude with Spring extensible XML authoring
When you use Spring as one of the possible containers which your Java application or your own framework should run on, you will possibly take in account the Spring feature called "extensible XML authoring" (refer to http://static.springframework.org/spring/docs/2.5.x/reference/extensible-xml.html for details).
With this very nice thing, you can embed your own XML stuff into the Spring bean definition so it will be up to you, to read out and to wire all those components with the container even based on your own XML stuff.
Without going deeper with the basic feature which is very well documented on the page behind the link, I would like to show how you can use XInclude to comfortably separate your own XML stuff from the Spring bean definition on the file base, so you can later reuse the file containing your own XML completely independently from Spring. So, the separation of concerns and reusability as well as technology independency keep on living.
Lets assume, you already have defined your XML schema having smth. like <myns:mytag> as the topmost XML element. In the "classic" Spring extensible XML authoring, you will probably have your bean definition in a file like that:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://mycompany/myschema myschema.xsd"
xmlns:myns="http://mycompany/myschema">
<myns:mytag>
...
</myns:mytag>
</beans>
Having a bean definition like this constrains you to embed your own XML tags directly into it and to rewrite it again whenever it's used outside Spring. How can you keep your XML code reusable so it can be just referenced by the bean definition instead of beeing embedded?
The solutions comes with the XInclude specification. Using it, you can create such a reference. Take a look at the resulting bean definition file assuming we separated our own XML completely to a file called myxml.xml being completely valid according to our schema (keep in mind that we reference schemas either via their official URL or expect them to be in the same folder as a file for this example):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://mycompany/myschema myschema.xsd
http://www.w3.org/2001/XInclude XInclude.xsd"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:myns="http://mycompany/myschema">
<xi:include href="myxml.xml"/>
</beans>
The problem is that Spring doesn't support XInclude through its default implementation. In the depth of its code it creates an object of the javax.xml.parsers.DocumentBuilderFactory with the default XInclude awareness set to false (unset at all). That means, the XInclude reference doesn't get resolved and an exception gets thrown.
But as with all Spring components, there is a quite tricky but more or less elegant way to solve this issue.
First, we subclass the FileSystemXmlApplicationContext in order to override the protected method "loadBeanDefinitions":
public class MyFileSystemXmlApplicationContext extends FileSystemXmlApplicationContext {
public MyFileSystemXmlApplicationContext(String path) {
super(path);
}
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader =
new XmlBeanDefinitionReader(beanFactory);
//use our own DocumentLoader here
DocumentLoader documentLoader = new MyDocumentLoader();
beanDefinitionReader.setDocumentLoader(documentLoader);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver( new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
}
Relevant code modifications are highlighted red. Sure we now need the new class, MyDocumentLoader.
public class MyDocumentLoader extends DefaultDocumentLoader {
@Override
protected DocumentBuilderFactory createDocumentBuilderFactory(
int validationMode,
boolean namespaceAware)
throws ParserConfigurationException {
//let the parent to the job
DocumentBuilderFactory factory =
super.createDocumentBuilderFactory(validationMode, namespaceAware);
//now set all necessary Xerces settings
factory.setXIncludeAware(true);
factory.setNamespaceAware(true);
factory.setFeature(
"http://apache.org/xml/features/xinclude/fixup-base-uris", false);
return factory;
}
}
We override the method createDocumentBuilderFactory and set the XInclude awareness to true as well as the Namespace awareness. That's it. The feature being set at the end of the method is required for Xerces (default XML parser brought with the JDK) to avoid fixing base URL - that "feature" is well documented on the web - just google for it for further details.
From here you only need to use your new application context class to be able to reference per XInclude. For the ContextListener and the general extensible XML authoring stuff follow standard documentation and further subclassing.