Hi Alex, I think that the misunderstanding is that JAX-RS wasn’t conceived, or designed, to build on top of Servlets. JAX-RS is its own separate specification, and it’s perfectly possible to run a JAX-RS container without a Servlet runtime (most JAX-RS implementations provide ways of doing this). That being said, due to the prevalence of Servlet Containers one of the most common ways to host a JAX-RS container is by using a Servlet Container to provide the HTTP connection. For this reason most JAX-RS providers include a “gateway servlet” which can be used to host a JAX-RS runtime within a servlet container.
The JAX-RS and Servlet specifications are also both part of Jakarta EE, which is why the JAX-RS specification includes the one small link to the Servlet specification, that is using @Context to inject an HttpServletRequest. This feature will only work if your JAX-RS runtime is running within a Servlet Container, and so technically isn’t 100% portable. It’s pretty rare, however, to see a production JAX-RS container that isn’t using a Servlet Container to provide the HTTP layer. I’m hoping that this helps to clear up some of the confusion, none of which is within the control of OSGi, Aries JAX-RS or PAX-Web I’m afraid. All the best, Tim > On 3 Dec 2020, at 20:13, Jean-Baptiste Onofre <[email protected]> wrote: > > The annotation should not be required for JAXRS (@Consume and @Producer > should be used). > > So, as said, I gonna enhance the Karaf rest example with multipart. But > tomorrow my time ;) > > Regards > JB > >> Le 3 déc. 2020 à 19:02, Alex Soto <[email protected] >> <mailto:[email protected]>> a écrit : >> >> I hear you Tim, and I appreciate you taking a moment to help me. >> >> I really am no expert on the the inner workings of these technologies >> (merely trying to move forward my application), but it seems to me that if >> JAX-RS was conceived to work on top of Servlet, there should have been a >> way to pass down configuration from the upper layer (JAX-RS) down to the >> lower layer (Servlet), don’t you think? >> >> Specifically, a Servlet can be customized by the @MultipartConfig >> annotation, but the ability to pass this down from JAX-RS is not there, or >> at least, not clear enough. >> >> Best regards, >> Alex soto >> >> >> >> >>> On Dec 3, 2020, at 12:32 PM, Tim Ward <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> As with most Open Source Software efforts, it’s an all volunteer army. I >>> haven’t personally needed to use file upload with JAX-RS, and it’s possible >>> that few of the other users of Aries JAX-RS have either. At least one >>> person seems to have it working (based on the GitHub bug you’ve seen), but >>> they didn’t contribute an example or any documentation improvements. >>> >>> As for the main issue - Multipart upload like this isn’t really supported >>> by JAX-RS. You’re having to fall back to support in the Servlet API, which >>> means you’re not really using JAX-RS to do it. The problems that you’re now >>> encountering are “how do I enable multipart for the servlet hosting my >>> JAX-RS application. In the past (the GitHub bug) it has been sufficient to >>> configure the JAX-RS whiteboard instance to add the “enable multipart” >>> property from the OSGi Http Whiteboard specification. At that point all of >>> the multipart wizardry is being handled by the Http Whiteboard and Aries >>> JAX-RS has nothing to do with it. >>> >>> I would recommend trying to deploy your JAX-RS resource (without the >>> application and application select filter if you can) into a plain OSGi >>> framework using the OSGi Http Whiteboard reference implementation (from >>> Felix), and the Aries JAX-RS whiteboard configured to enable multipart. If >>> this doesn’t work then the answer lies somewhere in Aries, and is a >>> regression since the bug was written. If it does work then this points the >>> finger either at something more complex in the application code, or at >>> PAX-Web. >>> >>> All the best, >>> >>> Tim >>> >>>> On 3 Dec 2020, at 17:12, Alex Soto <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> Hi Tim, >>>> >>>> Thank you for the feedback. Yes, I understand the @MultipartConfig is in >>>> the Servlet Spec, I only added it at the suggestion of others in this >>>> thread. It clearly is not doing anything, as you say. >>>> >>>> Regarding the @Protected annotation, it is irrelevant to the problem, that >>>> is just a name binding annotation to activate a security filter. >>>> >>>> Elsewhere I read that property >>>> osgi.http.whiteboard.servlet.multipart.enabled=true would enable the multi >>>> part support, but this is not working for me. I also tried prefixing it >>>> with “servlet.init.”, as suggested, and it still does not work. I tried >>>> these properties both in my custom JAX-RS Application configuration PID, >>>> and in the org.apache.aries.jax.rs.whiteboard.default, same result. >>>> >>>> Really, I did not expect this to be this obscure, I have not seen any >>>> documentation at all covering file uploads in the JAX-RS Whiteboard >>>> Specification, or in the Aries web site. Is file upload such an obscure >>>> use case to not merit coverage in the examples and documentation? >>>> >>>> >>>> Best regards, >>>> Alex soto >>>> >>>> >>>> >>>> >>>>> On Dec 3, 2020, at 11:23 AM, Tim Ward <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>> Hello, >>>>> >>>>> Having seen the class included in this email chain I can see that your >>>>> example is actually quite complex, and that a couple of things you’re >>>>> trying to do may not be working as you expect: >>>>> >>>>> Firstly, the @MultipartConfig annotation is from the Servlet >>>>> specification, and has no meaning in JAX-RS. The JAX-RS whiteboard will >>>>> therefore not do anything with the annotation. The annotation also has no >>>>> meaning as part of a DS component, and will not result in any service or >>>>> configuration properties being set. Anything that you want to achieve >>>>> using this annotation will therefore most likely not work. >>>>> >>>>> Secondly, you make use of an annotation @Protected, but this isn’t listed >>>>> in your imports. It’s not an annotation that I recognise from the JAX-RS >>>>> or JAX-RS whiteboard specifications, so it’s possible that this >>>>> annotation is also not doing anything. >>>>> >>>>> Thirdly, you are making use of the @JaxrsApplicationSelect annotation - >>>>> this means that your JAX-RS resource will *probably* not target the >>>>> default application (I can’t be sure because the selection filter you are >>>>> using isn’t shown). If your resource isn’t targeting the default >>>>> application then it may also not be targeting the default JAX-RS >>>>> whiteboard. If this is the case then the whiteboard configuration you >>>>> will need to set will *not* be the one with pid >>>>> org.apache.aries.jax.rs.whiteboard.default, but using the factory pid >>>>> that you used to create that whiteboard. >>>>> >>>>> Fourthly, the exception that you’re describing shows up on google as >>>>> being an issue people have had when using Jetty generally. Are you >>>>> certain that Jetty is correctly configured? >>>>> >>>>> Fifthly, have you inspected your running framework to see: >>>>> Generic: The actual service properties on your JAX-RS resource >>>>> Generic: Which application your JAX-RS resource has been bound to, and >>>>> what service properties it has >>>>> Generic: Which JAX-RS whiteboard your application has been bound to, and >>>>> what service properties it has >>>>> Aries specific: What the corresponding service properties are for the >>>>> Servlet Service and Http Context service corresponding to your JAX-RS >>>>> whiteboard >>>>> If any of these aren’t as you expect then that will give a better fix on >>>>> the problem. >>>>> >>>>> Finally, you say that you are using PAX-Web. The Aries JAX-RS whiteboard >>>>> is designed to work with any compliant implementation of the OSGi Http >>>>> Whiteboard >>>>> (https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html >>>>> >>>>> <https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html>). >>>>> I can’t find this specification referenced anywhere in the PAX-Web >>>>> documentation, nor can I find PAX-Web listed as an implementation. This >>>>> doesn’t mean that PAX-Web doesn’t support the Http Whiteboard (it may >>>>> simply not be documented), but the Aries JAX-RS whiteboard makes >>>>> extensive use of features from across the Http Whiteboard specification. >>>>> If there are any gaps or incompatibilities in the PAX-Web support then >>>>> it’s possible that they’re preventing the JAX-RS whiteboard from >>>>> operating properly. Have you tried testing your JAX-RS resource in a >>>>> plain OSGi framework using either the Felix or Equinox Http Whiteboards? >>>>> If this works then it will narrow the search space considerably. >>>>> >>>>> All the best, >>>>> >>>>> Tim Ward >>>>> >>>>>> On 3 Dec 2020, at 12:49, Alex Soto <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>> Yes, of course, I will write you to your email. >>>>>> >>>>>> Best regards, >>>>>> Alex soto >>>>>> >>>>>> >>>>>> >>>>>> >>>>>>> On Dec 3, 2020, at 7:45 AM, Jean-Baptiste Onofre <[email protected] >>>>>>> <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> Hi Alex, >>>>>>> >>>>>>> Not yet started, I will take investigate tonight. >>>>>>> >>>>>>> By the way, any chance we can do direct chat together (to move forward >>>>>>> faster) ? >>>>>>> >>>>>>> Regards >>>>>>> JB >>>>>>> >>>>>>>> Le 3 déc. 2020 à 13:34, Alex Soto <[email protected] >>>>>>>> <mailto:[email protected]>> a écrit : >>>>>>>> >>>>>>>> Hi JB, >>>>>>>> >>>>>>>> Did you have a chance to look into this? It is starting become a >>>>>>>> blocker in our project, so if there is workaround or any hints, I will >>>>>>>> appreciate it. >>>>>>>> >>>>>>>> Best regards, >>>>>>>> Alex soto >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>> On Dec 1, 2020, at 9:03 AM, Jean-Baptiste Onofre <[email protected] >>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>> >>>>>>>>> Don’t worry, I will update the karaf-rest-example. >>>>>>>>> >>>>>>>>> Regards >>>>>>>>> JB >>>>>>>>> >>>>>>>>>> Le 1 déc. 2020 à 15:01, Alex Soto <[email protected] >>>>>>>>>> <mailto:[email protected]>> a écrit : >>>>>>>>>> >>>>>>>>>> I’ll try but these days I'm very busy…. >>>>>>>>>> >>>>>>>>>> Best regards, >>>>>>>>>> Alex soto >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> On Dec 1, 2020, at 8:52 AM, Francois Papon >>>>>>>>>>> <[email protected] >>>>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>>>> >>>>>>>>>>> Hi Alex, >>>>>>>>>>> >>>>>>>>>>> Any chances to have a sample project to share on github? >>>>>>>>>>> >>>>>>>>>>> regards, >>>>>>>>>>> >>>>>>>>>>> François >>>>>>>>>>> [email protected] <mailto:[email protected]> >>>>>>>>>>> Le 01/12/2020 à 14:50, Alex Soto a écrit : >>>>>>>>>>>> No problem, thanks. >>>>>>>>>>>> >>>>>>>>>>>> I think it will help others to have a working example of a File >>>>>>>>>>>> Upload using pure OSGi JAX-RS Whiteboard Specification, all the >>>>>>>>>>>> samples I have found do not go there. >>>>>>>>>>>> >>>>>>>>>>>> Best regards, >>>>>>>>>>>> Alex soto >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> On Dec 1, 2020, at 8:43 AM, Jean-Baptiste Onofre >>>>>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks for the update. >>>>>>>>>>>>> >>>>>>>>>>>>> I’m pretty busy with ActiveMQ, Decanter, Camel and Karaf5 PoC, >>>>>>>>>>>>> but I will take a look tomorrow. >>>>>>>>>>>>> >>>>>>>>>>>>> Regards >>>>>>>>>>>>> JB >>>>>>>>>>>>> >>>>>>>>>>>>>> Le 1 déc. 2020 à 14:29, Alex Soto <[email protected] >>>>>>>>>>>>>> <mailto:[email protected]>> a écrit : >>>>>>>>>>>>>> >>>>>>>>>>>>>> Hi JB, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Yes, Aries JAXRS 1.0.10. >>>>>>>>>>>>>> I suppose it is PAX-WEB, or whatever the default is for Karaf >>>>>>>>>>>>>> 4.3.0. >>>>>>>>>>>>>> >>>>>>>>>>>>>> The class: >>>>>>>>>>>>>> >>>>>>>>>>>>>> import javax.servlet.ServletException; >>>>>>>>>>>>>> import javax.servlet.annotation.MultipartConfig; >>>>>>>>>>>>>> import javax.servlet.http.HttpServletRequest; >>>>>>>>>>>>>> import javax.servlet.http.Part; >>>>>>>>>>>>>> import javax.ws.rs.Consumes; >>>>>>>>>>>>>> import javax.ws.rs.DELETE; >>>>>>>>>>>>>> import javax.ws.rs.GET; >>>>>>>>>>>>>> import javax.ws.rs.PATCH; >>>>>>>>>>>>>> import javax.ws.rs.POST; >>>>>>>>>>>>>> import javax.ws.rs.Path; >>>>>>>>>>>>>> import javax.ws.rs.PathParam; >>>>>>>>>>>>>> import javax.ws.rs.Produces; >>>>>>>>>>>>>> import javax.ws.rs.core.Context; >>>>>>>>>>>>>> import javax.ws.rs.core.MediaType; >>>>>>>>>>>>>> import javax.ws.rs.core.SecurityContext; >>>>>>>>>>>>>> import javax.ws.rs.core.UriInfo; >>>>>>>>>>>>>> >>>>>>>>>>>>>> @Component(service = FirmwareResource.class, scope = >>>>>>>>>>>>>> ServiceScope.PROTOTYPE) >>>>>>>>>>>>>> @JaxrsResource >>>>>>>>>>>>>> @Path(ResourceConstants.FIRMWARE_PATH) >>>>>>>>>>>>>> @JaxrsName("firmware") >>>>>>>>>>>>>> @JaxrsApplicationSelect(Constants.JAXRS_APP_SELECT) >>>>>>>>>>>>>> @Produces(Constants.API_MEDIA_TYPE) >>>>>>>>>>>>>> @Protected >>>>>>>>>>>>>> @MultipartConfig >>>>>>>>>>>>>> public class FirmwareResource { >>>>>>>>>>>>>> >>>>>>>>>>>>>> @POST >>>>>>>>>>>>>> @Consumes(MediaType.MULTIPART_FORM_DATA) >>>>>>>>>>>>>> public void upload(@Context HttpServletRequest request) throws >>>>>>>>>>>>>> IOException, ServletException { >>>>>>>>>>>>>> Collection<Part> parts = request.getParts(); >>>>>>>>>>>>>> ... >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thank you for taking a look at this. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Best regards, >>>>>>>>>>>>>> Alex soto >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Dec 1, 2020, at 1:23 AM, Jean-Baptiste Onofre >>>>>>>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Hi Alex, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In order for me to reproduce, are you using: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> - Aries JAXRS 1.0.10 still (or did you update) ? >>>>>>>>>>>>>>> - Pax Web or Felix as HTTP service ? >>>>>>>>>>>>>>> - Do you have JEE @MultipartConfig annotation on your JAXRS >>>>>>>>>>>>>>> class ? >>>>>>>>>>>>>>> - @Consumers is set to MediaType.MULTIPART ? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> It could be necessary to mimic the JAXRS tests by adding a >>>>>>>>>>>>>>> fragment to bring org.apache.cxf.jaxrs.utils.multipart to Aries >>>>>>>>>>>>>>> JAXRS bundle. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Regards >>>>>>>>>>>>>>> JB >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Le 30 nov. 2020 à 19:19, Alex Soto <[email protected] >>>>>>>>>>>>>>>> <mailto:[email protected]>> a écrit : >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Hello, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Anybody has any insight about this? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Best regards, >>>>>>>>>>>>>>>> Alex soto >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Nov 13, 2020, at 8:54 AM, Alex Soto <[email protected] >>>>>>>>>>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Thank you, João, for your response. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Unfortunately, it is not working for me. I tested adding the >>>>>>>>>>>>>>>>> annotation, and my service look almost identical to yours. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I found this thread >>>>>>>>>>>>>>>>> https://github.com/osgi/osgi.enroute/issues/65 >>>>>>>>>>>>>>>>> <https://github.com/osgi/osgi.enroute/issues/65> in which Tim >>>>>>>>>>>>>>>>> Ward explains about the need to set >>>>>>>>>>>>>>>>> “osgi.http.whiteboard.servlet.multipart.enabled=true” in the >>>>>>>>>>>>>>>>> configuration PID >>>>>>>>>>>>>>>>> “org.apache.aries.jax.rs.whiteboard.default” but that is not >>>>>>>>>>>>>>>>> working either. It still fails with exception: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> java.lang.IllegalStateException: No multipart config for >>>>>>>>>>>>>>>>> servlet >>>>>>>>>>>>>>>>> at >>>>>>>>>>>>>>>>> org.eclipse.jetty.server.Request.getParts(Request.java:2378) >>>>>>>>>>>>>>>>> ~[!/:9.4.31.v20200723] >>>>>>>>>>>>>>>>> at >>>>>>>>>>>>>>>>> org.eclipse.jetty.server.Request.getParts(Request.java:2366) >>>>>>>>>>>>>>>>> ~[!/:9.4.31.v20200723] >>>>>>>>>>>>>>>>> at >>>>>>>>>>>>>>>>> javax.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:375) >>>>>>>>>>>>>>>>> ~[!/:3.1.0] >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> Best regards, >>>>>>>>>>>>>>>>> Alex soto >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Nov 13, 2020, at 4:30 AM, João Assunção >>>>>>>>>>>>>>>>>> <[email protected] >>>>>>>>>>>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Hello Alex, >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I used Multipart with Aries JAX-RS and I'm almost sure I >>>>>>>>>>>>>>>>>> didn't need to mess with the configuration. >>>>>>>>>>>>>>>>>> I annotated the class with @MultipartConfig and placed a >>>>>>>>>>>>>>>>>> @Consumes(MediaType.MULIPART_FOR_DATA). >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> @Path("/firmware") >>>>>>>>>>>>>>>>>> @Component(service = FirmwareService.class, // >>>>>>>>>>>>>>>>>> immediate = true, // >>>>>>>>>>>>>>>>>> scope = ServiceScope.SINGLETON, property = { >>>>>>>>>>>>>>>>>> JaxrsWhiteboardConstants.JAX_RS_RESOURCE + "=true", >>>>>>>>>>>>>>>>>> JaxrsWhiteboardConstants.JAX_RS_APPLICATION_SELECT + >>>>>>>>>>>>>>>>>> "=(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=myApp)" >>>>>>>>>>>>>>>>>> }) >>>>>>>>>>>>>>>>>> @MultipartConfig >>>>>>>>>>>>>>>>>> public class FirmwareService { >>>>>>>>>>>>>>>>>> .... >>>>>>>>>>>>>>>>>> @POST >>>>>>>>>>>>>>>>>> @Path("/upload") >>>>>>>>>>>>>>>>>> @Consumes(MediaType.MULTIPART_FORM_DATA) >>>>>>>>>>>>>>>>>> public Response uploadFirmware(@Context >>>>>>>>>>>>>>>>>> HttpServletRequest request) { >>>>>>>>>>>>>>>>>> try { >>>>>>>>>>>>>>>>>> doUploadFirmware(request); >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Hope this helps >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> João Assunção >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Email: [email protected] >>>>>>>>>>>>>>>>>> <mailto:[email protected]> >>>>>>>>>>>>>>>>>> Mobile: +351 916968984 >>>>>>>>>>>>>>>>>> Phone: +351 211933149 >>>>>>>>>>>>>>>>>> Web: www.exploitsys.com <http://www.exploitsys.com/> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Thu, Nov 12, 2020 at 5:25 PM Alex Soto >>>>>>>>>>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>>>>>>>>>>>>> With Karaf 4.3.0, using Aries JAX-RS 1.0.10, how can I >>>>>>>>>>>>>>>>>> enable multi part support? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I am adding configuration file >>>>>>>>>>>>>>>>>> “org.apache.aries.jax.rs.whiteboard.default.cfg” to the >>>>>>>>>>>>>>>>>> “etc” directory with property: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> osgi.http.whiteboard.servlet.multipart.enabled=true >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> But I am still getting error: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> java.lang.IllegalStateException: No multipart config >>>>>>>>>>>>>>>>>> for servlet >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> When getting parts from HttpServletRequest. >>>>>>>>>>>>>>>>>> Any help will be appreciated. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Best regards, >>>>>>>>>>>>>>>>>> Alex soto >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >
