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/