<dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> </dependencies>
package mtitek.jaxb.marshalling.utils; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; public class ResourceUtils { private ResourceUtils() { } public static InputStream getResourceAsStream(final String fileName) { return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); } public static String getResourceAsString(final String fileName) throws IOException { try (final InputStream inputStream = ResourceUtils.getResourceAsStream(fileName)) { return IOUtils.toString(inputStream, "UTF-8"); } } }
package mtitek.jaxb.marshalling.utils; import java.util.Optional; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import org.apache.commons.lang3.ArrayUtils; public class JAXBContextUtils { private JAXBContextUtils() { } public static <T> Optional<JAXBContext> getJAXBContext(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { return Optional.ofNullable(JAXBContext.newInstance(ArrayUtils.add(classesToBeBound, mainClassToBeBound))); } }
package mtitek.jaxb.marshalling.utils; import java.io.IOException; import java.util.Optional; import java.util.stream.Stream; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.apache.commons.lang3.ArrayUtils; import org.xml.sax.SAXException; public class SchemaUtils { private SchemaUtils() { } public static Optional<Schema> getSchema(final String... filesNames) throws SAXException, IOException { Schema schema = null; StreamSource[] streamSources = null; if (!ArrayUtils.isEmpty(filesNames)) { try { streamSources = Stream.of(filesNames) .map(fileName -> ResourceUtils.getResourceAsStream(fileName)) .filter(inputStream -> inputStream != null) .map(inputStream -> new StreamSource(inputStream)) .toArray(StreamSource[]::new); if (!ArrayUtils.isEmpty(streamSources)) { final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); schema = schemaFactory.newSchema(streamSources); } } finally { if (!ArrayUtils.isEmpty(streamSources)) { Stream.of(streamSources).forEach(streamSource -> { try { streamSource.getInputStream().close(); } catch (IOException e) { e.printStackTrace(); } }); } } } return Optional.ofNullable(schema); } }
package mtitek.jaxb.marshalling.utils; import java.io.OutputStream; import java.util.Optional; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.namespace.QName; public class MarshallerUtils { private MarshallerUtils() { } public static <T> void marshal(final OutputStream outputStream, final T object, final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<Marshaller> optionalMarshaller = MarshallerUtils.createMarshaller(mainClassToBeBound, classesToBeBound); if (optionalMarshaller.isPresent()) { Marshaller marshaller = optionalMarshaller.get(); marshaller.marshal(object, outputStream); } else { System.out.println("Failed to create the marshaller!"); } } private static <T> Optional<Marshaller> createMarshaller(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<JAXBContext> jaxbContext = JAXBContextUtils.getJAXBContext(mainClassToBeBound, classesToBeBound); Marshaller marshaller = null; if (jaxbContext.isPresent()) { marshaller = jaxbContext.get().createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); } return Optional.ofNullable(marshaller); } }
package mtitek.jaxb.marshalling.utils; import java.io.InputStream; import java.util.Optional; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; public class UnmarshallerUtils { private UnmarshallerUtils() { } public static <T> Optional<T> unmarshal(final InputStream inputStream, final Schema schema, final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<Unmarshaller> optionalUnmarshaller = UnmarshallerUtils.createUnmarshaller(mainClassToBeBound, classesToBeBound); T instance = null; if (optionalUnmarshaller.isPresent()) { Unmarshaller unmarshaller = optionalUnmarshaller.get(); if (schema != null) { unmarshaller.setSchema(schema); unmarshaller.setEventHandler(new DefaultValidationEventHandler()); } final StreamSource streamSource = new StreamSource(inputStream); final JAXBElement<T> jaxBElement = unmarshaller.unmarshal(streamSource, mainClassToBeBound); if (jaxBElement != null) { instance = jaxBElement.getValue(); } } else { System.out.println("Failed to create the unmarshaller!"); } return Optional.ofNullable(instance); } private static <T> Optional<Unmarshaller> createUnmarshaller(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<JAXBContext> jaxbContext = JAXBContextUtils.getJAXBContext(mainClassToBeBound, classesToBeBound); Unmarshaller unmarshaller = null; if (jaxbContext.isPresent()) { unmarshaller = jaxbContext.get().createUnmarshaller(); } return Optional.ofNullable(unmarshaller); } }
package mtitek.jaxb.marshalling.payload; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "payload") @XmlType(name = "payload", propOrder = { "id", "code", "parameters" }) @XmlAccessorType(XmlAccessType.FIELD) public class Payload { @XmlElement(name = "id", required = true) private String id; @XmlElement(name = "code", required = true) private String code; @XmlElementWrapper(name = "parameters") @XmlElement(name = "parameter") private final List<PayloadParameter> parameters = new ArrayList<>(); public String getId() { return id; } public void setId(String value) { this.id = value; } public String getCode() { return code; } public void setCode(String value) { this.code = value; } public List<PayloadParameter> getParameters() { List<PayloadParameter> copyParameters = new ArrayList<PayloadParameter>(); copyParameters.addAll(this.parameters); return copyParameters; } public void setParameters(final List<PayloadParameter> parameters) { this.parameters.clear(); if (parameters != null) { this.parameters.addAll(parameters); } } @Override public String toString() { return "Payload [id=" + id + ", code=" + code + "]"; } }
package mtitek.jaxb.marshalling.payload; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "parameter") @XmlType(name = "parameterType", propOrder = { "name", "value" }) @XmlAccessorType(XmlAccessType.FIELD) public class PayloadParameter { @XmlAttribute(name = "id", required = true) private String id; @XmlElement(name = "name", required = true) private String name; @XmlElement(name = "value", required = true) private String value; public String getId() { return id; } public void setId(String value) { this.id = value; } public String getName() { return name; } public void setName(String value) { this.name = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @Override public String toString() { return "PayloadParameter [id=" + id + ", name=" + name + ", value=" + value + "]"; } }
@javax.xml.bind.annotation.XmlSchema(namespace = "http://marshalling.jaxb.mtitek/payload", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package mtitek.jaxb.marshalling.payload;
<?xml version="1.0" encoding="UTF-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://marshalling.jaxb.mtitek/payload" xmlns="http://marshalling.jaxb.mtitek/payload" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"> <xs:element name="payload"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:string" /> <xs:element name="code" type="xs:string" /> <xs:element name="parameters" type="parametersType" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="parametersType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="parameterType"> <xs:all> <xs:element name="name" type="xs:string" /> <xs:element name="value" type="xs:string" /> </xs:all> <xs:attribute name="id" type="xs:string" /> </xs:complexType> </xs:schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <payload xmlns="http://marshalling.jaxb.mtitek/payload" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://marshalling.jaxb.mtitek/payload payload.xsd"> <id>123</id> <code>xyz</code> <parameters> <parameter id="11"> <name>bar</name> <value>foo</value> </parameter> <parameter id="22"> <value>ti</value> <name>ta</name> </parameter> </parameters> </payload>
package mtitek.jaxb.marshalling; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; import mtitek.jaxb.marshalling.payload.PayloadParameter; import mtitek.jaxb.marshalling.payload.Payload; import mtitek.jaxb.marshalling.utils.MarshallerUtils; public class TestMarshaller { public static void main(String[] args) throws Exception { final Payload payload = initPayload(); try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { MarshallerUtils.marshal(byteArrayOutputStream, payload, null, Payload.class); System.out.println(byteArrayOutputStream.toString("UTF-8")); } } private static Payload initPayload() { final Payload payload = new Payload(); payload.setId("1"); payload.setCode("111"); final List<PayloadParameter> parameters = new ArrayList<>(); { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("1"); parameter.setName("aaa"); parameter.setValue("bbb"); parameters.add(parameter); } { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("2"); parameter.setName("ccc"); parameter.setValue("ddd"); parameters.add(parameter); } payload.setParameters(parameters); return payload; } }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <payload xmlns="http://marshalling.jaxb.mtitek/payload"> <id>1</id> <code>111</code> <parameters> <parameter id="1"> <name>aaa</name> <value>bbb</value> </parameter> <parameter id="2"> <name>ccc</name> <value>ddd</value> </parameter> </parameters> </payload>
package mtitek.jaxb.marshalling; import java.io.IOException; import java.io.InputStream; import java.util.Optional; import javax.xml.bind.JAXBException; import javax.xml.validation.Schema; import org.xml.sax.SAXException; import mtitek.jaxb.marshalling.payload.Payload; import mtitek.jaxb.marshalling.utils.ResourceUtils; import mtitek.jaxb.marshalling.utils.SchemaUtils; import mtitek.jaxb.marshalling.utils.UnmarshallerUtils; public class TestUnmarshaller { public static void main(String[] args) throws SAXException, IOException, JAXBException { System.out.println(ResourceUtils.getResourceAsString("payload.xsd")); final Optional<Schema> schema = SchemaUtils.getSchema("payload.xsd"); if (schema.isPresent()) { try (final InputStream inputStream = ResourceUtils.getResourceAsStream("payload.xml")) { final Optional<Payload> optionalPayload = UnmarshallerUtils.unmarshal(inputStream, schema.get(), Payload.class); if (optionalPayload.isPresent()) { final Payload payload = optionalPayload.get(); System.out.println(payload); System.out.println(payload.getParameters()); } } } } }
Payload [id=123, code=xyz] [PayloadParameter [id=11, name=bar, value=foo], PayloadParameter [id=22, name=ta, value=ti]]