|
I was wandering if you plan to add support for wiring beans through multiple bundles. Example: So I've got bundle-B depending on bundle-A. Bundle-A defines a bean-1 in it's own context.xml. A second bean-2 is defined in the context.xml of bundle-B. This bean-2 needs bean-1 to be initialized. Now if you would detect the dependency to bundle-A you could first start it and try to initialize its ApplicationContext and afterwards bundle-B.
Right now we are using this multiple beans wiring through multiple bundles. We are achieving this by loading all config-locations in one application context. This is done in a "platform"-bundle which has an extension-point for the different config locations. Adrian and I have discussed this before. I think its essential that it be possible to easily wire beans in different bundles together using spring and support dependency ordering. This is one of the nice things that Declarative Services provides and is almost certainly necessary for a fully-featured spring impl.
How well does the "platform" bundle concept work for you? I think this is the right idea, but you would want to avoid hard dependencies on the configuration of other bundles. My $0.02 :) I can think of two different scenarios for wiring beans across multiple bundles.
The case that most closely resembles Spring usage today is to create a single application context using the content of multiple bundles. I think the current implementation precludes this by requiring that contex.xml files be loaded from the bundle resource path (i.e. inside the same bundle), but this restriction can be trivially lifted. This setup would work as follows: Bundle 1 "myApplicationContext" uses the Spring ContextLoaderBundleActivator to fire up an application context. This is configured with resource paths for (e.g.) 3 context.xml files: * org/bundle1/application-context.xml * org/bundle2/application-context.xml * org/bundle3/application-context.xml (Let's assume that the "myApplicationContext" uses the org.bundle1 package prefix, and the other two bundles use org.bundle2 and org.bundle3). The "myApplicationContext" bundle would need an Import-Package header for the bundle2 and bundle3 packages. OSGi would look after the rest, and you'd end up with one application context wiring together beans from the three bundles using the three context files. In the second scenario there are (for example) 2 application contexts (ie. 2 bundles, each using the ContextLoaderBundleActivator). An application context depending on a bean defined in another (non-parent) application context is not something Spring supports today. The way I envisioned this scenario working is via the exporter and proxy factory support: the first application context would use an OsgiServiceProxyFactoryBean to inject a reference to a bean exported by the second context using OsgiServiceExporter. In this second scenario, unless you put in an explicit "Requires-Bundle" header, I don't think there's any easy way to get OSGi to automatically start bundle 2 for you when bundle 1 is started? Which of the two approaches do you need? Or is there a third alternative even that I haven't thought of? Andy>How well does the "platform" bundle concept work for you?
This concept works quite well. Wiring beans is easy and there is just one applicationcontext, which is easy to understand. We are going productive in July. Let's see how it will work then. ;-) Adrian> First scenario: This sounds a little like my setup. Some comments: - How do you configure Bundle1 to have these 3 context.xml? In my setup the Bundle1 "myApplicationContext" has an ExtensionPoint "beans.configlocations" where each Plugin that wants to add beans defines a context.xml location. - Imports of Packages I have different Plugin dependencies in my setup. Bundle2 and 3 depend on Bundle1 e.g. to get it's ApplicationContext and other classes. So Bundle1 can't import packages of Bundle2 and 3. In order to load the different classes in Bundle1 when starting the ApplicationContext, I use BuddyClassLoading of Eclipse. Second scenario: Hmm I don't really understand these exporter / proxy concept. As you see my setup is tight to Eclipse, not just OSGi. And as I said I have a running setup, I'm just interested in a standard setup that might come with an spring version some day. If anyone wants some example code let me know. Adrian,
In standard OSGi there is no way to automatically start bundle 2 when bundle 1 starts, even by adding "Requires-Bundle". The Requires-Bundle directive doesn't have anything to do with lifecycle, only dependency management. See the recent thread on the equinox-dev mailing list, or Peter Kriens's summary in his latest blog entry. In Equinox you can use the non-standard "Eclipse-LazyStart" directive, which asks the container to start a bundle as soon as any class is loaded from the bundle. Therefore if bundle 2 loads a class from bundle 1, bundle 1 will be started. However I consider this a hack, which Equinox introduced in order to support backwards compatibility for existing Eclipse plugins. I prefer your scenario 2 above, namely that the bundle imports and exports services to/from the OSGi Service Layer. I like to consider the Spring application context to be an implementation detail of my bundles, so I don't want to leak the details of that implementation to other bundles by using Spring contexts for inter-bundle dependencies. The advantage of this is that I can interoperate cleanly with non-Spring-enabled bundles. - Neil Hi all,
I am trying to get something really cool to work: Using Jetty as a web servlet container, OSGi inside a sample web application and Spring inside this application. I am pretty happy that I got a small example to work in this environment and this is really cool!!! Now I am trying to get the DispatcherServlet to work properly for a service class inside an OSGi bundle. The problem I encountered is: When using the Dispatcher Servlet Spring is trying to read a special context definition file for that servlet. It is possible to prevent Spring from doing this? Since the setup of the context definition files is spread over different bundles I would need to define some special context definition files for each bundle and allow the Bundle Activator to tell the Dispatcher Servlet somehow to use those definition files. Any idea? Thanks a lot!!! -Martin I have the above patch working with Spring 1.2.7 but I get the exception 'java.lang.IllegalArgumentException: interface com.ineousa.service.DeviceService is not visible from class loader' when I try to run my application. I have spring in one OSGi bundle, my service classes in a second, and factory in a third bundle. The exception is thrown from Proxy.getProxyClass who is checking against the class loader obtained from org.springframework.aop.framework.JdkDynamicAopProxy.getProxy which is the Thread.getContextClassLoader. Should the code in JdkDynamicAopProxy code be getting the class loader from the context and not from the thread.
Kevin: The classloader support currently relies on the CCL being set correctly to the BundleDelegatingClassloader. This then defines classes in the target bundle. I did come across some problems in my prototype env with classloading and log4j and also the env the initial config is read in, I was able to resolve these but it was a bit messy and we probably need a cleaner model for making these things play nicely. Bottom line is that there are some issues which still need resolving. Can you attach your spring config? (or maybe that ought to be a different issue!)
Martin: I'm not sure I fully understand your problem. Certainly the files that are currently looked for need some work. Do you have a stacktrace? What BundleActivator are you using? Great that Spring is getting OSGI support. We're currently looking at using OSGI for handling and reloading our services and if we could reuse some of our spring configuration that would be great.
One thing though. If a bean is exported through spring-osgi the actual implementation is used as the service name. ServiceRegistration sReg = this.bundleContext.registerService(bean.getClass().getName(), bean, serviceProperties); Wouldn't it be more logical to allow specification of the name for which the service was registered, e.g. the interface name the service implements. That way the services can be used from osgi in an implementation independ way. Just a small addition to my previous comment. I modified the OsgiServiceExporter to use maps as a way to specify the beans that need to be exported:
<bean class="org.springframework.osgi.service.OsgiServiceExporter"> <property name="exportBeans"> <map> <entry> <key><value>exampleService</value></key> <value>osgi.example.ExampleService</value> </entry> </map> </property> This way I can use the osgi-spring components to make my spring beans easily available in my bundle and hide the implementation. This works on the latest knoplefish osgi implementation. Another thing though to get the spring integration working with knoplefish (haven't tried any other implementation) is that the ContextLoaderBundleActivator fields needed to be changed to remove the ".", they threw an illegalargumentexception when running. Changing this to the following field names fixed this. private static final String CONTEXT_LOCATION_HEADER = "org-springframework-context"; private static final String PARENT_CONTEXT_SERVICE_NAME_HEADER = "org-springframework-parent-context"; Hope this is some use to you. Btw. if you want a patch for this let me know. Actually the implementation has changed quite a bit since the drop in cvs. The newer code allows you to indeed specify the interface to the service exporter as you wish. The context names are also changed.
There is a spec now and the impl mostly reflects the spec. We should probably consider doing another drop of both. Thanks for your comments! I'm confused as to when this OSGi support will be released --
http://forum.springframework.org/showthread.php?t=23749 (from April) says it won't be out within the 2.0 timeframe. http://forum.springframework.org/showthread.php?t=25234 (from May) says it *will* be out with 2.0. And this bug report says 2.1 RC1. Is there a definitive release date? Thanks. 2.1 since 2.0 is closed for business. The OSGi support may even be released as a separate module.
If you could do another drop that would be very useful. That will make it easier for me to change to the official release once it gets released.
Andy, you said that there is a spec for this work. Is the spec available somewhere so we can see what's coming?
I would like to take a look at that spec too
Current Spring/OSGi specification
I'm working on an updated version of the specification following a face-to-face meeting held last week with some of the key players. I'll attach it to this bug report as soon as it is available.
Spring 2.0 has done much of the hard work to ensure that the Spring container behaves well in an OSGi environment (so that a bundle providing the Spring framework code can properly load application classes and resources defined in another bundle for example). The target release for the full support (all Spring jars shipping as legitimate OSGi bundles, and Spring support for OSGi namespace etc.) is Spring 2.1. We'll look to update the code in the public sandbox as soon as we can. I am doing a study on a project inside my company and I am particularly interested in the Spring/OSGi integration. I have read the specs attached to this issue and it looks very nice to me. Elegant and simple(in the sense of Einstein simplicity for theoretical physics :-)) as all the Spring framework.
Can we know, at least approximatively, for when is Spring 2.1 scheduled? An year from now on? Or is it possible to have Spring packaged as OSGi bundles earlier? Thanks a lot! Attaching version 0.7 of the specification to this report. Note that the schema in appendix B still needs updating. I'll repost once that is available.
Hi Cristian,
We haven't set a date for Spring 2.1 yet but it's not going to be as major a change as from 1.2 -> 2.0, so I would hope it is substantially less than a year!. Andy Piper has actually done the work of a one-off conversion of the Spring jars into OSGi bundles for Spring 2.0, we'll make these available publically based on the final version of Spring 2.0 as soon as that is available (September). The OSGi support code should also be available for download and experimentation well in advance of the final release of Spring 2.1 - you should see code arriving in the early milestone builds. Regards, Adrian. Attaching the finished 0.7 level of the specification, including updated schema.
I'll close this SPR issue, since we have the OSGi sister project now.
We have a separate SPR issue for delivering properly OSGi-fied jars in the Spring core distribution. Juergen |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- Adds support for ContextLoaderListener so that OSGi bundles can be spring-enabled non-intrusively. This works the same way as the servlet ContextLoaderListener. It listens for OSGi bundle events and creates an appropriatre Spring ApplicationContext when a bundle is started.