Thanks for getting back to me Sergey.  I meant to update the email post...

It appears that I have found the problem (on my end):

I changed the annotated method in the interface FROM THIS syntax (failed)
...

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Path("/ordermanagement/{CUSTID}/orders")
public Response addOrderDocument(@Multipart("json") String json,
@Multipart("orderfile") InputStream contentStream,  @FormParam("fileInfo")
ContentDisposition fileInfo, @Context UriInfo info, @QueryParam("$filter")
String filter) throws RESTServiceException;


TO this syntax:


@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Path("/ordermanagement/{CUSTID}/orders")
public Response addOrderDocument(@Multipart("json") String json,
@Multipart("*orderfile*") *MultipartBody* *orderfile*, @Context UriInfo
info, @QueryParam("$filter") String filter) throws RESTServiceException;



And now, code like this,  that's used in the Implemented method... WORKS !
:-) :

   public Response addOrderDocument(String json, *MultipartBody* *orderfile*,
UriInfo info, String filter) throws RESTServiceException {
      LOGGER.trace("entry params: json = [{}], search = [{}], filter =
[{}]", json, filter);

    Attachment file = orderfile.getAttachment("*orderfile*");

     if ( file != null) {
         contentStream=file.getObject(InputStream.class);
         LOGGER.trace("file.getContentType = [{}]", file.getContentType());
         LOGGER.trace("file.getContentDisposition = [{}]",
file.getContentDisposition().toString());
         LOGGER.trace("contentStream = [{}]", contentStream);
     }

The LOGGER output showed what I expected, including the stream of binary
characters in the contentStream ...

It's just that with Multipart POST, the 2 stacks seem to vary somewhat in
the required classes and syntax used... but both appear to accomplish the
same thing of course.

The key was defining the *orderfile* as a *MultipartBody* type and naming
it correctly in the @Multipart() annotation so the Attachment instance
could be pulled from the object received...

I had to add these imports:

import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;

Regards,


Mark

On Tue, Oct 27, 2015 at 9:45 AM, Sergey Beryozkin <sberyoz...@gmail.com>
wrote:

> Hi Mark
>
> Sorry for a delay,
>
> I'm not seeing a 'fileinfo' part in the payload which works with Jersey,
> where exactly does it have a 'fileinfo' from ? Or is it a convention used
> to refer to Content-Disposition of the very last part ?
>
> Cheers, Sergey
>
> On 25/10/15 13:37, Mark Streit wrote:
>
>> Hello
>>
>> We have a deployed set of JAX-RS endpoints which work fine under Jersey
>> and
>> include both GET and POST annotated methods.
>>
>> We are looking to move from Jersey to CXF with this and  @GET methods
>> appear to be fine.   However @POST methods are presenting some problems.
>>
>> (Note: We place annotations on the interface and not the implementation
>> classes directly - this works in BOTH cases - the WADL returned appears
>> correct)
>>
>> We are also using POSTMAN for the test, so it generates the form/mime
>> boundaries automatically. I've also omitted the HTTP Headers and binary
>> content for brevity.
>>
>> *The Jersey case: Relevant annotations in yellow: - these appear to be
>> Jersey-specific* (all others are standard JAX-RS annotations)
>>
>>
>> @POST
>> @Consumes(MediaType.MULTIPART_FORM_DATA)
>> @Produces(MediaType.APPLICATION_JSON)
>> @Path("/ordermanagement/{CUSTID}/orders")
>> public Response addOrder(@FormDataParam("json") String json,
>> @FormDataParam("orderfile")
>> InputStream contentStream, @FormDataParam("fileInfo")
>> FormDataContentDisposition fileInfo, @Context UriInfo info,
>> @PathParam(AppConstants.CUSTID) String CUSTID,
>> @QueryParam(AppConstants.SOURCE_APP_ID_PARAM) String srcAppId,
>> @QueryParam(AppConstants.SOURCE_APP_FEATURE_ID_PARAM) String
>> srcAppFeatureId) throws RESTServiceException;
>>
>>
>> *Example of POSTMAN test that WORKS SUCCESSFULLY for this case*
>>
>> POST
>>
>> /services/core/orderprocess/ordermanagement/22334455/orders?srcAppId=orderService&srcAppFeatureId=creation
>> HTTP/1.1
>> Host: localhost:8080
>>
>> ### MOST HEADERS-REMOVED-FOR-CLARITY ###
>>
>> Cache-Control: no-cache
>> Postman-Token: db5a119a-e885-4bfd-14ae-8bac119845bd
>> Content-Type: multipart/form-data;
>> boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>> Content-Disposition: form-data; name="json"
>>
>> {   "displayName": "OrderxTest",   "originalFileName": "OrderxTest.pdf",
>> "fileName": "OrderxTest.pdf",   "OrderumentType": "pdf",
>> "OrderumentStatus": "CLEAR",   "attachmentType": "Company",   "category":
>> "DRAFT",   "subcategory": "DRAFT",   "keywords": "",   "notes": [],
>> "fileSize": 163361,   "uploadState": "PROGRESS",   "metadataState":
>> "INCOMPLETE",   "uploadFile": {},   "nextOrder": "" }
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>> Content-Disposition: form-data; name="orderfile";
>> filename="OrderxTest.pdf"
>> Content-Type: application/pdf
>>
>>
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>>
>> ### BINARY DATA STREAM REMOVED ###
>>
>> *The POST is processed successfully and we get back a HTTP 202*
>>
>>
>>
>> *The CXF case: Relevant annotations in yellow: - these appear to be
>> CXF-specific, everything is the same except changing what we believed were
>> the required annotation changes*
>>
>> *@POST*
>> *@Consumes(MediaType.MULTIPART_FORM_DATA)*
>> *@Produces(MediaType.APPLICATION_JSON)*
>> *@Path("/ordermanagement/{CUSTID}/orders")*
>> *public Response addOrderument(@Multipart("json") String json,
>> @Multipart("orderfile") InputStream contentStream, @FormParam("fileInfo")
>> ContentDisposition fileInfo, @Context UriInfo info, @QueryParam("$filter")
>> String filter) throws RESTServiceException;*
>>
>>
>>
>> *Example of POSTMAN test that FAILS for this case*
>>
>>
>> POST
>>
>> /services/core/orderprocess/ordermanagement/22334455/orders?srcAppId=orderService&srcAppFeatureId=creation
>> HTTP/1.1
>> Host: localhost:8080
>>
>> ### MOST HEADERS-REMOVED-FOR-CLARITY ###
>>
>> Cache-Control: no-cache
>> Postman-Token: db5a119a-e885-4bfd-14ae-8bac119845bd
>> Content-Type: multipart/form-data;
>> boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>> Content-Disposition: form-data; name="json"
>>
>> {   "displayName": "OrderxTest",   "originalFileName": "OrderxTest.pdf",
>> "fileName": "OrderxTest.pdf",   "OrderumentType": "pdf",
>> "OrderumentStatus": "CLEAR",   "attachmentType": "Company",   "category":
>> "DRAFT",   "subcategory": "DRAFT",   "keywords": "",   "notes": [],
>> "fileSize": 163361,   "uploadState": "PROGRESS",   "metadataState":
>> "INCOMPLETE",   "uploadFile": {},   "nextOrder": "" }
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>> Content-Disposition: form-data; name="orderfile";
>> filename="OrderxTest.pdf"
>> Content-Type: application/pdf
>>
>>
>> ----WebKitFormBoundary7MA4YWxkTrZu0gW
>>
>> ### BINARY DATA STREAM REMOVED ###
>>
>>
>> The call fails with the following stack trace clearly something involving
>> the "multi-part" element processing... I am assuming we have made an error
>> in using what were believed to be the CXF-equivalent annotations.
>>
>> java.lang.RuntimeException: *Invalid URL encoding: not a valid digit
>> (radix
>> 16): 80*
>> * org.apache.cxf.common.util.UrlUtils.digit16(UrlUtils.java:114)*
>> * org.apache.cxf.common.util.UrlUtils.urlDecode(UrlUtils.java:94)*
>> * org.apache.cxf.common.util.UrlUtils.urlDecode(UrlUtils.java:66)*
>> * org.apache.cxf.common.util.UrlUtils.urlDecode(UrlUtils.java:121)*
>> * org.apache.cxf.jaxrs.utils.HttpUtils.urlDecode(HttpUtils.java:94)*
>> *
>>
>> org.apache.cxf.jaxrs.utils.FormUtils.populateMapFromMultipart(FormUtils.java:230)*
>> *
>>
>> org.apache.cxf.jaxrs.utils.JAXRSUtils.processFormParam(JAXRSUtils.java:956)*
>> *
>>
>> org.apache.cxf.jaxrs.utils.JAXRSUtils.createHttpParameterValue(JAXRSUtils.java:877)*
>> *
>>
>> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:837)*
>> *
>>
>> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:787)*
>>
>>
>> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
>>
>> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:77)
>>
>> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
>>
>> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
>>
>> org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
>>
>> org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
>>
>> org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
>>
>> org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
>>
>> org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:171)
>>
>> org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:293)
>>
>> org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:212)
>> javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
>>
>> I did try changing the
>>
>> @FormParam("fileInfo") ContentDisposition fileInfo part of the annotated
>> method to
>>
>>
>> @Multipart("fileInfo") ContentDisposition fileInfo
>>
>>
>> and this time the error was quite different, appears the MIME boundary is
>> confusing things ... or we clearly are not using the correct annotations
>> on
>> this:
>>
>> Oct 25, 2015 9:10:08 AM
>> org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils getMultipart
>>
>> WARNING: No multipart with content id fileInfo found, request content type
>> : multipart/form-data;boundary=----WebKitFormBoundarysJRabRa4EZMpZwwB
>>
>> Oct 25, 2015 9:10:08 AM
>> org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
>>
>> WARNING: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
>>
>> at org.apache.cxf.jaxrs.utils.SpecExceptions.toBadRequestException(
>> SpecExceptions.java:84)
>>
>> at org.apache.cxf.jaxrs.utils.ExceptionUtils.toBadRequestException(
>> ExceptionUtils.java:114)
>>
>> at org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getMultipart(
>> AttachmentUtils.java:143)
>>
>> at org.apache.cxf.jaxrs.provider.MultipartProvider.readFrom(
>> MultipartProvider.java:169)
>>
>> at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(
>> JAXRSUtils.java:1340)
>>
>> at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(
>> JAXRSUtils.java:1291)
>>
>> at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(
>> JAXRSUtils.java:824)
>>
>> at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(
>> JAXRSUtils.java:787)
>>
>> at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(
>> JAXRSInInterceptor.java:212)
>>
>> at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(
>> JAXRSInInterceptor.java:77)
>>
>>
>> Trying to understand how, if possible, to only change the annotations on
>> the method signature and still have the POST operation work under CXF.  We
>> have managed to have the GET operations working fine, but there are far
>> less differences the GET operations are using mostly stack independent and
>> rely on standard JAX-RS annotations anyway.
>>
>>
>> Any insight from CXF experts would be appreciated...
>>
>> Thanks
>>
>> Mark
>>
>>
>
> --
> Sergey Beryozkin
>
> Talend Community Coders
> http://coders.talend.com/
>

Reply via email to