How to convert Java Object into/from XML – with Castor & Spring Boot

In the tutorial How to convert Java Object into/from XML, JavaSampleApproach will introduce way to Marshalling & Unmarshalling by an open source XML binding framework Castor with SpringBoot project.

Related Posts:
1. Gson to convert Java Object to/from Json
2. Jackson to convert Java Object to/from Json String


I. Technologies for convert Java Object into/from XML tutorial

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Castor
– SpringBoot – 1.5.7.RELEASE

II. Overview

1. Project Structure

Java Object into from XML project structure

2. Step to do

– Create SpringBoot project
– Create simple Model
– Create XML Converter
– Configure CastorMarshaller & XmlConverter
– Create Mapping file
– Develop main class for checking Marshalling & Unmarshalling
– Run & Check Results

III. Practices

1. Create SpringBoot project

– Open Spring Tool Suite, on main menu, choose File->New->Spring Starter Project, add project info. Press Next, then Finish, a Spring Boot project will be created successfully.

Open pom.xml file, add needed dependencies: Spring Oxm, Castor & xerces

<!-- spring oxm -->
<!-- http://mvnrepository.com/artifact/org.springframework/spring-oxm -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-oxm</artifactId>
</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>

2. Create simple Model

– Create Customer model:


package com.javasampleapproach.marshalling.model;

public class Customer {
	private int age;
	private String firstname;
	private String lastname;
	
	public Customer(){
	}
	
	public Customer(int age, String firstname, String lastname){
		this.age = age;
		this.firstname = firstname;
		this.lastname = lastname;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getFirstname() {
		return firstname;
	}
	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}
	public String getLastname() {
		return lastname;
	}
	public void setLastname(String lastname) {
		this.lastname = lastname;
	}
	
	@Override
	public String toString() {
		String info = String.format("Customer info: firstname = %s, lastname = %s, age = %d", firstname, lastname, age);
		return info;
	}
}

3. Create XML Converter

Create XML Converter for handling Marshaller and Unmarshaller


package com.javasampleapproach.marshalling.xmlconvert;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.bind.JAXBException;

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, JAXBException {
		try (FileOutputStream os = new FileOutputStream(filepath)) {
			marshaller.marshal(object, new StreamResult(os));
		}catch(Exception e){
			throw e;
		}
		
	}

	public Object convertFromXMLToObject(String xmlfile) throws IOException, JAXBException {
		try (FileInputStream is = new FileInputStream(xmlfile)){
			return unmarshaller.unmarshal(new StreamSource(is));
		} catch(Exception e){
			throw e;
		}
	}
}

4. Configure CastorMarshaller & XmlConverter

Because CastorMarshaller implements both Marshaller & Unmarshaller, so CastorMarshaller bean can use for XMLConverter as Marshaller & Unmarshaller:
– public class CastorMarshaller extends AbstractMarshaller
– public abstract class AbstractMarshaller implements Marshaller, Unmarshaller

Details code:


package com.javasampleapproach.marshalling.config;

import javax.annotation.Resource;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.castor.CastorMarshaller;

import com.javasampleapproach.marshalling.xmlconvert.XmlConverter;

@Configuration
public class AppConfig {
	
	@Resource
	ConfigurableApplicationContext appContext;
	
	@Bean 
	XmlConverter xmlConverter(){
		XmlConverter xmlConverter = new XmlConverter();
		xmlConverter.setMarshaller(castorMarshaller());
		xmlConverter.setUnmarshaller(castorMarshaller());
		return xmlConverter;
	}
	
	@Bean
	public CastorMarshaller castorMarshaller(){
		CastorMarshaller castorMarshaller = new CastorMarshaller();
		castorMarshaller.setMappingLocation(appContext.getResource("classpath:mapping.xml"));
		return castorMarshaller;
	}
}

5. Create Mapping file

Mapping file is a way to control what field is element or attribute.

<mapping>
	<class name="com.javasampleapproach.marshalling.model.Customer">
		<map-to xml="customer" />
		<field name="age" type="integer">
			<bind-xml name="age" node="attribute" />
		</field>
		
		<field name="firstname" type="string">
			<bind-xml name="firstname" node="element" />
		</field>

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

For locating the mapping file, use setMappingLocation method: castorMarshaller.setMappingLocation(appContext.getResource(“classpath:mapping.xml”));

6. Develop main class for checking Marshalling & Unmarshalling

In main class of SpringBoot:


package com.javasampleapproach.marshalling;

import javax.annotation.Resource;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.javasampleapproach.marshalling.model.Customer;
import com.javasampleapproach.marshalling.xmlconvert.XmlConverter;

@SpringBootApplication
public class SpringBootMarshallingApplication implements CommandLineRunner{

	@Resource
	XmlConverter xmlConverter;
	
	public static void main(String[] args) {
		SpringApplication.run(SpringBootMarshallingApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		final String xmlFile = "customer.xml";
		Customer cust = new Customer(20, "Jack", "Smith");
		
		//Convert Customer Object to Xml!
		System.out.println("Convert Customer Object to Xml!");
		xmlConverter.convertFromObjectToXML(cust, xmlFile);
		System.out.println("Done \n");

		//from XML to Customer Object
		System.out.println("Convert Xml to Customer Object!");
		Customer cust2 = (Customer)xmlConverter.convertFromXMLToObject(xmlFile);
		System.out.println(cust2.toString());
		System.out.println("Done");

	}
}

7. Run & Check Results

Run the project with Spring Boot App mode.
Results:
1. Logs:


Convert Customer Object to Xml!
Done 

Convert Xml to Customer Object!
Customer info: firstname = Jack, lastname = Smith, age = 20
Done

2. Content of customer.xml:

<?xml version="1.0" encoding="UTF-8"?>
<customer age="20">
	<firstname>Jack</firstname>
	<lastname>Smith</lastname>
</customer>

IV. Sourcecode

SpringBootMarshalling



By grokonez | January 19, 2017.

Last updated on April 24, 2021.



Related Posts


5 thoughts on “How to convert Java Object into/from XML – with Castor & Spring Boot”

    1. Hi,

      With Castor, We need a Mapping File to control the marshaling behavior. Up to now, We don’t see any support from annotations.

      Regards,

  1. Hi,

    I am getting ‘IllegalArgumentException’ while Marshalling, when Implementing the above solution. Can you help me resolve this?

    Stack Trace:
    java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
    at org.exolab.castor.mapping.loader.FieldHandlerImpl.getValue(FieldHandlerImpl.java:413) ~[castor-1.2.jar:na]
    at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1760) ~[castor-1.2.jar:na]
    at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:838) ~[castor-1.2.jar:na]

    1. Hello JagdshLK,

      I had checked the sourcecode and it works well.
      So we can NOT reproduce your case.
      Please double-check your implementation again!

      Regards,
      JSA

      1. I am getting the same error as mentioned. I have tried every possible solution in the last 14 hours, still clueless. Can you please help?

        Stacktrace :

        java.lang.IllegalArgumentException: object is not an instance of declaring class
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_181]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_181]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_181]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_181]
        at org.exolab.castor.mapping.loader.FieldHandlerImpl.getValue(FieldHandlerImpl.java:409) ~[castor-xml-1.3.3.jar:${VERSION}${RELEASE}]
        at org.exolab.castor.xml.Marshaller.processAttribute(Marshaller.java:2662) ~[castor-xml-1.3.3.jar:${VERSION}${RELEASE}]
        at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1534) ~[castor-xml-1.3.3.jar:${VERSION}${RELEASE}]
        at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:997) ~[castor-xml-1.3.3.jar:${VERSION}${RELEASE}]
        at com.demo.xml.Client.marshal(Client.java:328) ~[classes/:?]
        at com.demo.client.Processor.toString(Processor.java:244) ~[classes/:?]
        at com.demo.client.Processor$$FastClassBySpringCGLIB$$efa7e4a2.invoke() ~[classes/:?]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at com.demo.client.Processor$$EnhancerBySpringCGLIB$$95910882.toString() ~[classes/:?]
        at com.demo.goal.test.SaveDemo.saveDemo(SaveDemo.java:71) ~[classes/:?]
        at com.demo.goal.test.DemoService.start(DemoService.java:138) ~[classes/:?]
        at com.demo.goal.test.DemoService$$FastClassBySpringCGLIB$$9bb23164.invoke() ~[classes/:?]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
        at com.demo.goal.test.DemoService$$EnhancerBySpringCGLIB$$785cf808.start()

Got Something To Say:

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

*