cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sergey Beryozkin" <>
Subject Re: Attachment support in XML binding and ProviderChainObserver (Was : Mime support...)
Date Wed, 31 Jan 2007 18:50:26 GMT

Please find a patch attached at

Here's a summary of changes as listed in that Jira issue :

* org.apache.cxf.binding.xml.XMLBindingFactory updated to add AttachmentInInterceptor to created
* org.apache.cxf.jaxws.ProviderChainObserver.onMessage() adds AttachmentInInterceptor unless
Provider's type parameter is DataSource or SourceMessage 
* converts Message.getAttachments into
Map<String, DataHandler> as per JAXWS spec 
* org.apache.cxf.jaxws.interceptors.DispatchInInterceptor skips GET requets 
* org.apache.cxf.jaxws.interceptors.DispatchOutInterceptor closes DataSource input stream
after copying the data to output stream 
* org.apache.cxf.jaxws.transports.http.JettyHTTPDestination updated not to duplicate response
Content-Type and honour Content-Type property if set in Provider implementations 
* Updated to try to read even if InputStream.available()
shows 0, as it's not a reliable indication that the stream can not fetch more data

Tests added

More work will have to be done to deal with Provider<SoapBody> wishing to return MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS,
as well as to optimize attachments conversion (LaxyAttachmentMap), but that will be a minor

Please evaluate this patch and apply it...If necessary I can add more tests though I reckon
I've covered all the changes, either by unit or system tests

Thanks, Sergey


  There's something wrong with the implementation of a utility ByteDataSource implementing
DataSource...In my system test which I'm running in the server depending on CXF simply using
like this in 
  the Provider<DataSource> implementation causes an instant HTTP 500 :

  DataSource invoke(DataSource) {
      return new ByteDataSource("foo".getBytes()); 

  I feel the way it implements DataSource is subtly incorrect perhaps ? I've replaced the
call with javax.mail.ByteArrayDataSource, works just fine... 

  Cheers, Sergey

    ----- Original Message ----- 
    From: Sergey Beryozkin 
    To: Sergey Beryozkin ; 
    Sent: Friday, January 26, 2007 11:54 AM
    Subject: Re: Attachment support in XML binding and ProviderChainObserver (Was : Mime support...)

    The only concern is whether it actually JAXWS-compliant to have a Provider<Source>
implementations to get a root part of the multipart/related request as the invoke Source and
get to other parts through a Map<String, DataHandler>...

    Looks like it's compliant...A useful matrix is here :

    so it says Provider<Source> represents either a primary part (of multipart/related)
or content...

    That said, I have things working just fine using Provider<DataSource>, can get both
POSTed (raw) multipart/related data and even GET even binary data back this is really good.
That said, I can have an initial patch sent in the next few days or so if I can get an approval
for the ProviderChainObserver::onMessage() change as described below...

    Cheers, Sergey


      Would it suffice if I do this :

      * In ProviderChainObserver::onMessage() explictly add AttachmentInInterceptors in front
of the DispatchInInterceptor, simpliest solution possibly, but not generic

      for a start ?

      endpoint.getBinding().getInInterceptors().add(new AttachmentInInterceptor());
      endpoint.getBinding().getInInterceptors().add(new DispatchInInterceptor());

      With this change my test works just fine. Provider<Source> implementation gets
the root part of the multipart/related body as a Source and then it can get any other remaining
parts from MessageContext as a Map<String, DataHandler> by using MessageContext.INCOMING_MESSAGE_ATTACHMENTS.

      Obviosuly for SOAP XML providers, they'll have to handle XOP root body themselves with
xop:Includes, but this root part will passed to them as a Source and then they would be able
to retrieve all the included parts form the Map...

      I reckon having an explicit AttachmentInInterceptor() in ProviderChainObserver::onMessage()
won't harm in . Without it, Provider<Source> implementaions just don't work if a multipart/related
message is sent to them... Not a very big deal perhaps, as one can do Provider<DataSource>
to get a non-XML input, but in this case multipart/related parts will have to be parsed manually...

      Cheers, Sergey


      Renamed the subject to better reflect the topic of this thread.
      I've spent a bit of time trying to make a test verifyiing attachments can be handled
by Provider<Source> implementations working and finally I found what seems to be the
      stumbling block.

      As it happens, all in-interceptors for Provider-based endpoints, specifically the ones
added at XMLBinding creation time, are cleared away in ProviderChainObserver::onMessage()


      endpoint.getBinding().getInInterceptors().add(new DispatchInInterceptor());

      As Eoghan explained to me, this is in fact compatible with the JAX-WS spec, as Providers
are willing to deal with Sources (XML) directly, so any XMLBinding interceptors required to
serve SEI endpoints. 

      Unfortunately, the way it's done at the moment causes a problem in case of the attachments
coming in a multpart/related package, simply because AttachmentInInterceptors required to
deserialize the message properly so that a root part of the mutlipart/related package can
be presented as a Source, is cleared away. Actually, as far as I understand, the same problem
would apply to Provider<Source> provideres served by HTTPBinding.

      So what would be the best way to solve this problem ? Several options are possible.

      * In ProviderChainObserver::onMessage() explictly add AttachmentInInterceptors in front
of the DispatchInInterceptor, simpliest solution possibly, but not generic.

      * clear away only those interceptors which are not instanceof certain AbstractInterceptor
types so that interceptors to do with the (de)serializing, logging, etc can be left in the

      * Update base Interceptor interface to have a method like getType() or smth like that
so that binding interceptors dealing with SEI invocatins can be removed...

      I'd aprerciate some feedback on this.

      By the way, I've just found that by implementing Provider<DataSource> (with Service.MODE=Message),
I can actually get all the raw data coming in, be they in XMl or not XML format, and also
I can serve GET requests by returning non-XML data. This is great. Only thing is that it's
much handier to deal with Map<String, DataHandler> then parsing all the attchment stuff
manually :-) so once the pacth is applied I'd consider doing Provider<Source>. Only
minor issue is that text/xml is set as Content-Type all the time, but it's a minor issue indeed.

      Cheers, Sergey


      What's the recommended approach for setting uninitilzied properties in JAXWS. 
      For ex, if message.getAttachments() returns null then should I add an empty map as
      a MessageContext.INBOUND_ATTACHMENT_VALUE ? I'd prefer adding the empty map, 
      this would probably be consistent with the way other similar values are being setup..but
I can add nothing in case of unitialized attachments if it would more consistent with the
way CXF inits properties...
      Thanks, Sergey

      > I'm fine with just throwing everything in the Map for now. We can create a
      > LazyAttachmentMap later - having the functionality is most important part at
      > this point :-) A JIRA for the LazyAttachmentMap would be great too. Thanks,
      > - Dan
      > On 1/23/07, Sergey Beryozkin <> wrote:
      >> Hi
      >> I suppose we can have a unmodifyable Map<String, DataHandler>
      >> implementation using Collection<Attachment> internally for
      >> iterating/queries. I guess the only performance benefit we can get with it
      >> is that the provider's invoke() can be hit without caching in all the
      >> attachemnats first...But this I think is important when a provider can
      >> proceed with handling the invocation without reading all the attachments it
      >> may need first which may not always be possible...
      >> If you reckon it's a worthy idea (creating LazyAttachmentMap) then I can
      >> create a JIRA specifically to address the performance issue resulting from
      >> the fact that creating a HashMap<String, DataHandler> will lead to all
      >> attachments be read through the LazyAttachmentCollection and then perhaps
      >> look into it later, as at the moment I need to create a basic patch to
      >> ensure attachements gets delivered to XMLBinding providers...
      >> Thanks, Sergey
      >> >I think that JAX-WS specifies that it be typed as Map<String,DataHandler>
      >> > not Collection<Attachment>. The key in the map would be the Content-ID.
      >> So
      >> > we would have to convert.
      >> >
      >> > This kills performance as it requires us to cache all the attachments
      >> > (unlike JAXB where we can lazily load do to some hackish code :-)), but
      >> > there isn't much I can do about that.
      >> >
      >> > - Dan
      >> >
      >> > On 1/22/07, Sergey Beryozkin <> wrote:
      >> >>
      >> >> Hi
      >> >>
      >> >> Thanks for a hint. So I've added an AttachmentInInterceptor to the
      >> of
      >> >> in-interceptors in the XMLBindingFactory.
      >> >> As far as I can see after looking through the code the side-effect
      >> this
      >> >> addition is that an implementation of org.apache.cxf.message.Messagewill
      >> >> have a Collection<Attachment> set on it by the AttachmentDeserializer.
      >> >>
      >> >> Now the next problem to solve is how to make this collection visible
      >> >> Provider<Source> implementations as they only see a
      >> >> I can see
      >> >>, and it's there
      >> >> where a MessageContext is created, in createWebServiceContext(Exchange
      >> >> exchange).
      >> >>
      >> >> So in this method I've just added
      >> >>
      >> >> ctx.put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS,
      >> >> exchange.getInMessage().getAttachments());
      >> >>
      >> >> so that the incoming attachments if any can be visible to Provider
      >> impls.
      >> >>
      >> >> I reckon that's all I need. Any comments/corrections would be
      >> >> appreciated...
      >> >>
      >> >> Thanks, Sergey
      >> >>
      >> >>
      >> >>
      >> >>
      >> >>
      >> >>
      >> >>
      >> >>
      >> >>
      >> >> ----- Original Message -----
      >> >> From: "Dan Diephouse" <>
      >> >> To: <>
      >> >> Sent: Friday, January 12, 2007 8:47 PM
      >> >> Subject: Re: MIME support in XML binding
      >> >>
      >> >>
      >> >> > It shouldn't be too hard to support MIME with the XML binding.
      >> added
      >> >> in
      >> >> > the attachment interceptors to the HTTP binding so I've already
      >> gotten
      >> >> MIME
      >> >> > over HTTP with no SOAP working. I think the main thing it requires
      >> >> adding
      >> >> > the interceptors to the XMLBindingFactory.
      >> >> >
      >> >>
      >> >>
      >> >
      >> >
      >> > --
      >> > Dan Diephouse
      >> > Envoi Solutions
      >> > |
      >> >
      > -- 
      > Dan Diephouse
      > Envoi Solutions
      > |
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message