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
- XML Marshalling – Convert Object to XML.
- 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.
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.
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>
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:
http://castor.codehaus.org/how-to-map-a-collection.html
Me too.
how can I convert a xml to a java.util.map without having those entryset, key , value tags in the xml ? Please answer…
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?
Anyone please tell How to do this with Spring 4.2.2 ?
Hi,
How can i define the CastorMarshaller and XMLConverter beans using Annotations in a configuration class?
please help.
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 .
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.
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.
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
I´m facing the same problem
can u please update this link http://www.castor.org/xml-mapping.html%20target=
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 ?
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.
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.
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.
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.
Thanks .. its very useful for me….
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
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??
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
Hi Mk,
Using Xtream from codehaus is made easy of conversion xml to object, json etc.
http://xstream.codehaus.org/index.html
Thanks,
Santhosh
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.
Really you have explained very nicely.Thanks a lot 🙂
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.
Download the source code at the end of the article, it should contains everything you need.
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
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.
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.