NB: Question was also asked two weeks ago on stackoverflow.com. Any solution will be shared there as well: https://stackoverflow.com/questions/43740866/unsupporteddatatypeexception-thrown-by-writetooutputstream-method-when-soap…
Environment: Java 8
Issue: When a javax.xml.soap.SOAPMessage instance includes an attachment (in this case, a GZipped archive file), writeTo(OutputStream) method throws the following exception:
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type application/gzip
Is there a more robust and/or conventional way to build SOAPMessage instances with attachments?
Sample code for Error Replication:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.zip.GZIPOutputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import static javax.xml.soap.SOAPConstants.DEFAULT_SOAP_PROTOCOL;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.TransformerException;
import org.xml.sax.SAXException;
public class SOAPMessageWriteToTest {
private static final String FILE_NAME = "TestGZipFile.txt.gz";
private static final String UNCOMPRESSED_CONTENTS
= "Two households, both alike in dignity," + System.lineSeparator()
+ "In fair Verona, where we lay our scene," + System.lineSeparator()
+ "From ancient grudge break to new mutiny," + System.lineSeparator()
+ "Where civil blood makes civil hands unclean." + System.lineSeparator()
+ "From forth the fatal loins of these two foes" + System.lineSeparator()
+ "A pair of star-crossed lovers take their life," + System.lineSeparator()
+ "Whose misadventured piteous overthrows" + System.lineSeparator()
+ "Doth with their death bury their parents̓ strife." + System.lineSeparator()
+ "The fearful passage of their death-marked love" + System.lineSeparator()
+ "And the continuance of their parents̓ rage," + System.lineSeparator()
+ "Which but their children̓s end, naught could remove," + System.lineSeparator()
+ "Is now the two-hours̓traffic of our stage;" + System.lineSeparator()
+ "The which if you with patient ears attend," + System.lineSeparator()
+ "What here shall miss, our toil shall strive to mend." + System.lineSeparator()
+ "00101010111001000011011011110111001010010001001100110100111" + System.lineSeparator();
private static final String SOAP_MESSAGE_XML
= "<soapenv:Envelope "
+ "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <AResponse>\n"
+ " <ResponseFile>" + FILE_NAME + "</ResponseFile>\n"
+ " </AResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
/*
* MIME types to test
*/
private static final String MIME_TYPE = "application/gzip";
//private static final String MIME_TYPE = "application/octet-stream";
public static void main(String[] args)
throws IOException, ParserConfigurationException,
SAXException, SOAPException, TransformerException {
/*
* Test case initialization
*/
final File testGZipFile = new File(FILE_NAME);
createFileIfMissing(testGZipFile);
final SOAPMessage testSoapMessage = generateSoapMessage();
attach(testSoapMessage, testGZipFile);
/*
* Error replication; will throw UnsupportedDataTypeException
*/
final String result;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
testSoapMessage.writeTo(out);
result = new String(out.toByteArray(), Charset.forName("UTF-8"));
}
System.out.println("result: " + result);
}
/*
* If one doesn't exist, create a test GZip file for error replication.
*/
private static void createFileIfMissing(final File testGZipFile)
throws IOException {
if (!testGZipFile.exists()) {
try (FileOutputStream fos = new FileOutputStream(testGZipFile);
GZIPOutputStream gzos = new GZIPOutputStream(fos);
OutputStreamWriter osw = new OutputStreamWriter(gzos)) {
osw.write(UNCOMPRESSED_CONTENTS);
}
}
}
/*
* Build a SOAPMessage instance based on static XML. Will attach to it.
*/
private static SOAPMessage generateSoapMessage()
throws IOException, TransformerException, SOAPException {
final SOAPMessage soapMessage;
try (ByteArrayInputStream bais = new ByteArrayInputStream(SOAP_MESSAGE_XML.getBytes("UTF-8"))) {
soapMessage = MessageFactory
.newInstance(DEFAULT_SOAP_PROTOCOL)
.createMessage(new MimeHeaders(), bais);
}
return soapMessage;
}
/*
* Attach the File parameter to the SOAPMessage parameter. Leverages side effects. NAUGHTY!
*/
private static void attach(SOAPMessage testSoapMessage, final File testGZipFile)
throws IOException, SOAPException {
final AttachmentPart attachmentPart = testSoapMessage.createAttachmentPart();
final byte[] attachmentData = Files.readAllBytes(testGZipFile.toPath());
testSoapMessage.addAttachmentPart(attachmentPart);
try (ByteArrayInputStream bais = new ByteArrayInputStream(attachmentData)) {
attachmentPart.setContent(bais, MIME_TYPE);
}
testSoapMessage.saveChanges();
}
}