XML should be readable for humans. Therefore you will have to print XML output with correct indentation and line breaks.

JAXB is not doing so by default, also not using Spring.

In order to enable so called pretty printing for XML files generated using JAXB, you will have to modify the context.xml in your Java Spring project.

XML

Juat add the following to the bean definition for the JAXB Marshaller in your projects Spring context.xml.

Below is an example for an ItemWriter, which sets the marshallers property "jaxb.formatted.output" to true.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<bean id="xmlItemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
 <property name="resource" value="file:xml/examResult.xml" />
 <property name="rootTagName" value="UniversityExamResultList" />
 <property name="marshaller">
 <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
    <list>
      <value>de.consulting.bolte.batch.model.ExamResult</value>
    </list>
  </property>
  <property name="marshallerProperties">
    <map>
      <entry key="jaxb.formatted.output">
        <value type="boolean">true</value>
      </entry>
    </map>
  </property>
 </bean>
 </property>
 </bean>

However this will cause the JAXB marshaller to indent your XML, Spring Batch will ruin it again by encapsulating it with a StaxEventItemWriter

I found following solution on stackoverflow.com to work for me.

First you will have to add the following dependency to your pom.xml.

1
2
3
4
5
<dependency>
    <groupId>net.java.dev.stax-utils</groupId>
    <artifactId>stax-utils</artifactId>
    <version>20080702</version>
</dependency>

I could not get one artifact, the stax-utils depend on in the company artifactory so I just downloaded the jar from the artifactory and included it in the build path of my project.

Source Code

Then I was able to override the StaxEventItemWriter with an implementation that just delegates the writing to a stax-utils class called IndentingXmlEventWriter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
 *
 */
package org.db.com.gk.img;
 
import java.io.Writer;
 
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
 
import org.springframework.batch.item.xml.StaxEventItemWriter;
 
import javanet.staxutils.IndentingXMLEventWriter;
 
/**
 * @author Alexander Bolte
 * @param <T>
 *
 */
public class PrettyPrintStaxEventItemWriter<T> extends StaxEventItemWriter<T> {
	private boolean indenting = true;
 
	@Override
	protected XMLEventWriter createXmlEventWriter(XMLOutputFactory outputFactory, Writer writer)
			throws XMLStreamException {
 
		if (indenting) {
			return new IndentingXMLEventWriter(super.createXmlEventWriter(outputFactory, writer));
		} else {
			return super.createXmlEventWriter(outputFactory, writer);
		}
	}
 
	public boolean isIndenting() {
		return indenting;
	}
 
	public void setIndenting(boolean indenting) {
		this.indenting = indenting;
	}
}

Last but not least you have to update the ItemWriter defined in the Spring Batch XML context to something like the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- XML ItemWriter which writes the data in XML format -->
    <bean id="xmlItemWriter" class="org.db.com.gk.img.PrettyPrintStaxEventItemWriter">
        <property name="resource" value="file:src/test/resources/testResult.xml" />
        <property name="rootTagName" value="AveksaMetadataFile" />
        <property name="headerCallback" >
        	<bean class="org.db.com.gk.img.AveksaMetadataFileHeaderCallback" />
        </property>
        <property name="indenting" value="true" />
        <property name="marshaller">
            <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            	<property name="packagesToScan">
            		<value>org.db.com.gk.img</value>
            	</property>
				<property name="marshallerProperties">
			        <map>
			            <entry>
			                <key>
			                    <util:constant static-field="javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT" />
			               </key>
			              <value type="boolean">true</value>
			            </entry>
			        </map>
			    </property>
				
                <!-- <property name="contextPath" value="org.db.com.gk.img"/>
                <property name="classesToBeBound">
                    <list>
                        <value>org.db.com.gk.img.ExportedBusinessApplication</value>
                        <value>org.db.com.gk.img.AveksaMetadataFile</value>
                    </list>
                </property>  -->
            </bean>
        </property>
    </bean>

 Pretty much effort, just to make it readable!

The "util" prefix in above "constant" tag definition refers to the following XML namespace.

http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd

Hope it helps.