Archive for August, 2013

JAXB part 8: generate classes from DTD with maven

After using JAXB with XSD schema, I have finally discovered that it´s MUCH better to make it with files and jaxd binding files.

Supposing you want to generate the classes for a web-app xml file, in the Maven pom.xml you need to add something like:

		<!-- if you want to put DTD somewhere else <schemaDirectory>src/main/jaxb</schemaDirectory> -->

In the specified schema directory there must be both the .dtd and the .jaxb binding files.
To specify a package for the generated classes, in the jaxb file like:

<?xml version="1.0" ?>
     <xml-java-binding-schema xmlns:xjc=""
         <options package="deploy.service.webapp" />

You can find a full demo of a web-app xml schema classes generation at sourceforge: JAXB DTD maven demo

JAXB part 7: increase performance with singleton JaxbContext instance

Currently I am developing an application to rename some jboss configuration content.
Using JAXB, I had made marshalling and unmarshalling methods, creating a new JAXBcontext instance each time the single methods were invoked (for each xml file!).
The application was incredibly slow. Taking up to 45 minutes to complete the tasks.
Then I have discovered that I could make it all in less than 30% of the time, by using a singleton design pattern to reuse a single instance of the JAXBContext.

All you need to do is:
1) creating a singleton class to instance the context
2) use it in your marshalling/unmarshalling method.

The singleton class is like this:

import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;



public class MbeanJAXBContext {

	private static JAXBContext instance;

	public XmdescJAXBContext() {

	public static synchronized JAXBContext initContext() {
		try {
			if (instance == null)
				instance = JAXBContext.newInstance(Mbean.class);
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
		return instance;


I am using the synchronized keyword to make it thread safe.
Then you can instance your context like this:

public static void marshaller(Mbean mbean, String filePath)
			throws CustomizerException {

	StringWriter stringWriter = new StringWriter();
	String xmlContent;
	File file = new File(filePath);

	try {
		xmlContent = FileUtils.readFileToString(file, "UTF-8");
		FileWriter fileWriter = new FileWriter(file);
		XmdescJAXBContext jaxbHelper = new XmdescJAXBContext();
		JaxbContext jaxbContext= jaxbHelper.initContext();
		Marshaller marshaller = jaxbContext.createMarshaller();

                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

					new XmlCharacterHandler());

		     marshaller.marshal(mbean, stringWriter);
	xmlContent = XmdescContentHandler.addEntityReferences(xmlContent,


		} catch (MarshalException e) {

		throw new CustomizerException("Marshalling the file: " + filePath
					+ "not possible. Wrong file content");

		} catch (JAXBException e) {

		throw new CustomizerException("Could not parse the XML file: "
					+ filePath);

		} catch (IOException e) {

		throw new CustomizerException("Could not access the file: "
					+ filePath);


Awfully I have also noticed that with Ubuntu 12.04, with the singleton instance, the application now takes just a minute to run, while with Windows 7 it still takes 16 minutes. Long live Linux!

You can find a post about the Character Handler in this blog. Have fun!

JAXB part 6: entities references expansion (before unmarshalling)

Let´s consider an xml file with entity references.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mbean PUBLIC "members of the whole firm" "team.dtd">
<team category="developer">
    <Member role="junior">Laura</Member>
    <Member role="senior">Mike</Member>

In your dtd schema you can specify the reference.

<?xml version="1.0" encoding="UTF-8"?>
  <!ENTITY john '<Member role="boss">John</Member>'>

If you need to unmarshal an xml file with entity references, first of all you need to expand them.

public static String xmlStringEntityResolver(String filePath)
			throws ParserConfigurationException, SAXException, IOException,
			TransformerException, JAXBException {

		File file = new File(filePath);
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory
		// Specifies that the parser produced by this code will
		// expand entity reference nodes
		DocumentBuilder builder = builderFactory.newDocumentBuilder();
		Document doc = builder.parse(file);
		TransformerFactory transformerFactory = TransformerFactory
		Transformer transformer = transformerFactory.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");

		StringWriter writer = new StringWriter();
		StreamResult result = new StreamResult(writer);
		DOMSource source = new DOMSource(doc);
		transformer.transform(source, result);
		// System.out.println("Expandend xml file: \n" + writer.toString());
		return writer.toString();

Then you can unmarshal the file passing it as a string file.

public static Team unmarshall(String xmlString)
			throws ParserConfigurationException, SAXException, IOException,
			TransformerException, JAXBException {

		// unmarshaller from string
		JAXBContext jaxbContext = JAXBContext.newInstance(Team.class);
		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		InputStream stream = new ByteArrayInputStream(
		Team team = (Team) unmarshaller.unmarshal(stream);

		return team;


I would like to find a better way. I´ll see what I can do.

JAXB part 5: XML Character handler

With JAXB you need to dhandle special characters you can just choose between two options.

Otherwise you need to define your own character handler.

The following class shows you how to handle both CDATA elements and special characters.


import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

public class XmlCharacterHandler implements CharacterEscapeHandler {

	public void escape(char[] buf, int start, int len, boolean isAttValue,
			Writer out) throws IOException {
		StringWriter buffer = new StringWriter();

		for (int i = start; i < start + len; i++) {

		String st = buffer.toString();

		if (!st.contains("CDATA")) {
			st = buffer.toString().replace("&", "&amp;").replace("<", "&lt;")
					.replace(">", "&gt;").replace("'", "&apos;")
					.replace("\"", "&quot;");

//		System.out.println(st);


In your marshaller method just add the following property:

					new XmlCharacterHandler());

JAXB part 4: handling CDATA elements

If you want to specify that element values are CDATA, you can create an adapter class like this:

import javax.xml.bind.annotation.adapters.XmlAdapter;

 * to parse CDATA values.
 * @author Laura Liparulo
public class AdapterXmlCDATA extends XmlAdapter<String, String> {

    public String marshal(String value) throws Exception {
        return "<![CDATA[" + value + "]]>";
    public String unmarshal(String value) throws Exception {
        return value;


In the bean class, generated by JAXB add the following annotation.

    protected String description;

In this way any occurrence of the elements with the annotation above will be automatically parsed as CDATA.