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 | [email protected]<mailto:[email protected]>
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 <[email protected]>
Gesendet: Dienstag, 7. Juli 2020 12:37
An: Fauth Dirk (CAP-SST/ESM1) <[email protected]>; OSGi Developer Mail
List <[email protected]>
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
<[email protected]<mailto:[email protected]>> 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 | [email protected]<mailto:[email protected]>
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
[email protected]<mailto:[email protected]>
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
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev