You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@ws.apache.org by Wouter Cloetens <wc...@raleigh.ibm.com> on 2000/07/30 10:57:02 UTC
Multipart Mime support
Sorry for the large document and diff in the next mail. I don't have any webspace on the
Net I can easily dump this stuff on.
I've made a first pass at multipart mime support. This version takes a minimal
effort approach and is by no means ready to be merged with the tree, for
reasons discussed below.
This version depends on JavaMail (http://java.sun.com/products/javamail/) and
the Java Activiation Framework (http://java.sun.com/products/beans/glasgow/jaf.html).
You will need mail.jar and activation.jar.
The serialiser takes an InputStream, a (JAF) DataSource, a (JAF) DataHandler
or a (JavaMail) MimeBodyPart. These objects are assigned a unique Mime
Content-ID and attached as Mime parts. The SOAP request itself becomes the
first Mime part.
The content itself is set to "multipart/related" (with a boundary identifier) if there
are any attachments. The SOAP HTTP headers remain in the HTTP request,
not in the Mime headers of the SOAP part.
The attachments are referred to by their Content-ID with a new type of
"attachment". For example:
<return
xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:attachment"
href="cid:2936953.964977132419.wcloeten@255.255.255.255"
/>
I'm not sure if this is a desirable format (in fact, I'm pretty sure it isn't), but I lack
support in the SOAP specification and just about everybody who suggested
how to do multipart support uses a different type, most of those a violation of the
logic of some specification. "href" is supposed to refer to a URI, and I figured
making up a "cid" protocol wasn't too bad. Trying to figure out if the "attachment"
type should be specified in some schema makes my head hurt, and value
reference format in the SOAP spec may not entirely agree with it. Suggestions
more than welcome.
These attachments are always deserialised as DataHandler objects. From this,
you can derive a DataSource, the Mime content type, an InputStream, an object,
a bean, or you can even handle it with content handlers supporting the content
type. The Java Activation Framework is really quite nifty.
Notes:
1. The code should be decoupled more. Multipart support (only for HTTP so far)
is scattered over the rpcrouter, SOAPHTTPConnection and HTTPUtils. Other
transport types will have to duplicate significant amounts of code as it stands
today.
2. Other transport types will likely require different transfer-encodings (e.g. e-mail
encoding may impose a 7-bit limit). See my discussion on an encoding context
below, under 6.
3. I've ported rpcrouter.jsp to a servlet. I'm not sure if that'll work out of the box
anywhere else than on my development platform (WebSphere 1.1 for OS/2). It's
easy to port the changes back into the jsp.
4. I'm not too happy with using JavaMail for the mime- and
multipart-{en|de}coding. It seemed like a good idea to use existing code, but its
implementation is really too closely tied to e-mail. I had no luck finding a generic
Mime toolkit. We might want to roll our own, which may support other
mechanisms of encoding multiple parts than Mime Multipart for transport
mechanisms which have support for this sort of thing already (not that I know of
any).
5. With a bit more effort, batched requests consisting of multiple SOAP
envelopes could be implemented too. The question there is how to distinguish
SOAP Mime parts from other attachments with "text/xml" as a type. We could
use the "Content-Disposition" header, setting the SOAP requests to "inline" and
attachments to "attachment", for instance. Note that IMO the choice of "text/xml"
in the SOAP spec was a very big mistake (SOAP request are *not* user
readable documents!); it should've been "application/xml" with some new
modifier for SOAP.
6. Unless if I'm mistaken, the marshall/unmarshall methods of the [de]serializers
do not have access to any object holding some type of global context for the
SOAP message. This makes it impossible to refer ahead, or store a reference
to something that should be appended later. The value references in the SOAP
spec, not yet supported in this implementation, would need something like this.
Multipart Mime support is very similar.
I didn't feel like changing the syntax of the [un]marshall methods without public
discussion, so I've implemented the following kludge... I've created an
RPCContext class which holds a reference to the MimeMultipart object being
built (serialisation) or referred to by the SOAP body (deserialisation). To obtain
a reference to this object, it was equipped with a static Hashtable, mapping
thread IDs to RPCContext objects, and static get/set methods to assign an
RPCContext to the current running thread. This imposes the relatively light
restriction on the client that only a single SOAP Call object can be built within the
context of a thread, and it should be built in a single thread. The same applies to
the server when it's unmarshalling the Call object or building the Response
object. Though the single thread restriction can be circumvented the way I've
implemented it, it remains a kludge.
I would like to propose that the structure be changed to add such an context
object, accessible during envelope [un]marshalling. This context object could
be the Envelope object perhaps. Other advantages than the ones discussed
above are that the transport classes could use it to specify certain encoding
preferences. E.g. smtp transport may want to impose a 7-bit restriction. Even the
String serialiser may need that to encode Unicode characters in a special way.
Also, the list of abilities of the partner could be specified here. E.g. if the
MimeSerializer, invoked on the server, were to know that the client does not
support multipart responses (e.g. because it did not indicate in a SOAP header
that it does), it could inline an attachment as a string (JAF easily allows you to
detect if this is possible) or a base-64 encoded byte array.
bfn, Wouter