osgi HttpService register resource from outside of the bundle ( filesystem ) - osgi

I am using OSGI's HttpService to register my servlets and resources.
To register resource I am using HttpService.registerResources(java.lang.String alias, java.lang.String name, HttpContext context)
I have tested that "name" can take any relative path inside the bundle. example /resource where resource is a folder inside the bundle jar.
But I want to give "name" a value outside of the bundle example /home/user/webapps/resource.
i.e. name links to the filesystem's path.
I want to know if that's possible and how ?
I saw a similar post but it didn't conclude.
how to get the image which is outside the OSGi bundle?

An easy way to fetch objects from outside the bundle is to implement a servlet as Robert described it.
A better way, were you have much better control on what objects to return, correct MIME type handling etc. is to implement an HttpContext object and to register it with the HTTP Service. The HTTP Service then always calls method HttpContext.getResource(String name) whenever a resource is requested. And here you can serve your objects from the file system. From the specification:
public URL getResource( String name )
Called by the Http Service to map a
resource name to a URL. For servlet
registrations, Http Service will
call this method to support the
ServletContext methods getResource and
getResourceAsStream. For resource
registrations, Http Service will
call this method to locate the named
resource. The context can control from
where resources come. For example, the
resource can be mapped to a file in
the bundle’s persistent storage area
via
bundleContext.getDataFile(name).toURL()
or to a resource in the context’s
bundle via
getClass().getResource(name).
Please have a look at section 102.3, Registering Resources and following of the OSGi Service Compendium. There, the whole concept is explained in detail and with examples.

I am not familiar with the deep internals of HttpService.registerResources(..) but my work-around solution would be to implement a Servlet that delivers the resources. As it is your own implementation you can access the filesystem as well.
The only thing you have to keep in mind when implementing that Servlet is to set the correct Content-Type and may be other required response header fields.

Related

Spring Boot classpath: vs relative path

In Spring Boot, to access a resource, say myresource.json, I can use both classpath: or a relative path, like ./myresource.json
What is the difference? Which one should I use?
When you call getResource() on a specific application context, and the location path specified doesn't have a specific prefix like ./myresource.json, you will get back a Resource type that is appropriate to that particular application context.
If getResource() was executed against a ClassPathXmlApplicationContext instance it will return a ClassPathResource.If the same method was executed against a FileSystemXmlApplicationContext instance, you'd get back a FileSystemResource. For a WebApplicationContext, you'd get back a ServletContextResource, and so on.
As such, you can load resources in a fashion appropriate to the particular application context.
On the other hand, you may also force ClassPathResource to be used, regardless of the application context type, by specifying the special classpath: prefix.
See this doc

Spring boot - Serving static content

I have issues configuring Spring boot 1.2.0.M1 to serve static content.
As soon as I add a #RestController component in my application, the static content is not displayed and I get the whitelabel error page instead. My resources are in the src/main/resources/static folder.
I followed the instructions at http://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot and managed to have them displayed by setting the ResourceHandlerRegistry priority to -1. But i guess it is not the standard and right way to do it. It seems that the handler of the REST resources takes priority over the resource handler registry. Is there a possibility to configure the handler for rest resource to be used for a sub-context only like /api ?
Update:
I have put the DispatcherServlet in debug and I have better understanding on why this is happening but still not sure what would be the best way to deal with it.
I have noticed that the following handlers are registered in the Dispatch servlet in the respective order by default :
SimpleUrlHandlerMapping -> favico
RequestMappingHandlerMapping -> annotated #RestController methods registered
SimpleUrlHanderMapping -> / (home page handling ?)
BeanNameUrlHandlerMapping
SimpleUrlHandlerMapping -> handles resources configured in the resources registry
WebMVCConfigurationSupport handler
When I perform a POST on the REST resource 2. handles it.
When I perform a GET on a static resource 2. throws a HttpRequestMethodNotSupportedException because it cannot find the resource (in its handleNoMatch method).
If i change the priorities using ResourceHandlerRegistry#setOrder(Ordered.HIGHEST_PRECEDENCE); 5. is placed before 2. but in this case i cannot perform a POST /user/api intended for my REST resource, it is not matched as a resource (i have configured a /** pattern for the resource handler).
If i compare to what node.js/express does for instance is that you configure routes for your controllers and if none matches the request, the request is handled by the handler for static resources or templates.
Do you know how if it is possible through annotation to have the 2 (i.e RequestMappingHandlerMapping ) not throw an exception but just pass the request to the next handler in the chain in case of no-match ?
I'd like avoiding having a specific context (/static for static resources).
Update 2:
Actually it was just a misconfiguration of my annotated REST controller #RestController
I configured the path in the value attribute of the annotation that is not meant for that but to store the controller's name
I forgot to add the #RequestMapping therefore the handler RequestMappingHandlerMapping was enabled for any url path and the get request did not match any annotated methods, therefore it returned an error.

Autofac with Web API: inject dependencies from HttpRequestMessage?

I have a need to inject certain values from the HttpRequestMessage (mostly revolving around identity) into some of my objects.
As I understand it, using HttpSession.Current is not recommended in the Web Api framework. How do I access the HttpRequestMessage for user's Identity and other attributes such as user's IP address, UserAgent, etc. during binding of my dependencies in Autofac?
You can use builder.RegisterHttpRequestMessage() while you're building your dependency container. After that, anything that takes an HttpRequestMessage as a dependency will get the current message.
Adding to the accepted answer of #Travis Illig, the full call should be something like this:
builder.RegisterHttpRequestMessage(System.Web.Http.GlobalConfiguration.Configuration);

Webapi DefaultHttpControllerSelector does not properly resolve my controller

I have an WebApi application that contains some controllers (they are registered using the extension method RegisterApiControllers). This application references another assembly that contains other controllers that I don't want to expose(I have checked that they are not registered in the container). It happens that both have an OrderController, and when I try to access the /api/Order url, I get an exception "Multiple types were found that match the controller named 'order'." and the stack trace shows that I was in DefaultHttpControllerSelector.
I have seen that AutofacControllerFactory used to exist and there was even a ConfigureWebApi that registered it, but it is not anymore present in the default branch.(you can see it here http://alexmg.com/post/2012/03/09/Autofac-ASPNET-Web-API-(Beta)-Integration.aspx)
It seems also that we can not filter the namespace of the route definition in WebApi (it is possible to MVC).
So any idea on how I can use only the Controller registered in my Autofac container and not use the DefaultHttpControllerSelector that seems to scan all referenced assemblies to discover controller?
Thanks
The problem is that registering the controller with autofac is not really related to the routing process. Only once the routing process has identified which controller to dispatch to will Autofac be called to resolve the type.
It looks like, from digging around in the source, that you would need to write a replacement IHttpControllerSelector in order to handle two controllers with the same name. (which really sucks BTW).
You might be able replace the DefaultHttpControllerTypeResolver with an instance that is passed a predicate that filters out the controllers from the assembly that you want to ignore. It's a bit of a kludgy solution but might work.
Actually, you might be able to replace the DefaultHttpControllerTypeResolver completely with one that is based on registrations in your Autofac container. It is a very simple interface, so as long as Autofac have a some kind of discovery mechanism, you should be golden.
public interface IHttpControllerTypeResolver
{
ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver);
}

Springframework application context resource resolver

Does anyone know how to manipulate a spring application context to use a specified resource resolver. I have written an s3 resource to pull content from a security context from amazon s3, and a resource resolver to create these "resources" from s3://... type urls, and the local application context uses the right security credentials on load from the configured amazons3client. I've written an s3 ResourceLoader that preconfigure the AmazonS3 client for a newly constructed s3 resource.
It would be nice to be able to specify these resources in the context configuration as simply "s3://..." and rely on this resource resolver to create the right resource type, however, so far this requires overriding the spring ApplicationContext's getResource method inherited from DefaultResourceLoader to use my own resourceResolver implementation.
Another tack is to configure a variable resolver for resources matching the "s3://..." scheme to resolve resource types with that resource resolver.
I am hoping their is a spring guru out their that knows a better way to manipulate the infrastructure of the spring application context (ClasspathXMLAC for arguments sake) to make my S3 security needs very easy to deal with.
Other suggestions are welcome.
Use an implementation of Spring's GenericApplicationContext, which provides you with a #setResourceLoader method.
You mentioned ClassPathXmlApplicationContext, which is not a GenericApplicationContext, meaning that you're forced to take the uglier overriding route.
GenericXmlApplicationContext is a generally preferred alternative to CPXAC, and as the name suggests, is a GenericApplicationContext.
So you should be able to do the following:
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.setResourceLoader(new S3ResourceLoader());
ctx.load("s3:///some.bucket.name/path/to/my/spring.xml");
ctx.refresh();
...
Obviously, the S3ResourceLoader will need to be parameterized with keys, etc. Note that the S3ResourceLoader should probably extend DefaultResourceLoader in order to pick up all the other functionality available there, e.g. processing "classpath:" and other resource prefixes.
Order of invocation in the above example matters, i.e. the resource loader needs to be provided before #load is called with an s3: resource prefix for obvious reasons.

Resources