I'm trying to get a CXFRS endpoint return a MultiPart response. The CXFRS service is a REST-SOAP proxy, it just receives a POJO and MIME attachments, and forwards that to a SOAP service that returns a MultiPart response with a response POJO and more (different) attachments.
After invoking the SOAP service using a cxf:bean, I see the exchange message holds the response POJO in the body, and the attachments as well. However, I'm having a hard time making SimpleCxfRsBinding include the attachments in the Multipart response. There seems to be a difference in how DefaultCxfBinding and how SimpleCxfRsBinding - including DefaultCxfRsBinding as well - handle exchange mesage attachments. DefaultCxfBinding seems to honour them regardless of method parameters/return type, making them available in the exchange, while the CxfRs ones seem to ignore them. With a REST SEI operation such as this: @POST @Path("/someOperation") @Consumes("multipart/form-data") @Produces("multipart/form-data") @Multipart(value = "jsonResponse", type = "application/json") public BusinessResponse someOperation(BusinessParams parameters); And a route like: from("cxfrs:bean:jaxRSEndpoint?bindingStyle=SimpleConsumer") .setHeader("operationName", "someOperation") .toD("cxf:bean:someService") I only get a few headers as a response, I think due to having a MessageContentsList in the body. If I do .transform().simple("${body.get(0)}") the response is effectively a Multipart response with a single part named "jsonResponse" containing the BusinessResponse POJO only. Found out later this is because SimpleCxfRsBinding just does that explicitly in its buildResponse() method: // avoid using the request MessageContentsList as the entity; it simply doesn't make sense if (base != null && !(base instanceof MessageContentsList)) { response.entity(base); } For some reason toD("cxf:bean") is leaving a MessageContentsList there in the body, maybe it has to do with the fact they're returning MIME attachments apart from the BusinessResponse POJO? Anywyay, my main concern is: How can I include the attachments into the Multipart response, maintaining the name they have in the Messages attachments Map? I'd like ideally to maintain the operation signature intact (the return type) just as the CXF endpoint can do (SOAP SEI has the same exact signature, returning a Multipart response with MIME attachments, and DefaultCxfBinding seems to be able to process the attachments into the Message). One way I've found by trying and playing with the exchange is changing the operation signature to return a MultipartBody and just force that manually in a Processor after invoking the SOAP service: .process(new Processor() { public void process(Exchange exchange) throws Exception { List<Attachment> attachments = new ArrayList<Attachment>(); attachments.add(new Attachment("jsonResponse", "application/json", exchange.getIn().getBody(MessageContentsList.class).get(0))); for (String an : exchange.getIn().getAttachmentNames()) { attachments.add(new Attachment(an, "application/octet-stream", exchange.getIn().getAttachment(an))); } MultipartBody mpb = new MultipartBody(attachments, true); exchange.getIn().setBody(mpb); } }) Unfortunately this looks extremely verbose and specific for the use case this CXFRS endpoint will have to cover. Is there a more generic way? Possibly involving rolling my own Binding class extending SimpleCxfRsBinding or DefaultCxfRsBinding to do something similar to what that Processor does? Made a quick SimpleCxfRsBinding subclass that seemed to work in an extremely simplified case: public static class MyBinding extends SimpleCxfRsBinding { @Override public Object populateCxfRsResponseFromExchange(org.apache.camel.Exchange camelExchange, Exchange cxfExchange) throws Exception { Object base = super.populateCxfRsResponseFromExchange(camelExchange, cxfExchange); Message m = camelExchange.hasOut() ? camelExchange.getOut() : camelExchange.getIn(); boolean methodAnnotatedWithMultipart = true; // This should be looked up on method annotation if (methodAnnotatedWithMultipart && !m.getAttachments().isEmpty()) { List<Attachment> attachments = new ArrayList<Attachment>(); attachments.add(new Attachment("root", "application/json", base)); // Should take part name and MIME-Type from Method @Multipart annotation for (String an : m.getAttachmentNames()) { attachments.add(new Attachment(an, "application/octet-stream", m.getAttachment(an))); } base = new MultipartBody(attachments, true)); } return buildResponse(camelExchange, base); } Unfortunately, this doesn't work with a POJO response type, apparently because CXF itself does something similar, and seems to expect a MultipartBody response type. Can I get any advice or feedback about this binding. Is this a sensible way to approach the issue? Maybe it's just plain wrong trying to achieve this? (pojo arguments operation that will include MIME attachments in the response - it seems to be allowed just fine with the CXF component). Thanks