Index > Features > Custom XML

One of the main points of using XML rather than, say, a script, to configure your application is that it allows any XML tooling to edit the configuration. We really like Spring's XML format, however it is very technical - folks need to understand the code to be able to configure the application.

What we'd like is an alternative where components can have their own namespaces and schemas which are more concise and work better in XML editing tools.

There follows a number of examples on different ways of using custom XML syntaxes; in each case the main requirement is you use the XBean versions of the usual Spring ApplicationContext classes. e.g. use the org.xbean.spring.context.ClassPathXmlApplicationContext class instead of the Spring base class.

For more information on editing the XML see Editing Custom XML.

Simple example

The simplest example uses a custom namespace starting with java:// and ending with the Java package name to denote the package/classes to use in the XML. This avoids needing any special mapping configuration and can work with most POJOs today...

{snippet:id=xml|lang=xml|url=xbean/trunk/xbean-spring/src/test/resources/org/apache/xbean/spring/context/pizza-xbean-java.xml}

The Java POJO which this configures is shown below. Notice in the above that the element localName is the same as the class in the package from the namespace. So this mechanism works great when there is a one to one mapping of XML element names to class names in the package defined by the java:// namespace.

{snippet:id=bean|lang=java|url=xbean/trunk/xbean-spring/src/test/java/org/apache/xbean/spring/example/PizzaService.java}

Custom XML mappings

This example shows how to customise the mapping of XML to POJOs using a discovery-properties file. Using the same POJO as above, here's an example of the XML

{snippet:id=xml|lang=xml|url=xbean/trunk/xbean-spring/src/test/resources/org/apache/xbean/spring/context/pizza-xbean.xml}

Notice that we are using our own custom namespace here and using a custom element name too. To inform the XBean XML parser of your new custom mapping you need to create a properties file on the classpath at META-INF/services/org/apache/xbean/spring/$namespace. The namespace is encoded to take out : and // etc.

So in the above example we need to include this properties file in META-INF/services/org/apache/xbean/spring/http/xbean.apache.org/schemas/pizza. The contents of the file are here

# the default package that POJOs are in package = org.xbean.spring.example # Mapping of XML Element localNames to classes pizza = org.xbean.spring.example.PizzaService restaurant = org.xbean.spring.example.RestaurantService # Mapping of XML Attributes to property names pizza.myTopping = topping # Mapping of nested bean properties restaurant.dinnerMenu.list = dinnerMenu restaurant.favourite = favourite

Notice that we are renaming both XML element names to classes and XML attribute names to different property names. The renaming of properties can be useful to avoid clashes with standard Spring attributes like "id", "class", "ref" etc.

Constructor injection

This example shows how to customise the mapping of XML to POJOs which use constructor injection. For this example, we are going to configure the following bean which can only be configured using constructor injection:

{snippet:id=bean|lang=java|url=xbean/trunk/xbean-spring/src/test/java/org/apache/xbean/spring/example/SaladService.java}

The Xml uses the same clean format as above:

{snippet:id=xml|lang=xml|url=xbean/trunk/xbean-spring/src/test/resources/org/apache/xbean/spring/context/salad-xbean.xml}

In this example we use a custom namespace just like we did in the previous example. To enable constructor injection we need to provide the constructor argument names to the XBean Spring parser in the mapping properties file as follows:

{snippet:id=config|lang=none|url=xbean/trunk/xbean-spring/src/test/resources/META-INF/services/org/apache/xbean/spring/http/xbean.apache.org/schemas/salad}

The most important element of this file is the last entry, which tell the parser that the SaladService(java.lang.String,java.lang.String,boolean) constructor parameters are named dressing, size and crouton respectively.

Handling nested properties which are beans or list of beans

Its quite common to want to use nested child elements to map to complex property values. The following example shows this in action...

{snippet:id=xml|lang=xml|url=xbean/trunk/xbean-spring/src/test/resources/org/apache/xbean/spring/context/restaurant-xbean.xml}

Notice that the nested element <dinnerMenu> maps to the collection of pizza beans which maps to a Spring <property name="foo"><list>... construct. This can be achived using the pizza.dinnerMenu.list = realPropertyName entry in the properties file. If there is no entry for the nested property element then introspection is used on the class to determine if its a <property><bean>... or <property><list><bean>... style property.

Also we can handle non-list nested properties, such as the <favourite> element which maps to a <property name="foo">... construct. Again XBean will default to using introspection if necessary, otherwise you can configure this using the pizza.favourite = realPropertyName construct.

More tools

If you want to automatically generate HTML documentation for your XML configuration or to auto-generate the META-INF/services/* properties file or to make an XSD for your XML then please checkout the XBean Ant Task