SDC-ri sends broken Response when Marshalling Problems occur
When creating an Mdib that can be unmarshalled, but not marshalled again, for instance by inserting the following XML Snippet into one of its XML Nodes:
<Extension><unknown mustUnderstand="true"></Extension>
then it is still possible to start an SDC-ri Provider with this Mdib, but this Provider answers a GetMdib Request with a Response that
- has a 500 Status Code, indicating that something went wrong, but
- otherwise looks like a normal GetMdibResponse, containing a long XML document whose prefix looks perfectly valid, but
- ends in an Exception like the following
DescriptorVersionError marshalling HTTP output stream: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; lineNumber: 0; columnNumber: 0; cvc-complex-type.2.4.a: Ung�ltiger Content wurde beginnend mit Element 'unknown' gefunden. '{WC[##other:"http://standards.ieee.org/downloads/11073/11073-10207-2017/extension"]}' wird erwartet.
javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; lineNumber: 0; columnNumber: 0; cvc-complex-type.2.4.a: Ung�ltiger Content wurde beginnend mit Element 'unknown' gefunden. '{WC[##other:"http://standards.ieee.org/downloads/11073/11073-10207-2017/extension"]}' wird erwartet.]
and hence produces parsing errors when passed to an XML parser.
Of course, starting an SDC Provider with a broken Mdib is misconfiguration, but since certain Operations (f.i. SetContextState) allow SDC Consumers to insert XML snippets into the Provider's Mdib, this state can also be reached when the initial Mdib is valid.
Of course it is hard to prevent all kinds of marshalling problems. However, I would have expected SDC-ri to
- answer with a SoapFault in this case.
- log the whole exception including its StackTrace to allow debugging issues like that.
Additional Information:
Without the Stacktrace, all one can do is to guess where the Exception came from. Here is what I found:
- The MarshallingException seems to be thrown by a call to marshallingService.marshal(responseMsg, outStream); in line 110 of RequestResponseServerHttpHandler.
- It is then caught in a try-catch block and its message (NOT its stackTrace) is inserted into a HTTPException in line 113 of RequestResponseServerHttpHandler. Usually, it would be best practice to attach it to the HTTPException as a cause, but HTTPException does not allow this. Nevertheless, it should have been logged at this point.
- the HTTPException is caught in line 99 of JettyHttpServerHandler, where it is logged WITHOUT a stackTrace. Next, its message is written directly into the outputStream (tempOut), which butchers the XML document whose prefix has at this point already been written there by marshallingService.marshal(). This is a rather weird way to do error handling. IMHO, it would be much better to log the Exception INCLUDING its stackTrace and then reset the outputStream before writing a SoapFault with the Exception's message.