Spring Object/XML mapping example

The Spring’s Object/XML Mapping, is converting Object to XML or vice verse. This process is also known as

  1. XML Marshalling – Convert Object to XML.
  2. XML UnMarshalling – Convert XML to Object.

In this tutorial, we show you how to use Spring’s oxm to do the conversion, Object <--- Spring oxm ---> XML.

Note
No nonsense, for why and what benefits of using Spring’s oxm, read this official Spring Object/XML mapping article.

1. Project Dependency

Dependencies in this example.

Note
Spring’s oxm itself doesn’t handle the XML marshalling or UnMarshalling, it depends developer to inject their prefer XML binding framework. In this case, you will use Castor binding framework.

	<properties>
		<spring.version>3.0.5.RELEASE</spring.version>
	</properties>

	<dependencies>

		<!-- Spring 3 dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- spring oxm -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- Uses Castor for XML -->
		<dependency>
			<groupId>org.codehaus.castor</groupId>
			<artifactId>castor</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Castor need this -->
		<dependency>
			<groupId>xerces</groupId>
			<artifactId>xercesImpl</artifactId>
			<version>2.8.1</version>
		</dependency>

	</dependencies>

2. Simple Object

A simple object, later convert it into XML file.


package com.mkyong.core.model;

public class Customer {

	String name;
	int age;
	boolean flag;
	String address;

	//standard getter, setter and toString() methods.
}

3. Marshaller and Unmarshaller

This class will handle the conversion via Spring’s oxm interfaces : Marshaller and Unmarshaller.


package com.mkyong.core;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class XMLConverter {

	private Marshaller marshaller;
	private Unmarshaller unmarshaller;

	public Marshaller getMarshaller() {
		return marshaller;
	}

	public void setMarshaller(Marshaller marshaller) {
		this.marshaller = marshaller;
	}

	public Unmarshaller getUnmarshaller() {
		return unmarshaller;
	}

	public void setUnmarshaller(Unmarshaller unmarshaller) {
		this.unmarshaller = unmarshaller;
	}

	public void convertFromObjectToXML(Object object, String filepath)
		throws IOException {

		FileOutputStream os = null;
		try {
			os = new FileOutputStream(filepath);
			getMarshaller().marshal(object, new StreamResult(os));
		} finally {
			if (os != null) {
				os.close();
			}
		}
	}

	public Object convertFromXMLToObject(String xmlfile) throws IOException {

		FileInputStream is = null;
		try {
			is = new FileInputStream(xmlfile);
			return getUnmarshaller().unmarshal(new StreamSource(is));
		} finally {
			if (is != null) {
				is.close();
			}
		}
	}

}

4. Spring Configuration

In Spring’s bean configuration file, inject CastorMarshaller as the XML binding framework.


<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-3.0.xsd">

	<bean id="XMLConverter" class="com.mkyong.core.XMLConverter">
		<property name="marshaller" ref="castorMarshaller" />
		<property name="unmarshaller" ref="castorMarshaller" />
	</bean>
	<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />

</beans>

5. Test

Run it.


package com.mkyong.core;

import java.io.IOException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.core.model.Customer;

public class App {
	private static final String XML_FILE_NAME = "customer.xml";
	
	public static void main(String[] args) throws IOException {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("App.xml");
		XMLConverter converter = (XMLConverter) appContext.getBean("XMLConverter");
		
		Customer customer = new Customer();
		customer.setName("mkyong");
		customer.setAge(30);
		customer.setFlag(true);
		customer.setAddress("This is address");
		
		System.out.println("Convert Object to XML!");
		//from object to XML file
		converter.convertFromObjectToXML(customer, XML_FILE_NAME);
		System.out.println("Done \n");
		
		System.out.println("Convert XML back to Object!");
		//from XML to object
		Customer customer2 = (Customer)converter.convertFromXMLToObject(XML_FILE_NAME);
		System.out.println(customer2);
		System.out.println("Done");
		
	}
}

Output


Convert Object to XML!
Done 

Convert XML back to Object!
Customer [name=mkyong, age=30, flag=true, address=This is address]
Done

The following XML file “customer.xml” is generated in your project root folder.

File : customer.xml


<?xml version="1.0" encoding="UTF-8"?>
<customer flag="true" age="30">
	<address>This is address</address>
	<name>mkyong</name>
</customer>

Castor XML Mapping

Wait, why flag and age are converted as attribute? Is that a way to control which field should use as attribute or element? Of course, you can use Castor XML mapping to define the relationship between Object and XML.

Create following mapping file, and put it into your project classpath.

File : mapping.xml


<mapping>
	<class name="com.mkyong.core.model.Customer">

		<map-to xml="customer" />

		<field name="age" type="integer">
			<bind-xml name="age" node="attribute" />
		</field>

		<field name="flag" type="boolean">
			<bind-xml name="flag" node="element" />
		</field>

		<field name="name" type="string">
			<bind-xml name="name" node="element" />
		</field>

		<field name="address" type="string">
			<bind-xml name="address" node="element" />
		</field>
	</class>
</mapping>

In Spring bean configuration file, inject above mapping.xml into CastorMarshaller via “mappingLocation“.


<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-3.0.xsd">

	<bean id="XMLConverter" class="com.mkyong.core.XMLConverter">
		<property name="marshaller" ref="castorMarshaller" />
		<property name="unmarshaller" ref="castorMarshaller" />
	</bean>
	<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
		<property name="mappingLocation" value="classpath:mapping.xml" />
	</bean>

</beans>

Test it again, the XML file “customer.xml” will be updated.

File : customer.xml


<?xml version="1.0" encoding="UTF-8"?>
<customer age="30">
	<flag>true</flag>
	<name>mkyong</name>
	<address>This is address</address>
</customer>

Download Source Code

References

  1. Castor XML mapping
  2. Spring Object/XML Mapping reference

30 comments on “Spring Object/XML mapping example

  1. how can I convert a xml to a java.util.map without having those entryset, key , value tags in the xml ? Please answer…

    Reply
  2. Thank you for your examples. It worked well for me as a static java app. I used the same code above in a Spring app and the converter will throw :
    java.lang.IllegalArgumentException: object is not an instance of declaring class… . at java.lang.reflect.Method.invoke(Unknown Source)

    I have been trying unsuccessfully to resolve the error. Any ideas how to resolve the unknown source problem?

    Reply
  3. Anyone please tell How to do this with Spring 4.2.2 ?

    Reply
  4. Hi,

    How can i define the CastorMarshaller and XMLConverter beans using Annotations in a configuration class?

    please help.

    Reply
  5. Hello,

    I am trying to read the xml

    100000
    200000
    3%
    124324
    131523
    188195

    284100
    589320
    2.5%
    365324
    413123
    518815

    and my mapping file is

    But it is throwing the error. Could you please help me to format my mapping xml?
    The mapping for , is not correct .

    Reply
  6. I am getting below exception while executing the above example:
    Exception in thread “main” org.springframework.oxm.UnmarshallingFailureException: Castor unmarshalling exception; nested exception is org.exolab.castor.xml.MarshalException: org.xml.sax.SAXException: The class for the root element ‘customer’ could not be found.{File: [not available]; line: 2; column: 32}

    at org.springframework.oxm.castor.CastorMarshaller.convertCastorException(CastorMarshaller.java:675)

    at org.springframework.oxm.castor.CastorMarshaller.unmarshalInputStream(CastorMarshaller.java:564)

    at org.springframework.oxm.support.AbstractMarshaller.unmarshalStreamSource(AbstractMarshaller.java:368)

    at org.springframework.oxm.support.AbstractMarshaller.unmarshal(AbstractMarshaller.java:134)

    at core.XMLConverter.convertFromXMLToObject(XMLConverter.java:73)

    at action.Execute.main(Execute.java:39)

    Caused by: org.exolab.castor.xml.MarshalException: org.xml.sax.SAXException: The class for the root element ‘customer’ could not be found.{File: [not available]; line: 2; column: 32}

    at org.exolab.castor.xml.Unmarshaller.convertSAXExceptionToMarshalException(Unmarshaller.java:919)

    at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:775)

    at org.springframework.oxm.castor.CastorMarshaller.unmarshalInputStream(CastorMarshaller.java:561)

    … 4 more

    Caused by: org.xml.sax.SAXException: The class for the root element ‘customer’ could not be found.

    at org.exolab.castor.xml.UnmarshalHandler.processFirstElement(UnmarshalHandler.java:920)

    at org.exolab.castor.xml.StartElementProcessor.compute(StartElementProcessor.java:103)

    at org.exolab.castor.xml.UnmarshalHandler.startElementProcessing(UnmarshalHandler.java:841)

    at org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:766)

    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)

    at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentScannerImpl$ContentDispatcher.scanRootElementHook(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)

    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)

    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)

    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)

    at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:763)

    … 5 more

    Please help me.

    Reply
  7. Thank you again for another helpful tutorial in the java spring and adjacent tech space. Whenever I see a list of resources and your blog comes up I go there first. keep up the good work.

    Reply
  8. Great article! Thank you.

    But still I have a small question – I’m new in Spring and I’m using Spring 4. I’d like to use @Autowired and not xml with beans. When I implement your solution, I’ve got an error:

    No qualifying bean of type [org.springframework.oxm.Marshaller] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency a nnotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    Can you please tell me what to add? I’ve added some @Component and @Autowired, etc.

    Thank you in advance,
    Rimma

    Reply
  9. Great Tutorial on SpringFramework.
    In this tutorial the output file is write on one row unformatted .
    I know , it’s xml so it’s the same but in jaxb it’s possible format the output.
    In Castor it’s possible do it ?

    Reply
  10. Thanks for providing this wonderful tutorial.
    I have a one question,I want to generate blank element like in following example

    true
    mkyong
    This is address
    How to generate this .
    Please help me.
    Thanks.

    Reply
  11. Thank you for this tutorial. It worked well for me.
    But It wouldn’t run until I added the mapping.xml and a reference to it in the bean.
    I would suggest modifying the tutorial to emphasize that this part needs to be there before testing.

    Reply
  12. Sorry…not Cargo but Castor! 😉
    I got that mappings thing solved but I am not able to tell Spring to autowire an XMLConverter instance into my @Service class:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘circularImporterController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.foo.bar.service.custom.MyImportService com.foo.bar.importer.portlet.MyImporterController.demoImportCircularService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘demoImportService’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.foo.bar.utils.XMLConverter com.foo.bar.service.custom.DemoImportServiceImpl.xmlConverter; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.foo.bar.utils.XMLConverter] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    What is missing…or misconfigured? In my WEB-INF/lib/ folder I have placed:
    castor-1.3.jar
    castor-1.3-core.jar
    xercesImpl.jar (ver 2.11.0)
    xml-apis.jar (was included in xerces-bin.zip)

    I am in a Liferay 6.1.3 and Spring MVC Portlet environment and have to use ANT not Maven!

    I hope anyone can help me soon. Thank you.

    Reply
  13. I tried to use Cargo in a portlet project. Whenever I try to startup Liferay I get this exception:

    Caused by: java.io.FileNotFoundException: class path resource [mappings.xml] cannot be opened because it does not exist

    I tried to create a new folder and add it as a further source folder to the classpath or put mappings.xml in many places in the project. Unsuccessfully.
    How can I tell Liferay (or…Spring) to find my mappings. xml?? Neither classpath:mappings.xml nor classpath*:mappings.xml works.

    Reply
  14. Hi!

    I have one question.
    Is there any way to obtain object serialized to xml as pure string, not to file.
    Something like:

    String xml = xmlConverter.getAsXml(obj)

    Thanks

    Reply
  15. What if the xml file is nested?
    I mean if customer class has account as object and there is element inside customer in xml file. Could you please suggest how would be the mapping in this particular case??

    Reply
  16. Hi mkyong,
    I’m getting following error when i run this project,
    Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘XMLConverter’ defined in class path resource [App.xml]: Cannot resolve reference to bean ‘castorMarshaller’ while setting bean property ‘marshaller’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘castorMarshaller’ defined in class path resource [App.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/exolab/castor/xml/XMLException

    Reply
  17. Hi, how can I use Castor and Xerces to marshall and unmarshall multiple objects? According to your example, what If i have multiple Customer objects and need multiple customer elements be generated in the XML file? Please advise.

    Reply
  18. Really you have explained very nicely.Thanks a lot 🙂

    Reply
  19. Nice tutorial but I am not able to resolve the dependent jars . Can you share the settings.xml or repository urls which I can use to get the dependant jars.

    Reply
    1. Download the source code at the end of the article, it should contains everything you need.

      Reply
  20. Hey mkyong,

    Thanks for all these awesome tutorials!!

    In this example you are reading only one object from XML, but do you know how can I read a collection of customers from an XML file whose structure is as follows:

     <?xml version="1.0" encoding="UTF-8"?>
     <customers>
         <customer age="26"><name>user1</name></customer>
         <customer age="27"><name>user2</name></customer>
     </customers>
    
    Reply
  21. Hi mkyong,

    For the above Spring Object/XML mapping example ,it needs another dependency i.e

    javax.xml.stream
    com.springsource.javax.xml.stream

    1.0.1

    or else it showing the errors.

    Thanks,

    sudheer

    Reply
    1. Hi mkyong,

      Spring Object/XML mapping example Compile Fail

      ?this.unmarshaller.unmarshal(new StreamSource(is));?
      Caused by: org.xml.sax.SAXException: The class for the root element ‘customer’ could not be found.

      Reply
    2. This example work fine in Eclipse Juno.
      I just need to configure project facet propeties into JBoss maven integration.
      After run as Goal: install
      Everything work fine.

      Hope this help for beginner.

      Reply

Leave a Comment

Your email address will not be published. Required fields are marked *