JAXB - Handling Lists in Generated Proxy Classes

JAXB has ".. goal of the JAXB project is to develop and evolve the code base for the Reference of JAXB, the Java Architecture for XML Binding".

It is effectively used to convert XML to Java objects and the other way round, based on XSD specification. When the XSDs are run through the JAXB compiles (through command line, plugins or Ant tasks), they generate the source code of classes for all the different elements defined in the XSD.

... JAXB not generating setter method for Lists ...

All the classes have setters and getters for the different members within the class. When one of the complex type in the XSD has a maxOccurs="unbounded", then there is no setter method. This makes it seemingly impossible to construct and load the object so that it can be marshalled (converted) to XML.

Source

You can download the Eclipse project for this article: JAXBList.zip

Remember to copy and include the following JAXB Jars:

  • activation.jar
  • jaxb1-impl.jar
  • jaxb-api.jar
  • jaxb-impl.jar
  • jaxb-xjc.jar
  • jsr173_1.0_api.jar

You can download it from JAXB homepage.

Example

For illustrating the solution, let us look at an example XSD.

CityInfo.xsd
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns:tns="http://www.wisetome.com/CityInfo" elementFormDefault="qualified" targetNamespace="http://www.wisetome.com/CityInfo" xmlns="http://www.w3.org/2001/XMLSchema">
  <element name="CityInfo">
    <complexType>
      <sequence>
        <element name="CityName" type="string" />
        <element maxOccurs="unbounded" name="PlaceOfInterest" type="string" />
      </sequence>
    </complexType>
  </element>
</schema>

This specifies the complex type CityInfo as follows:

CityInfo.xsd structure

Note that PlaceOfInterest is unbounded - it would result as a list in the JAXB generated class. And as expected, it does not have a setter method:

JAXBList project tree

There is no setPlaceOfInterest() method.

Solution

The solution is quite simple once you understand the mechanism of how Java handles variables. All you need to do to load the CityInfo object with more than one PlaceOfInterest, is use the getPlaceOfInterest() to get a List variable, and add values to that list. Here is the code snippet:

CityInfoTest.java
...
		CityInfo cityInfo = new CityInfo();
		// Load the object with values
		cityInfo.setCityName("Newyork");
		// No setter for Lists!
		// cityInfo.setPlaseOfInterest();
		List placeOfInterest;
		// Get the List pointer from the object
		placeOfInterest = cityInfo.getPlaceOfInterest();
		// Load it with list of values
		placeOfInterest.add("Brooklyn Bridge");
		placeOfInterest.add("Statue of Liberty");
		placeOfInterest.add("Museum of Art");
...

Now the cityInfo is loaded with values, and it can be marshalled to get an XML:

CityInfoTest.java
...
			// Setting the context and getting a 
			// marshaller in that context
			JAXBContext jaxbContext = JAXBContext
					.newInstance("example.xsd");
			Marshaller marshaller = jaxbContext.createMarshaller();
			StringWriter stringWriter = new StringWriter();
			// Marshall the java object to XML
			marshaller.marshal(cityInfo, stringWriter);
			// We are done!
			System.out.println("\n\nCity Info: \n" + stringWriter.toString());
...

This gives the following XML:

Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CityInfo xmlns="http://www.wisetome.com/CityInfo">
	<CityName>Newyork</CityName>
	<PlaceOfInterest>Brooklyn Bridge</PlaceOfInterest>
	<PlaceOfInterest>Statue of Liberty</PlaceOfInterest>
	<PlaceOfInterest>Museum of Art</PlaceOfInterest>
</CityInfo>

Comments

thanks for the explanation.

Thanks a lot for the explanation, i came across the similar problem and got resolved using your solution.
Keep posting...

Why I can't download JAXBList.zip? I have the same problem here
Where can I download this file?

Thanks

Sorry for the delay but the link was broken. I have fixed it now.