Hi Tim, Thanks a lot! I would have never come to that solution by myself! Once everything is setup I will write a blog post on that so more people can benefit from this. (and also use it as my “external memory”) ☺
For people that are interested, here the simple solution. 1. I used the enRoute Maven archetypes, therefore Jetty is my HTTP container. 2. As my service should be as minimal as possible, I decided to register a custom whiteboard application in favor of using the ConfigAdmin. @Component(service=Application.class) @JaxrsApplicationBase("app4mc") @JaxrsName("app4mcMigration") @HttpWhiteboardServletMultipart(enabled = true) public class MigrationApplication extends Application { } 3. Then I register my JAX-RS resource against that application and use the HttpServletRequest as suggested. @Component(service=Migration.class) @JaxrsResource @JaxrsApplicationSelect("(osgi.jaxrs.name=app4mcMigration)") public class Migration { @Path("converter") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response upload(@Context HttpServletRequest request) throws IOException, ServletException { Collection<Part> parts = request.getParts(); String filename = ""; for(Part part : parts) { filename += part.getSubmittedFileName(); System.out.printf("File %s, %s, %d%n", filename, part.getContentType(), part.getSize()); } return Response.ok("File uploaded = " + filename).build(); } } Mit freundlichen Grüßen / Best regards Dirk Fauth Cross Automotive Platforms - Systems, Software and Tools, (CAP-SST/ESM1) Robert Bosch GmbH | Postfach 30 02 40 | 70442 Stuttgart | GERMANY | www.bosch.com Tel. +49 7153 666-1155 | dirk.fa...@de.bosch.com<mailto:dirk.fa...@de.bosch.com> Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000; Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar Denner, Prof. Dr. Stefan Asenkerschbaumer, Dr. Michael Bolle, Dr. Christian Fischer, Dr. Stefan Hartung, Dr. Markus Heyn, Harald Kröger, Christoph Kübel, Rolf Najork, Uwe Raschke, Peter Tyroller Von: Tim Ward <tim.w...@paremus.com> Gesendet: Dienstag, 7. Juli 2020 12:37 An: Fauth Dirk (CAP-SST/ESM1) <dirk.fa...@de.bosch.com>; OSGi Developer Mail List <osgi-dev@mail.osgi.org> Betreff: Re: [osgi-dev] How to: File Upload with JAX-RS Whiteboard Hi Dirk, You’re absolutely correct in your statements that: * I know that file upload is more complicated that it looks in first place. * Aries is implemented using CXF, and a mixture of CXF and Jersey seems to be not possible. In fact the Aries JAX-RS whiteboard completely hides the underlying CXF implementation, so unless you start attaching fragments to the Aries bundle you can’t plug in CXF things either. You can only work with the JAX-RS standard. So to strip things back: 1. Using Multipart file upload requires support from the underlying servlet container - does the HTTP whiteboard implementation you’re using underneath Aries JAX-RS support Multipart? 2. If Multipart is supported by your HTTP container then is it enabled? There are several relevant service properties described at https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html#d0e120961<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.osgi.org%2Fspecification%2Fosgi.cmpn%2F7.0.0%2Fservice.http.whiteboard.html%23d0e120961&data=02%7C01%7CDirk.Fauth%40de.bosch.com%7Ced339a20e5bc468f59c108d82261ab23%7C0ae51e1907c84e4bbb6d648ee58410f4%7C0%7C0%7C637297151513644606&sdata=I0ECQBjqEmpGSElFe%2BWsmvPq4%2FPGAXywQvc9CW3FHXk%3D&reserved=0> 3. If you want to use Multipart inside a JAX-RS resource then you need to make sure that your whiteboard application sets the multipart service properties (so that the servlet hosting your application has them too). If you’re registering the application yourself then that’s a simple matter of putting an annotation on it (or however you’re doing your service properties). If you’re using the default application then you will need to configure your JAX-RS whiteboard using Config Admin and the org.apache.aries.jax.rs.whiteboard.default pid (see https://github.com/apache/aries-jax-rs-whiteboard#configuration<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fapache%2Faries-jax-rs-whiteboard%23configuration&data=02%7C01%7CDirk.Fauth%40de.bosch.com%7Ced339a20e5bc468f59c108d82261ab23%7C0ae51e1907c84e4bbb6d648ee58410f4%7C0%7C0%7C637297151513644606&sdata=MGEq0Wm9kVTDujxb9b2XNas4Ijs0507tYsisQVjEIK0%3D&reserved=0>) 4. To use the multipart upload in a JAX-RS resource the easiest thing to do is to inject the HttpServletRequest and consume it from there. For example: @POST @Path("/app4mc/converter") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response upload(@Context HttpServletRequest request) { Collection<Part> parts = request.getParts(); for(Part part : parts) { System.out.printf("File %s, %s, %d%n”, part.getName(), part.getContentType(), part.getSize()); try(InputStream is = part.getInputStream()) { // ... } } } I hope this helps. Tim On 7 Jul 2020, at 11:09, Fauth Dirk (CAP-SST/ESM1) via osgi-dev <osgi-dev@mail.osgi.org<mailto:osgi-dev@mail.osgi.org>> wrote: Hi, I am struggling with the following topic for days now. And I don't find any solution, tutorial or explanation anywhere. So I thought of asking here, hoping to get enlightened. :) I am trying to create a webservice to upload a file which then gets processed on the server. I know that file upload is more complicated that it looks in first place. But this one is driving me crazy. First I tried to use Jersey for the file upload. So I added org.glassfish.jersey.media.multipart as a dependency and created a method like this: @POST @Path("/app4mc/converter") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response upload(@FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition fileMetaData) This resulted in 415 Unsupported Media Type when I tried to upload a file. My guess was that I have to register the MultipartFeature.class, and as I did not know how to do this, I used the approach to register a new @JaxrsApplication via whiteboard and configure it there. This led to severe errors on startup as Aries is implemented using CXF, and a mixture of CXF and Jersey seems to be not possible. As I did not find a solution for this, I thought of using CXF to upload a file. So I added cxf-rt-frontend-jaxrs as a dependency and changed the method to this @POST @Path("/app4mc/converter") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response upload(MultipartBody body) Still 415. Then I read something about org.apache.cxf.jaxrs.provider.MultipartProvider that needs to be registered. So I thought maybe it would work using the @JaxrsExtension as the application is already a CXF application from what I can see in the startup trace. As the CXF MultipartProvider is not annotated with the needed JAX-RS Whiteboard annotations, I created this class for the registeration: @Component( scope = PROTOTYPE, property="serialize.to<https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fserialize.to%2F&data=02%7C01%7CDirk.Fauth%40de.bosch.com%7Ced339a20e5bc468f59c108d82261ab23%7C0ae51e1907c84e4bbb6d648ee58410f4%7C0%7C0%7C637297151513654595&sdata=M99oMsvnAWBiya3%2BGWMyTvUYeXlnBjuQfR7BPQ4yy9E%3D&reserved=0>=MULTIPART") @JaxrsExtension @JaxrsMediaType(MULTIPART_FORM_DATA) public class Multipart extends MultipartProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> { } This results in a IllegalArgumentException: java.lang.IllegalArgumentException: interface org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy is not visible from class loader at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:581) at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557) at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230) at java.lang.reflect.WeakCache.get(WeakCache.java:127) at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419) at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719) at org.apache.cxf.jaxrs.utils.InjectionUtils.createThreadLocalProxy(InjectionUtils.java:1080) I am running out of ideas. Does anybody has a hint or a small example to solve this? I am happy to write a blog post about the findings to help others in the future! :) Sorry for having posted this on the bndtools google group. The mailing list is surely a better place to ask such a question. Mit freundlichen Grüßen / Best regards Dirk Fauth Cross Automotive Platforms - Systems, Software and Tools, (CAP-SST/ESM1) Robert Bosch GmbH | Postfach 30 02 40 | 70442 Stuttgart | GERMANY | www.bosch.com<x-msg://7/www.bosch.com> Tel. +49 7153 666-1155 | dirk.fa...@de.bosch.com<mailto:dirk.fa...@de.bosch.com> Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000; Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar Denner, Prof. Dr. Stefan Asenkerschbaumer, Dr. Michael Bolle, Dr. Christian Fischer, Dr. Stefan Hartung, Dr. Markus Heyn, Harald Kröger, Christoph Kübel, Rolf Najork, Uwe Raschke, Peter Tyroller _______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org<mailto:osgi-dev@mail.osgi.org> https://mail.osgi.org/mailman/listinfo/osgi-dev<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.osgi.org%2Fmailman%2Flistinfo%2Fosgi-dev&data=02%7C01%7CDirk.Fauth%40de.bosch.com%7Ced339a20e5bc468f59c108d82261ab23%7C0ae51e1907c84e4bbb6d648ee58410f4%7C0%7C0%7C637297151513654595&sdata=eD2B9CpW82ILDsKNOVQmVlQlHYV5ARG0Xf3Rm6Jz2dE%3D&reserved=0>
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev