Scenario: I have a web application that uses Spring 3 MVC. Using the powerful new annotations in Spring 3 (@Controller, @ResponseBody etc), I have written some domain objects with @XML annotations for marhalling ajax calls to web clients. Everything works great. I declared my Controller class to have a return type @ResponseBody with root XML object - the payload gets marshalled correctly and sent to Client.
The problem is that some data in the content is breaking the XML compliance. I need to wrap this with CDATA when necessary. I saw a POST here How to generate CDATA block using JAXB? that recommends using a custom Content Handler. Ok, fantastic!
public class CDataContentHandler extends (SAXHandler|XMLSerializer|Other...) {
// see http://www.w3.org/TR/xml/#syntax
private static final Pattern XML_CHARS = Pattern.compile("[<>&]");
public void characters(char[] ch, int start, int length) throws SAXException {
boolean useCData = XML_CHARS.matcher(new String(c,start,length)).find();
if (useCData) super.startCDATA();
super.characters(ch, start, length);
if (useCData) super.endCDATA();
}
}
Using Spring MVC 3, how do I achieve this? Everything was "auto-magically" done for me with regards to the JAXB aspects of setup, Spring read the return type of the method, saw the annotations of the return type and picked up JAXB2 off the classpath to do the marshalling (Object to XML conversion). So where on earth is the "hook" that permits a user to register a custom Content Handler to the config?
Using EclipseLink JAXB implementation it is as easy as adding @XmlCDATA to the Object attribute concerned. Is there some smart way Spring can help out here / abstract this problem away into a minor configuration detail?
I know Spring isn't tied to any particular implementation but for the sake of this question, please can we assume I am using whatever the default implementation is. I tried the Docs here http://static.springsource.org/spring-ws/site/reference/html/oxm.html but it barely helped at all with this question from what I could understand.
Thanks all for any replies, be really appreciated.
Update:
Thanks for the suggested answer below Akshay. It was sufficient to put me on right tracks. Investigating further, I see there is a bit of history with this one between Spring version 3.05 and 3.2. In Spring 3.05 it used to be quite difficult to register a custom MessageConverter (this is really the goal here).
This conversation pretty much explains the thinking behind the development changes requested: https://jira.springsource.org/browse/SPR-7504
Here is a link to the typically required class override to build a cusom solution: http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/org/springframework/http/converter/AbstractHttpMessageConverter.html
And the following Question on stack overflow is very similar to what I was asking for (except the @ResponseBody discussion relates to JSON and jackson) - the goal is basically the same.
Spring 3.2 and Jackson 2: add custom object mapper
So it looks like usage of , and overriding MarshallingHttpMessageConverter is needed, registering to AnnotationMethodHandlerAdapter. There is a recommended solution in link above to also get clever with this stuff and wrap the whole thing behind a custom defined Annotation.
I haven't yet developed a working solution but since I asked the questions, wanted to at least post something that may help others with the same sort of question, to get started. With all due respect, although this has all improved in Spring 3.2, it's still bit of a dogs dinner to get a little customization working... I really was expecting a one liner config change etc.
Rather than twist and bend Spring, perhaps the easiest answer for my particular issue is just to change JAXB2 implementation and use something like Eclipse Link JAXB that can do this out of the box.