SOAP envelopes can be added to existing org.w3c.dom.Document or JAXB instances easily.
Farm farm = new Farm(); farm.getHorse().add(new Horse()); farm.getHorse().get(0).setName("glue factory"); farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Example: using standard API
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller(); marshaller.marshal(farm, document); SOAPMessage soapMessage = MessageFactory.newInstance().createMessage(); soapMessage.getSOAPBody().addDocument(document); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); soapMessage.writeTo(outputStream); String output = new String(outputStream.toByteArray());
Anti-example seen in the wild: manual concatenation/formatting
String soapEnvelope = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soapenv:Header /><soapenv:Body>%s</soapenv:Body></soapenv:Envelope>"; Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller(); marshaller.setProperty("jaxb.fragment", Boolean.TRUE); // required to stop <?xml ... being added ?> ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); marshaller.marshal(farm, outputStream); String payload = new String(outputStream.toByteArray()); String output = String.format(soapEnvelope, payload);
Note, the namespace prefix, which the standard libraries which defaults to SOAP-ENV can be changed, but it’s hard work.
soapMessage.getSOAPPart().getEnvelope().removeNamespaceDeclaration("SOAP-ENV"); soapMessage.getSOAPPart().getEnvelope().addNamespaceDeclaration("soap", "http://www.w3.org/2001/12/soap-envelope"); soapMessage.getSOAPPart().getEnvelope().setPrefix("soap"); soapMessage.getSOAPHeader().setPrefix("soap"); soapMessage.getSOAPBody().setPrefix("soap");