Question

I have a SOAP web service based on Axis2 1.4.1 that accepts MTOM uploads using the pattern from the docs:

public class MTOMService {
    public void uploadFileUsingMTOM(OMElement element) throws Exception {
        OMText binaryNode = (OMText) (element.getFirstElement()).getFirstOMChild();
        DataHandler actualDH;
        actualDH = (DataHandler) binaryNode.getDataHandler();

        // consume data from DataHandler
        InputStream inputStream = actualDH.getInputStream();
    }
}

I potentially need to read the data from the DataHandler more than once.

        inputStream.close();
        // get second InputStream to consume same data from DataHandler again
        InputStream inputStream2 = actualDH.getInputStream();

This works in simple tests. Can I assume this is always safe?

  • I can't find anything definitive in the documentation, either for the standard DataHandler or the specific DataSources implemented by Axiom (but I may have missed it)
  • Axis 1.4.1 uses Axiom 1.2.9 which represents attachments as either
    • PartOnFile, spooled to disk from memory which supports re-use until (I think) the end of the SOAP request; read via FileAccessor
    • PartOnMemoryEnhanced, which stores the data in multiple byte arrays and so should support re-use until garbage collected
  • Looking ahead, later versions of Axiom use a different class ParserInputStreamDataSource which supports different destructive or non-destructive Behavior enums, but Axis trunk does not specify and so Axiom defaults to Behavior.NON_DESTRUCTIVE which allows re-reads.

but this is all from a cursory scan of the code, which I don't know every well, so I may have missed other code paths or I may just be wrong.

Does Axis, or any of the other interfaces here, guarantee that DataHandlers can be read more than once? If not, is there a good mechanism to detect when Axis is passing attachments read-once-only mode so I can cache the first read myself? Does it make a difference if the request is MTOM or not? Thanks!

Was it helpful?

Solution

The DataHandler#getInputStream() method basically delegates to DataSource#getInputStream() and the contract of that method specifically requires that the content of the DataSource can be read multiple times. Axiom is designed to conform to that contract.

Axiom defines an extension interface (DataHandlerExt) that can be used in scenarios where one wants to "destructively" read the content.

There is however one thing you need to pay attention to: at the end of the request processing (i.e. after your service has been invoked), Axis2 is expected to instruct Axiom to destroy the temporary files related to DataHandler instances created during the request. That means that if you store a reference to a DataHandler and try to access it later (in another request, or in some background thread), then this may fail. Note that in a future version of Axiom it is planned to introduce an option that would let the garbage collector handle that cleanup, which would avoid this problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top