I was in a need to export some XML tags as CDATA in my CXF XML @WebService that generates some XML for our partner.

We had a field that contained an URL and in that we have ampersand characters. By default these get turned into “&” but our specific XML partner was not OK with that so we had to adjust to CDATA. That turned out to be rather complex as I was hoping for something simple like @CDATA annotation – but as always, life is full of suprises.

Anyway, the trick is rather simple to make it work – We need to define our own XML Stream Writer and overwrite the default write method from “writeCharacters” to “writeCData”.

We had a very specific tags in mind only so we specified those as static string array.

You can do this like this:

import java.util.Arrays;


import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;

 * Simple CDATA XML Stream Writer that exports some items as CDATA
public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter {

	// All elements with these names will be turned into CDATA
	private static String[] CDATA_ELEMENTS = { "infoUrl", "description" };

	private String currentElementName;

	public CDataXMLStreamWriter(XMLStreamWriter del) {

	public void writeCharacters(String text) throws XMLStreamException {
		if (Arrays.asList(CDATA_ELEMENTS).contains(currentElementName)) {
		} else {

	public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
		currentElementName = local;
		super.writeStartElement(prefix, local, uri);

OK; So now we have this nice writer, but how do you use it? Well, we are running it all inside a CXF that’s running with Spring container so as it turns out, we need an “Interceptor” that would help us write stuff. You can make one easily like this.



import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.staxutils.StaxUtils;

public class CDataWriterInterceptor extends AbstractPhaseInterceptor {

	public CDataWriterInterceptor() {

	public void handleMessage(Message message) {
		// Required for CDATA to working
		message.put("disable.outputstream.optimization", Boolean.TRUE);
		XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class));
		message.setContent(XMLStreamWriter.class, new CDataXMLStreamWriter(writer));

And now, how do you use this interceptor? In your applicationContext.xml or similar Spring context file, define the interceptor and use it!
Note that the LoggingFeature is not required but I’ve left it in here so that you could easily enable logging to see the incoming and outgoing messages better.

	<bean id="CDataWriterInterceptor" class="com.amivarius.cxf.util.CDataWriterInterceptor" />

	<jaxrs:server .... >

			<bean class="org.apache.cxf.feature.LoggingFeature" />

			<ref bean="CDataWriterInterceptor" />


And that’s it folks!

The output will be <![CDATA[]]> nicely 🙂