does anybody know what is possible with Lift and OSGi atm?
I cannot find information on that topic except for some old stuff.
I am asking because it would be really nice to have a website consisting
of several modules (which are OSGi bundles) and
dynamically adding/removing modules. This process should have the
ability to modify the sitemap and register snippets etc.
(I think dynamically adding snippets is already possible)
Thanks in advance
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code
That's why part of my current project contains an OSGi-like library
(written in Scala) specifically for use with Lift. Originally, it was
because I liked some of the OSGi concepts, but lately, it also turns
out that I need the ability to dynamically load and unload contexts.
Donald
(1) For complicated web application, it is good to partition it into bundle or the war will be too large (in OSGi environment).
(2) Sitemap and snippets in Lift make Lift a good web framework for dynamic web application, I means it could be like we develop plug-ins for Eclipse IDE to extend Eclispe IDE. I think this is what madrenegade want to do on Lift. Virgo has a project called Snaps which can plug in a snap to extend a web application at runtime like you extend Eclipse IDE using plugins. But Snaps couple with Tomcat. Because Lift abstract from the servlet implementation, I think Lift could do it even better and portable but it need some further work on Lift.
I have a post about how to fix Lift 2.4 for Lift work on OSGi.
https://groups.google.com/group/liftweb/browse_thread/thread/339f868df413e34b?fwc=1
You also need to solve the classloader issue for templates, CSS/js resource and properties (i18n). The following is what I defined in Boot.scala:
// ClassLoaderFactory is imported from Spring OSGi util package.
val clsLoader = ClassLoaderFactory.getBundleClassLoaderFor( Activator.INSTANCE.getBundleContext.getBundle() )
// our i18n resources
LiftRules.resourceNames = "user" :: "statistics" :: LiftRules.resourceNames
LiftRules.resourceBundleFactories.append {
case ("user", locale) => java.util.ResourceBundle.getBundle("user",locale, clsLoader )
case ("statistics", locale) => java.util.ResourceBundle.getBundle("statistics",locale, clsLoader )
}
// the classpath and context resource, which used to load js/css and template (html files)
var getResource = LiftRules.getResource ;
val getResourceFromBundleClasspath : String => Box[ java.net.URL ] = {
path =>
val bundle = Activator.INSTANCE.getBundleContext.getBundle()
Box !! bundle.getEntry( path ) or Box !! bundle.getResource( path ) or getResource ( path )
}
LiftRules.getResource = getResourceFromBundleClasspath
// lookup props/default.props
val propsPath = "/props/default.props"
val here : () => List[(String, () => Box[java.io.InputStream])] = () =>
List( (propsPath + "ui", clsLoader.getResourceAsStream( propsPath ) match {
case null => ()=>Empty
case i => ()=>Full( i ) }
) )
Props.whereToLook = here
When I did the above, I think how excellent Lift make it independent on OSGi API by its configurable design.
There are issues need to solve or research on further:
(1) How let other bundle to add the above logic in its Activator's start() method, and remove it in Activator.stop() method.
(2) How to refresh SiteMap at runtime when SiteMap is changed by a bundle (add/remove).
I'd like to discuss it with your guys if you think it is interested.
Guofeng
Donald
--
That's certainly not an OSGi question.Basically you have to:1) Define the SiteMap to be as general as possible (for instance, access to all paths under /xxx should be subject to a testing function that is defined externally and makes use of the dynamic site structure). SiteMap will only be used for access testing, not UI.2) Use your own data structure and snippet to display the navigation user interface.