cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF Documentation > JAX-RS Multiparts
Date Wed, 04 May 2011 12:50:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CXF20DOC&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Multiparts">JAX-RS
Multiparts</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~sergey_beryozkin">Sergey
Beryozkin</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >If you&#39;d like to experiment
with XOP then you need to set an &quot;mtom-enabled&quot; property on CXF jaxrs endpoints
and clients. <br>Please see [JAXRSMultipartTest|http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java]
(testXopWebClient) and [MultipartStore|http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java]
(addBookXop) for more details. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>h1. Note about Struts <br> <br>If you are using CXF and [Struts2|http://struts.apache.org/2.2.1/index.html]
within the same application and expecting CXF to process multipart/form-data payloads then
you need to make sure Struts2 dispatcher is not consuming the request input stream. <br>
<br>One option is to let Struts2 handle URIs matching some specific patterns only, for
example: <br> <br>{code:xml} <br>&lt;webapp&gt; <br>&lt;filter&gt;
<br>      &lt;filter-name&gt;struts2&lt;/filter-name&gt; <br>
     &lt;filter-class&gt; <br>           org.apache.struts2.dispatcher.FilterDispatcher
<br>       &lt;/filter-class&gt; <br>   &lt;/filter&gt; <br>
<br>   &lt;filter-mapping&gt; <br>       &lt;filter-name&gt;struts2&lt;/filter-name&gt;
<br>       &lt;url-pattern&gt;*.action&lt;/url-pattern&gt; <br>
  &lt;/filter-mapping&gt; <br> <br>   &lt;filter-mapping&gt; <br>
      &lt;filter-name&gt;struts2&lt;/filter-name&gt; <br>       &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;
<br>   &lt;/filter-mapping&gt; <br>&lt;/webapp&gt; <br>{code}
<br> <br>Alternatively,disabling a &quot;struts.multipart.parser&quot;
property might help. <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p><span style="font-size:2em;font-weight:bold"> JAX-RS : Support for
Multiparts </span></p>

<div>
<ul>
    <li><a href='#JAX-RSMultiparts-Readingattachments'>Reading attachments</a></li>
    <li><a href='#JAX-RSMultiparts-Writingattachments'>Writing attachments</a></li>
    <li><a href='#JAX-RSMultiparts-Uploadingfiles'>Uploading files</a></li>
    <li><a href='#JAX-RSMultiparts-Readinglargeattachments'>Reading large attachments</a></li>
<ul>
    <li><a href='#JAX-RSMultiparts-Formsandmultiparts'>Forms and multiparts</a></li>
</ul>
    <li><a href='#JAX-RSMultiparts-XOPsupport'>XOP support</a></li>
    <li><a href='#JAX-RSMultiparts-NoteaboutStruts'>Note about Struts</a></li>
</ul></div>

<h1><a name="JAX-RSMultiparts-Readingattachments"></a>Reading attachments</h1>

<p>Individual parts can be mapped to StreamSource, InputStream, DataSource or custom
Java types for which message body readers are available.</p>

<p>For example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
@Path(<span class="code-quote">"/books/jaxbjson"</span>)
@Produces(<span class="code-quote">"text/xml"</span>)
<span class="code-keyword">public</span> Response addBookJaxbJson(
        @Multipart(value = <span class="code-quote">"rootPart"</span>, type =
<span class="code-quote">"text/xml"</span>) Book2 b1,
        @Multipart(value = <span class="code-quote">"book2"</span>, type = <span
class="code-quote">"application/json"</span>) Book b2) 
        <span class="code-keyword">throws</span> Exception {
}
</pre>
</div></div>

<p>Note that in this example it's expected that the root part named 'rootPart' is a
text-xml Book representation, while a part named 'book2' is a Book JSON sequence.</p>

<p>All attachment parts can be accessed as a list of <a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/Attachment.java"
class="external-link" rel="nofollow">Attachment</a> with Attachment making it easy
to deal with a given part:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
<span class="code-keyword">public</span> void addAttachments(List&lt;Attachment&gt;
atts) <span class="code-keyword">throws</span> Exception {
}
</pre>
</div></div>

<p>For example, Attachment class can be used to get to a <a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/ContentDisposition.java"
class="external-link" rel="nofollow">Content-Disposition</a> header, when dealing
with the form submission of files.</p>

<p>Similarly, the whole request body can be represented as a <a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/multipart/MultipartBody.java"
class="external-link" rel="nofollow">MultipartBody</a>:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
<span class="code-keyword">public</span> void addAttachments(MultipartBody body)
<span class="code-keyword">throws</span> Exception {
body.getAllAtachments();
body.getRootAttachment();
}
</pre>
</div></div>

<p>When handling complex multipart/form-data submissions (such as those containing files)
MultipartBody (and Attachment) need to be used directly. In simpler cases, when every form
part can be captured by a String, the following code will suffice:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> void addForm1(@FormParam(<span class="code-quote">"name"</span>)
<span class="code-object">String</span> title, @FormParam(<span class="code-quote">"id"</span>)
<span class="code-object">Long</span> id) <span class="code-keyword">throws</span>
Exception {
}

@POST
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> void addForm2(@FormParam("") BookBean
book) <span class="code-keyword">throws</span> Exception {
}

@POST
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> void addForm3(MultivaluedMap&lt;<span
class="code-object">String</span>, <span class="code-object">String</span>&gt;
formData) <span class="code-keyword">throws</span> Exception {
}
</pre>
</div></div>

<p>When working with either List of Attachments or MultipartBody, one may want to process
the individual parts with the help of some custom procedures. Starting from CXF 2.3.0 it is
also possible to do the following:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
<span class="code-keyword">public</span> void addAttachments(MultipartBody body)
<span class="code-keyword">throws</span> Exception {
    Book book = body.getAttachmentObject(<span class="code-quote">"bookPart"</span>,
Book.class);
}

@POST
<span class="code-keyword">public</span> void addAttachments(List&lt;Attachment&gt;
attachments) <span class="code-keyword">throws</span> Exception {
    <span class="code-keyword">for</span> (Attachment attachment : attachments)
{
        Book book = attachment.getObject(Book.class);
    }  
}

</pre>
</div></div>




<p>When a user code has <a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/MessageContext.java"
class="external-link" rel="nofollow">MessageContext</a> injected, <a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/multipart/AttachmentUtils.java"
class="external-link" rel="nofollow">AttachmentUtils</a> can also be used by the
application code.</p>

<p>Please see these <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java"
class="external-link" rel="nofollow">test resource class</a> and <a href="http://sberyozkin.blogspot.com/2009/02/multiparts-in-cxf-jaxrs.html"
class="external-link" rel="nofollow">blog entry</a> for more examples.</p>


<h1><a name="JAX-RSMultiparts-Writingattachments"></a>Writing attachments</h1>

<p>Starting from 2.2.4 it is also possible to write attachments to the output stream,
both on the client and server sides.</p>

<p>On the server side it is sufficient to update the @Produces value for a given method:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class Resource {
   <span class="code-keyword">private</span> List&lt;Book&gt; books; 
   @Produces(<span class="code-quote">"multipart/mixed;type=text/xml"</span>)
   <span class="code-keyword">public</span> List&lt;Book&gt; getBooksAsMultipart()
{
      <span class="code-keyword">return</span> booksList;
   }

   @Produces(<span class="code-quote">"multipart/mixed;type=text/xml"</span>)
   <span class="code-keyword">public</span> Book getBookAsMultipart() {
      <span class="code-keyword">return</span> booksList;
   }
}
</pre>
</div></div>

<p>Note that a 'type' parameter of the 'multipart/mixed' media type indicates that all
parts in the multiparts response should have a Content-Type header set to 'text/xml' for both
getBooksAsMultipart() and getBookAsMultipart() method responses. The getBooksAsMultipart()
response will have 3 parts, the first part will have its Content-ID header set to "root.message@cxf.apache.org",
the next parts will have '1' and '2' ids. The getBookAsMultipart() response will have a single
part only with its Content-ID header set to "root.message@cxf.apache.org".</p>

<p>When returning mixed multiparts containing objects of different types, you can either
return a Map with the media type string value to Object pairs or MultipartBody:  </p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class Resource {
   <span class="code-keyword">private</span> List&lt;Book&gt; books; 
   @Produces(<span class="code-quote">"multipart/mixed"</span>)
   <span class="code-keyword">public</span> Map&lt;<span class="code-object">String</span>,
<span class="code-object">Object</span>&gt; getBooks() {
      Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;
map = <span class="code-keyword">new</span> LinkedHashMap&lt;<span class="code-object">String</span>,
<span class="code-object">Object</span>&gt;();
      map.put(<span class="code-quote">"text/xml"</span>, <span class="code-keyword">new</span>
JaxbBook());
      map.put(<span class="code-quote">"application/json"</span>, <span class="code-keyword">new</span>
JSONBook());
      map.put(<span class="code-quote">"application/octet-stream"</span>, imageInputStream);
      <span class="code-keyword">return</span> map;  
   } 

   @Produces(<span class="code-quote">"multipart/mixed"</span>)
   <span class="code-keyword">public</span> MultipartBody getBooks2() {
      List&lt;Attachment&gt; atts = <span class="code-keyword">new</span>
LinkedList&lt;Attachment&gt;();
      atts.add(<span class="code-keyword">new</span> Attachment(<span class="code-quote">"root"</span>,
<span class="code-quote">"application/json"</span>, <span class="code-keyword">new</span>
JSONBook()));
      atts.add(<span class="code-keyword">new</span> Attachment(<span class="code-quote">"image"</span>,
<span class="code-quote">"application/octet-stream"</span>, getImageInputStream()));
      <span class="code-keyword">return</span> <span class="code-keyword">new</span>
MultipartBody(atts, <span class="code-keyword">true</span>);  
   }

}
</pre>
</div></div>

<p>Similarly to the method returning a list in a previous code fragment, getBooks()
will have the response serialized as multiparts, where the first part will have its Content-ID
header set to "root.message@cxf.apache.org", the next parts will have ids like '1', '2', etc.
</p>

<p>In getBooks2() one can control the content ids of individual parts.</p>

<p>You can also control the contentId and the media type of the root attachment by using
a Multipart annotation:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class Resource {
   @Produces(<span class="code-quote">"multipart/form-data"</span>)
   @Multipart(value = <span class="code-quote">"root"</span>, type = <span
class="code-quote">"application/octet-stream"</span>) 
   <span class="code-keyword">public</span> File testGetImageFromForm() {
      <span class="code-keyword">return</span> getClass().getResource(<span
class="code-quote">"image.png"</span>).getFile();
   }
}
</pre>
</div></div> 

<p>One can also have lists or maps of DataHandler, DataSource, Attachment, byte arrays
or InputStreams handled as multiparts. </p>

<p>On the client side multiparts can be written the same way. For example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">

WebClient client = WebClient.create(<span class="code-quote">"http:<span class="code-comment">//books"</span>);
</span>client.type(<span class="code-quote">"multipart/mixed"</span>).accept(<span
class="code-quote">"multipart/mixed"</span>);
List&lt;Attachment&gt; atts = <span class="code-keyword">new</span> LinkedList&lt;Attachment&gt;();
atts.add(<span class="code-keyword">new</span> Attachment(<span class="code-quote">"root"</span>,
<span class="code-quote">"application/json"</span>, <span class="code-keyword">new</span>
JSONBook()));
atts.add(<span class="code-keyword">new</span> Attachment(<span class="code-quote">"image"</span>,
<span class="code-quote">"application/octet-stream"</span>, getImageInputStream()));
List&lt;Attachment&gt; atts = client.postAndGetCollection(atts, Attachment.class);
</pre>
</div></div>

<p>Note a new WebClient.postAndGetCollection which can be used for a type-safe retrieval
of collections. A similar WebClient.getCollection has also been added.</p>

<p>When using proxies, a Multipart annotation attached to a method parameter can also
be used to set the root contentId and media type. Proxies do not support at the moment multiple
method parameters annotated with Multipart (as opposed to the server side) but only a single
multipart parameter:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class Resource {
    @Produces(<span class="code-quote">"multipart/mixed"</span>)
    @Consumes(<span class="code-quote">"multipart/form-data"</span>)
    @Multipart(value = <span class="code-quote">"root"</span>, type = <span
class="code-quote">"application/octet-stream"</span>) 
    <span class="code-keyword">public</span> File postGetFile(@Multipart(value
= <span class="code-quote">"root2"</span>, type = <span class="code-quote">"application/octet-stream"</span>)
File file) {}
}
</pre>
</div></div>

<p>A method-level Multipart annotation will affect the writing on the server side and
the reading on the client side. A parameter-level Multipart annotation will affect writing
on the client (proxy) side and reading on the server side. You don't have to use Multipart
annotations.</p>

<h1><a name="JAX-RSMultiparts-Uploadingfiles"></a>Uploading files</h1>

<p>At the moment the only way to upload a file is to use a MultipartBody, Attachment
or File:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">

WebClient client = WebClient.create(<span class="code-quote">"http:<span class="code-comment">//books"</span>);
</span>client.type(<span class="code-quote">"multipart/form-data"</span>);
ContentDisposition cd = <span class="code-keyword">new</span> ContentDisposition(<span
class="code-quote">"attachment;filename=image.jpg"</span>);
Attachment att = <span class="code-keyword">new</span> Attachment(<span class="code-quote">"root"</span>,
imageInputStream, cd);
client.post(<span class="code-keyword">new</span> MultipartBody(att));

<span class="code-comment">// or just post the attachment <span class="code-keyword">if</span>
it's a single part request only
</span>client.post(att);

<span class="code-comment">// or just use a file
</span>client.post(getClass().getResource(<span class="code-quote">"image.png"</span>).getFile());

</pre>
</div></div>

<p>Using File provides a simpler way as the runtime can figure out how to create a ContentDisposition
from a File.</p>


<h1><a name="JAX-RSMultiparts-Readinglargeattachments"></a>Reading large
attachments</h1>

<p>One can use the following properties to set up folder and threshold values when dealing
with large attachments:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;beans&gt;</span>
  <span class="code-tag">&lt;jaxrs:server id=<span class="code-quote">"bookstore1"</span>&gt;</span>
     <span class="code-tag">&lt;jaxrs:properties&gt;</span>
         <span class="code-tag">&lt;entry key=<span class="code-quote">"attachment-directory"</span>
value=<span class="code-quote">"/temp/bookstore1"</span>/&gt;</span>
         <span class="code-tag"><span class="code-comment">&lt;!-- 200K--&gt;</span></span>
         <span class="code-tag">&lt;entry key=<span class="code-quote">"attachment-memory-threshold"</span>
value=<span class="code-quote">"404800"</span>/&gt;</span>
     <span class="code-tag">&lt;/jaxrs:properties&gt;</span>
  <span class="code-tag">&lt;/jaxrs:server&gt;</span>  
<span class="code-tag">&lt;/beans&gt;</span>
</pre>
</div></div>

<p>Note that such properties can be set up on a per-endpoint basis.</p>

<p>Alternatively, you might want to set the following system properties which will apply
to all endpoints:</p>

<p>&gt; -Dorg.apache.cxf.io.CachedOutputStream.Threshold=102400 <br/>
and<br/>
&gt; -Dorg.apache.cxf.io.CachedOutputStream.OutputDirectory=/temp</p>

<h2><a name="JAX-RSMultiparts-Formsandmultiparts"></a>Forms and multiparts</h2>

<p>The <a href="http://www.w3.org/TR/html401/interact/forms.html" class="external-link"
rel="nofollow">Forms in HTML documents</a> recommendation <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2"
class="external-link" rel="nofollow">suggests</a> that multipart/form-data requests
should mainly be used to upload files.</p>

<p>As mentioned in the previous section, one way to deal with multipart/form-data submissions
is to deal directly with a CXF JAXRS Attachment class and get a Content-Disposition header
and/or the underlying input stream.</p>

<p>It is now possible (since 2.2.5) to have individual multipart/form-data parts read
by registered JAX-RS MessageBodyReaders, something that is already possible to do for types
like multipart/mixed or multipart/related.</p>

<p>For example this <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/attachmentFormJson"
class="external-link" rel="nofollow">request</a> can be handled by a method with
the following signature:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
@Path(<span class="code-quote">"/books/jsonform"</span>)
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> Response addBookJsonFromForm(Book b1)
 {...}
</pre>
</div></div>

<p>Similarly, this <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/attachmentFormJsonJaxb"
class="external-link" rel="nofollow">request</a> can be handled by a method with
the following signature:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
@Path(<span class="code-quote">"/books/jsonjaxbform"</span>)
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> Response addBookJaxbJsonForm(@Multipart(<span
class="code-quote">"jsonPart"</span>) Book b1,
                                        @Multipart(<span class="code-quote">"bookXML"</span>)
Book b2) {}
</pre>
</div></div>

<p>Note that once a request has more than two parts then one needs to start using @Mutipart,
the values can refer to either ContentId header or to ContentDisposition/name. Note that at
the moment using @Multipart is preferred to using @FormParam unless a plain name/value submission
is dealt with. The reason is that @Multipart can also specify an expected media type of the
individual part and thus act similarly to a @Consume annotation.</p>

<p>When dealing with multiple parts one can avoid using  @Multipart and just use List,
ex, List\&lt;Atachment\&gt;, List\&lt;Book\&gt;, etc.</p>

<p>Finally, multipart/form-data requests with multiple files (file uploads) can be supported
too. For example, this <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/attachmentFormJsonFiles"
class="external-link" rel="nofollow">request</a> can be handled by a method with
the signature like :</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@POST
@Path(<span class="code-quote">"/books/filesform"</span>)
@Produces(<span class="code-quote">"text/xml"</span>)
@Consumes(<span class="code-quote">"multipart/form-data"</span>)
<span class="code-keyword">public</span> Response addBookFilesForm(@Multipart(<span
class="code-quote">"owner"</span>) <span class="code-object">String</span>
name,
                                 @Multipart(<span class="code-quote">"files"</span>)
List&lt;Book&gt; books) {} 
</pre>
</div></div>

<p>If you need to know the names of the individual file parts embedded in a "files"
outer part (such as "book1" and "book2"), then please use List&lt;Attachment&gt; instead.
It is currently not possible to use a Multipart annotation to refer to such inner parts but
you can easily get the names from the individual Attachment instances representing these inner
parts.</p>

<p>Note that it is only the last request which has been structured according to the
recommendation on how to upload multiple files but it is more complex than the other simpler
requests linked to in this section. </p>

<p>Please note that using JAX-RS FormParams is recommended for dealing with plain application/www-url-encoded
submissions consisting of name/value pairs only.</p>


<h1><a name="JAX-RSMultiparts-XOPsupport"></a>XOP support</h1>

<p>CXF JAXRS clients and endpoints can support <a href="http://www.w3.org/TR/xop10/"
class="external-link" rel="nofollow">XML-binary Optimized Packaging (XOP)</a>.<br/>
What it means at a practical level is that a JAXB bean containing binary data is serialized
using a multipart packaging, with the root part containing non-binary data only but also linking
to co-located parts containing the actual binary payloads. Next it is deserialized into a
JAXB bean on the server side.</p>

<p>If you'd like to experiment with XOP then you need to set an "mtom-enabled" property
on CXF jaxrs endpoints and clients.<br/>
Please see <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java"
class="external-link" rel="nofollow">JAXRSMultipartTest</a> (testXopWebClient) and
<a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/MultipartStore.java"
class="external-link" rel="nofollow">MultipartStore</a> (addBookXop) for more details.</p>

<h1><a name="JAX-RSMultiparts-NoteaboutStruts"></a>Note about Struts</h1>

<p>If you are using CXF and <a href="http://struts.apache.org/2.2.1/index.html" class="external-link"
rel="nofollow">Struts2</a> within the same application and expecting CXF to process
multipart/form-data payloads then you need to make sure Struts2 dispatcher is not consuming
the request input stream.</p>

<p>One option is to let Struts2 handle URIs matching some specific patterns only, for
example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;webapp&gt;</span>
<span class="code-tag">&lt;filter&gt;</span>
      <span class="code-tag">&lt;filter-name&gt;</span>struts2<span
class="code-tag">&lt;/filter-name&gt;</span>
      <span class="code-tag">&lt;filter-class&gt;</span>
           org.apache.struts2.dispatcher.FilterDispatcher
       <span class="code-tag">&lt;/filter-class&gt;</span>
   <span class="code-tag">&lt;/filter&gt;</span>

   <span class="code-tag">&lt;filter-mapping&gt;</span>
       <span class="code-tag">&lt;filter-name&gt;</span>struts2<span
class="code-tag">&lt;/filter-name&gt;</span>
       <span class="code-tag">&lt;url-pattern&gt;</span>*.action<span
class="code-tag">&lt;/url-pattern&gt;</span>
   <span class="code-tag">&lt;/filter-mapping&gt;</span>

   <span class="code-tag">&lt;filter-mapping&gt;</span>
       <span class="code-tag">&lt;filter-name&gt;</span>struts2<span
class="code-tag">&lt;/filter-name&gt;</span>
       <span class="code-tag">&lt;url-pattern&gt;</span>*.jsp<span
class="code-tag">&lt;/url-pattern&gt;</span>
   <span class="code-tag">&lt;/filter-mapping&gt;</span>
<span class="code-tag">&lt;/webapp&gt;</span>
</pre>
</div></div>

<p>Alternatively,disabling a "struts.multipart.parser" property might help.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Multiparts">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=24190815&revisedVersion=4&originalVersion=3">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Multiparts?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message