Why static classes are especially important for JAXB unmarshalling

I have several cases where a class generated by JAXB from an xsd file has a series of class lists that also contain class lists. The created class uses static inner classes to handle these cases, but this leads to multiple instances of the class that exists several times.

As an example, I have a Parameter class that exists in several xsd files. In each case, this parameter class is the same and contains a key pair. When generating code for each of these xsd files, each generated class contains an inner class called Parameter.

To reduce redundancy, I removed the Parameter class from all generated classes, re-executed it, and updated all the links. It works as expected.

The problem arises when I have another class, such as LogicalDevice, which is also implemented in several classes. LogicalDevice contains a ParameterList. When the LogicalDevice is retrieved into its own class and the links are updated, only the first attribute in the Parameter class is saved, and the rest are null.

This makes me think that there is something special with static inner classes.

For reference: my xml and code

<Jetstream xmlns="http://Jetstream.TersoSolutions.com/v1.1/GetPoliciesResponse">
    <Header/>
    <GetPoliciesResponse>
        <PolicyList>
            <Policy Id="53bb663f-7ed0-41f8-9757-90ad4e015995" Name="MyPolicy"
                 DeviceDefinitionId="f3536a6d-4610-4d56-82d9-54fd6602a883" >
                <ParameterList>
                    <Parameter Name="aggregateeventscancount" Value="2"/>
                    <Parameter Name="aggregateeventscantime" Value="10"/>
                    <Parameter Name="antenna1rxsensitivity" Value="50"/>
                    <Parameter Name="antenna1txpower" Value="30"/>
                    <Parameter Name="antenna2rxsensitivity" Value="50"/>
                    <Parameter Name="antenna2txpower" Value="30"/>
                    <Parameter Name="antenna3rxsensitivity" Value="50"/>
                    <Parameter Name="antenna3txpower" Value="30"/>
                    <Parameter Name="antenna4rxsensitivity" Value="50"/>
                    <Parameter Name="antenna4txpower" Value="30"/>
                    <Parameter Name="commandpollinterval" Value="60"/>
                    <Parameter Name="dns" Value="0.0.0.0"/>
                    <Parameter Name="dooropentimelimit" Value="300"/>
                    <Parameter Name="gateway" Value="0.0.0.0"/>
                    <Parameter Name="ip" Value="0.0.0.0"/>
                    <Parameter Name="jetstreamdeviceurl" Value="https://us-device.tersosolutions.com/v1.0/device/"/>
                    <Parameter Name="lockdownhightemp" Value="127"/>
                    <Parameter Name="lockdownonacpowerfailure" Value="0"/>
                    <Parameter Name="lockdownonreaderfailure" Value="0"/>
                    <Parameter Name="lockdownonhightemp" Value="0"/>
                    <Parameter Name="logentryeventhightemp" Value="127"/>
                    <Parameter Name="logentryeventlowtemp" Value="-128"/>
                    <Parameter Name="numberofantennas" Value="4"/>
                    <Parameter Name="logentrylevel" Value="Warning"/>
                    <Parameter Name="objecteventscancount" Value="2"/>
                    <Parameter Name="objecteventscantime" Value="10"/>
                    <Parameter Name="Subnet" Value="0.0.0.0"/>
                </ParameterList>
                <LogicalDeviceList>
                    <LogicalDevice LogicalDeviceId="MyDevice">
                        <ParameterList>
                            <Parameter Name="ip" value="192.168.91.100" />
                            <Parameter Name="subnet" value="255.255.255.0" />
                            <Parameter Name="gateway" value="192.168.91.1" />
                            <Parameter Name="dns" value="192.168.91.2" />
                        </ParameterList>
                    </LogicalDevice>
                </LogicalDeviceList>
            </Policy>
        </PolicyList>
    </GetPoliciesResponse>
</Jetstream>

The following is a modified generated code with updated links.

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference     Implementation, v2.2.7 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2013.09.09 at 10:24:32 AM CDT 
//


package com.TersoSolutions.Jetstream.SDK.XML.Model.GetPoliciesResponse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;

import com.TersoSolutions.Jetstream.SDK.XML.LogicalDeviceList;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Jetstream", propOrder = {
"header",
"getPoliciesResponse"
})
@XmlRootElement(name = "Jetstream")
public class Jetstream {

@XmlElement(name = "Header", required = true)
protected Jetstream.Header header;
@XmlElement(name = "GetPoliciesResponse", required = true)
protected Jetstream.GetPoliciesResponse getPoliciesResponse;

/**
 * Gets the value of the header property.
 * 
 * @return
 *     possible object is
 *     {@link Jetstream.Header }
 *     
 */
public Jetstream.Header getHeader() {
    return header;
}

/**
 * Gets the value of the getPoliciesResponse property.
 * 
 * @return
 *     possible object is
 *     {@link Jetstream.GetPoliciesResponse }
 *     
 */
public Jetstream.GetPoliciesResponse getGetPoliciesResponse() {
    return getPoliciesResponse;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "GetPoliciesResponse", propOrder = {
    "policyList",
    "any"
})
public static class GetPoliciesResponse {

    @XmlElement(name = "PolicyList", required = true)
    protected Jetstream.GetPoliciesResponse.PolicyList policyList;
    @XmlAnyElement(lax = true)
    protected List<Object> any;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    /**
     * Gets the value of the policyList property.
     * 
     * @return
     *     possible object is
     *     {@link Jetstream.GetPoliciesResponse.PolicyList }
     *     
     */
    public Jetstream.GetPoliciesResponse.PolicyList getPolicyList() {
        return policyList;
    }


    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "PolicyList", propOrder = {
        "policy"
    })
    public static class PolicyList {

        @XmlElement(name = "Policy")
        protected List<Jetstream.GetPoliciesResponse.PolicyList.Policy> policy;

        /**
         * Gets the value of the policy property.
         * 
         * <p>
         * This accessor method returns a reference to the live list,
         * not a snapshot. Therefore any modification you make to the
         * returned list will be present inside the JAXB object.
         * This is why there is not a <CODE>set</CODE> method for the policy property.
         * 
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getPolicy().add(newItem);
         * </pre>
         * 
         * 
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link Jetstream.GetPoliciesResponse.PolicyList.Policy }
         * 
         * 
         */
        public List<Jetstream.GetPoliciesResponse.PolicyList.Policy> getPolicy() {
            if (policy == null) {
                policy = new ArrayList<Jetstream.GetPoliciesResponse.PolicyList.Policy>();
            }
            return this.policy;
        }

        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "Policy", propOrder = {
            "parameterList",
            "logicalDeviceList",
            "any"
        })
        public static class Policy {

            @XmlElement(name = "ParameterList", required = true)
            protected com.TersoSolutions.Jetstream.SDK.XML.ParameterList parameterList;
            @XmlElement(name = "LogicalDeviceList", required = true)
            protected LogicalDeviceList logicalDeviceList;
            @XmlAnyElement(lax = true)
            protected List<Object> any;
            @XmlAttribute(name = "Id", required = true)
            protected String id;
            @XmlAttribute(name = "Name", required = true)
            protected String name;
            @XmlAttribute(name = "DeviceDefinitionId", required = true)
            protected String deviceDefinitionId;
            @XmlAnyAttribute
            private Map<QName, String> otherAttributes = new HashMap<QName, String>();

            /**
             * Gets the value of the parameterList property.
             * 
             * @return
             *     possible object is
             *     {@link Jetstream.GetPoliciesResponse.PolicyList.Policy.ParameterList }
             *     
             */
            public com.TersoSolutions.Jetstream.SDK.XML.ParameterList getParameterList() {
                return parameterList;
            }

            /**
             * Gets the value of the logicalDeviceList property.
             * 
             * @return
             *     possible object is
             *     {@link Jetstream.GetPoliciesResponse.PolicyList.Policy.LogicalDeviceList }
             *     
             */
            public LogicalDeviceList getLogicalDeviceList() {
                return logicalDeviceList;
            }

            /**
             * Gets the value of the id property.
             * 
             * @return
             *     possible object is
             *     {@link String }
             *     
             */
            public String getId() {
                return id;
            }

            /**
             * Gets the value of the name property.
             * 
             * @return
             *     possible object is
             *     {@link String }
             *     
             */
            public String getName() {
                return name;
            }

            /**
             * Gets the value of the deviceDefinitionId property.
             * 
             * @return
             *     possible object is
             *     {@link String }
             *     
             */
            public String getDeviceDefinitionId() {
                return deviceDefinitionId;
            }

        }

    }

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Header")
public static class Header {

    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

}

}

This is an updated logical device.

package com.TersoSolutions.Jetstream.SDK.XML;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;

import com.TersoSolutions.Jetstream.SDK.XML.Model.GetConfigurationResponse.Jetstream;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "LogicalDeviceList")
public class LogicalDeviceList {

@XmlElement(name = "LogicalDevice")
protected List<LogicalDevice> logicalDevice;

/**
 * Gets the value of the logicalDevice property.
 * 
 * <p>
 * This accessor method returns a reference to the live list,
 * not a snapshot. Therefore any modification you make to the
 * returned list will be present inside the JAXB object.
 * This is why there is not a <CODE>set</CODE> method for the logicalDevice property.
 * 
 * <p>
 * For example, to add a new item, do as follows:
 * <pre>
 *    getLogicalDevice().add(newItem);
 * </pre>
 * 
 * 
 * <p>
 * Objects of the following type(s) are allowed in the list
 * {@link Jetstream.GetConfigurationResponse.LogicalDeviceList.LogicalDevice }
 * 
 * 
 */
public List<LogicalDevice> getLogicalDevice() {
    if (logicalDevice == null) {
        logicalDevice = new ArrayList<LogicalDevice>();
    }
    return this.logicalDevice;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "LogicalDevice")
public static class LogicalDevice {

    @XmlElement(name = "ParameterList")
    protected com.TersoSolutions.Jetstream.SDK.XML.ParameterList parameterList;
    @XmlAttribute(name = "DeviceDefinitionId")
    protected String deviceDefinitionId;
    @XmlAttribute(name = "DeviceSerialNumber")
    protected String deviceSerialNumber;
    @XmlAttribute(name = "Health")
    protected String health;
    @XmlAttribute(name = "LogicalDeviceId", required = true)
    protected String logicalDeviceId;
    @XmlAttribute(name = "Region")
    protected String region;
    @XmlAttribute(name = "PolicyId")
    protected String policyId;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    /**
     * Gets the value of the deviceDefinitionId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getDeviceDefinitionId() {
        return deviceDefinitionId;
    }

    /**
     * Gets the value of the deviceSerialNumber property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getDeviceSerialNumber() {
        return deviceSerialNumber;
    }

    /**
     * Gets the value of the health property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getHealth() {
        return health;
    }


    /**
     * Gets the value of the logicalDeviceId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getLogicalDeviceId() {
        return logicalDeviceId;
    }


    /**
     * Gets the value of the region property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getRegion() {
        return region;
    }


    /**
     * Gets the value of the policyId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getPolicyId() {
        return policyId;
    }

    /**
     * Gets the value of the parameterList property.
     * 
     * @return
     *     possible object is
     *     {@link Jetstream.GetPoliciesResponse.PolicyList.Policy.LogicalDeviceList.LogicalDevice.ParameterList }
     *     
     */
    public com.TersoSolutions.Jetstream.SDK.XML.ParameterList getParameterList() {
        return parameterList;
    }

}
}

and finally the Parameter class

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ParameterList")
public class ParameterList {

@XmlElement(name = "Parameter", required = true)
protected List<com.TersoSolutions.Jetstream.SDK.XML.Parameter> parameter;
@XmlAnyAttribute
private Map<QName, String> otherAttributes = new HashMap<QName, String>();

/**
 * Gets the value of the parameter property.
 * 
 * <p>
 * This accessor method returns a reference to the live list,
 * not a snapshot. Therefore any modification you make to the
 * returned list will be present inside the JAXB object.
 * This is why there is not a <CODE>set</CODE> method for the parameter property.
 * 
 * <p>
 * For example, to add a new item, do as follows:
 * <pre>
 *    getParameter().add(newItem);
 * </pre>
 * 
 * 
 * <p>
 * Objects of the following type(s) are allowed in the list
 * {@link Jetstream.LogEntryEvent.LogEntryList.LogEntry.ParameterList.Parameter }
 * 
 * 
 */
public List<com.TersoSolutions.Jetstream.SDK.XML.Parameter> getParameter() {
    if (parameter == null) {
        parameter = new ArrayList<com.TersoSolutions.Jetstream.SDK.XML.Parameter>();
    }
    return this.parameter;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Parameter")
public static class Parameter {

    @XmlAttribute(name = "Name", required = true)
    protected String name;
    @XmlAttribute(name = "Value", required = true)
    protected String value;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();

    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }

    /**
     * Gets the value of the value property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getValue() {
        return value;
    }
}
}

, . , , , , LogicalDevice , .

- , .

+4
1

A JAXB (JSR-222) . , , , , , .

1 - / JAXB

XML, / . , .

2 - JAXB

JAXB, XJC .

0

All Articles