I apologize for not being clear that I was trying to use this service from non-bundle code. I had mentioned in my initial email that I was running Felix embedded in my app but I now realize that did not necessarily mean that that is what I was trying to do.
I am now getting a non-null reference to a RepositoryAdmin. It seems I had to additionally include the version of the bundle repository bundle being exported from the system bundle. So my using org.osgi.framework.system.packages.extra now looks something like this: org.osgi.framework.system.packages.extra="org.apache.felix.bundlerepository;version=\"2.1\",..." Neil, thanks for the detailed description of what needed to be done here; it helped a lot. Here's a more general question: ideally what I'd like OSGi to do for me is allow me to declare my dependencies by symbolic name only and on startup the framework would check my configured bundle repository for updates. If there were any newer versions of installed bundles, to fetch them, install them and start them. Is there some way to do that 'out of the box' or do I have to write custom code? I'm in the process of writing code to do this for our plugins. I've gotten the impression that Apache Karaf is at a higher level but have not looked at it in detail and so I don't know if it can do this. Thanks to all for the help so far. Tim On 08/07/2014 06:53 AM, Neil Bartlett wrote: > Hi Tim, > > First, the fact that you are doing this from outside of the OSGi framework > might have been quite useful information to highlight up front. It changes > everything! Just saying ;-) > > Consuming services from outside OSGi when they are published from inside a > bundle is pretty tricky… it can be done but you need to be very careful about > the API package imports and exports. > > In a “normal" situation, you have one of the following two scenarios: > > a) The service provider bundle exports the API package, and the consumer > imports it. > b) There is a separate API exporter bundle, and both the provider and the > consumer import from there. > > However in your situation, the “outside” (aka the OSGi system bundle) is the > consumer and unfortunately the system bundle CANNOT IMPORT from ordinary > bundles. So you have to do two things. First, arrange for the API to be > exported by the system bundle, using > org.osgi.framework.system.packages.extra. Then, make sure that the provider > bundle imports the API from the system bundle. This part might be tricky > because the provider bundle might be trying to export its own copy of the > API, though hopefully it also imports to allow for substitution. You need to > be careful to export from the system bundle with a version that satisfies the > provider bundle. > > If you get this wrong, and the provider bundle either uses its own package or > imports it from somewhere that is not the system bundle, then the service is > considered incompatible and it will be filtered out as I described in my > previous email. It sounds like this is exactly what is happening, because you > said the ServiceReference was null. > > Finally I would point out that what you’re doing is an advanced use case for > OSGi. It might be better to either get more experience with mainstream OSGi > usage before tackling this level of problem, or perhaps get yourself some > training or consulting from an expert. > > Kind regards, > Neil > > > On 7 August 2014 at 04:23:40, Tim McIver ([email protected]) wrote: > > Renato, > > Thanks for the response. You actually made me feel a lot better about > myself! I have been struggling to understand how to use OSGi (and > continue to). It's not what I thought it was when I started out; it is > indeed low-level - much lower level than I anticipated. I do intend to > move on to using Blueprint but I've inherited this project and it is > using OSGi at this low level right now. And I've been reading both > "OSGi In Action" and "Enterprise OSGi In Action". > > I've solved my main problem. The advice that I've been given here was > well-intentioned but it seemed to be predicated on the idea that the > code consuming the RepositoryAdmin service was in a bundle, which it was > not. I'm trying to access a RepositoryAdmin from my non-bundle app > code. I solved the ClassCastException issue by adding the > 'org.apache.felix.bundlerepository' package to the > FRAMEWORK_SYSTEMPACKAGES_EXTRA string. I got the idea from here: > http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html#ApacheFelixFrameworkLaunchingandEmbedding-hostserviceusage. > > > But now I have another problem: the RepositoryAdmin service reference is > null. I've installed and started the Felix bundle repository bundle. > I'm not sure what else to do. Any ideas on this one? > > Thanks, > Tim > > On 08/06/2014 04:33 PM, Paulo Renato de Athaydes wrote: >> I think he meant the package imports in the MANIFEST file. >> You need to make sure you are importing the package where RepositoryAdmin is >> (which should be in an API bundle) with the exact same version in both the >> consumer bundle of the service and the implementator bundle of the service. >> Look out for split packages (packages that are exported by more than one >> bundle, you really don't want that to happen)!! >> By the way, if you need to depend so much on the osgi API, I would imagine >> you're doing something really low-level. >> I have been using OSGi for a long time and I practically never depend on the >> OSGi API (so my classes are always POJOs) or need to worry about writing >> MANIFEST files (but I do like to read to make sure BND is doing what I want >> it to, via either the Maven Bundle Plugin or Gradle's OSGi plugin), >> publishing/consuming Services manually (which I usually do with Blueprint, >> but have now switched to IPojo) or anything else related to OSGi other than >> just declaring which packages I want to Export from each bundle (not Import >> because that should be done automatically). The chance of error if you >> manage these things manually is just too big. >> If you use Maven, have a look at the dependencies of your projects. That's >> where the Bundle plugin will gather information about which versions of each >> packages your bundles should import. Don't mess with package imports, let >> the plugin do its job and then check the MANIFEST to see what you've got >> (ie. don't explicitly say which packages you will import in the pom.xml)... >> If you get ClassCastException for classes that are clearly compatible (you >> may even get something like MyClass cannot be cast to MyClass) you just have >> some issues with your imports (as already mentioned) for your bundle (not >> the Java imports!), ie. the bundle which exports the service sees one >> version of MyClass, the bundle which imports it sees another version of it. >> Hope this makes you understand how this stuff works. I had to read OSGi in >> Action (for the low-level details) and also Enterprise OSGi in Action (for >> the real-world usage) to get my head around OSGi, and now I understand it (I >> hope!), and I love it... if you keep trying to just google for information >> about OSGi when something doesn't work you will go down the same path as >> most people and start hating it because you just couldn't get it. >> >> Regards, >> Renato >> >>> Date: Wed, 6 Aug 2014 11:58:52 -0400 >>> From: [email protected] >>> To: [email protected] >>> Subject: Re: RepositoryAdmin ClassCastException >>> >>> Neil, >>> >>> Thanks for your reply. Here are the OSGi/Felix -related imports I have >>> in the class that contains the code that I included in the original >>> email (below): >>> >>> import org.apache.felix.bundlerepository.Resource; >>> import org.apache.felix.framework.Felix; >>> import org.apache.felix.framework.util.FelixConstants; >>> import org.apache.felix.bundlerepository.RepositoryAdmin; >>> import org.osgi.framework.Bundle; >>> import org.osgi.framework.BundleException; >>> import org.osgi.framework.BundleContext; >>> import org.osgi.framework.Constants; >>> import org.osgi.framework.ServiceReference; >>> import org.osgi.util.tracker.ServiceTracker; >>> >>> Regardless of which import I'm using I'm still confused as to how this >>> discrepancy can exist since I'm requesting an implementation of the >>> RepositoryAdmin I'm importing. >>> >>> Thanks for the tip about how to open the ServiceTracker. We are indeed >>> using open() without an arg. I was not aware of that gotcha. >>> >>> Tim >>> >>> On 08/06/2014 11:18 AM, Neil Bartlett wrote: >>>> Tim, you don’t really need to know anything about classloaders! The >>>> important part from David’s email was the second paragraph. Make sure you >>>> import the same package that the provider of the service uses, and you >>>> will be okay. >>>> >>>> By the way, how did you open your ServiceTracker? Did you call open(true)? >>>> If so, this exposes you to incompatible services and potential >>>> classloading issues… you should nearly always use open(false) or the >>>> no-arg open() method, which is equivalent. Then OSGi protects you from >>>> seeing service instances that are incompatible with your bundle. >>>> >>>> Regards, >>>> Neil >>>> >>>> >>>> On 6 August 2014 at 16:04:32, Tim McIver ([email protected]) wrote: >>>> >>>> David, >>>> >>>> Thanks for the reply. I figured it had to do with Class loaders but I'm >>>> at a loss as to how this is happening; I don't know a lot about class >>>> loaders. >>>> >>>> Here's some more detail on my situation: as I said we're using Felix in >>>> an embedded fashion; we instantiate a Felix object and start it from >>>> within a JavaFX app (we're using IntelliJ). I suppose this is the >>>> source of the different classloaders. The reason I'm confused is that >>>> we have been successfully using a ServiceTracker to get references to >>>> our plugins without any classloading issues. So how can I fix this? Do >>>> I need access Felix's classloader and use it to load the >>>> RepositoryAdmin? Any pointers on how to do this? >>>> >>>> Thanks, >>>> Tim >>>> >>>> On 08/06/2014 03:15 AM, David Bosschaert wrote: >>>>> Hi Tim, >>>>> >>>>>> java.lang.ClassCastException: >>>>>> org.apache.felix.bundlerepository.impl.RepositoryAdminImpl cannot be >>>>>> cast to org.apache.felix.bundlerepository.RepositoryAdmin >>>>> This happens when the RepositoryAdmin interface is loaded from a >>>>> different classloader than where the RepositoryAdminImpl loads it >>>>> from. >>>>> >>>>> You need to check that the bundle that runs your code has an import on >>>>> the org.apache.felix.bundlerepository package like this: >>>>> Import-Package: org.apache.felix.bundlerepository;version="[1.0,2)" >>>>> and is wired to the same bundle where you get the RepositoryAdminImpl >>>>> from. >>>>> >>>>>> By the way, is there javadoc for Felix? I can't seem to find any. >>>>> If you're looking for documentation on Felix, it might be best to look >>>>> for general OSGi Framework documentation. You can find information on >>>>> the Felix Framework in the OSGi Core R5 specs [1] or in one of the >>>>> many books and web articles about the OSGi framework. >>>>> >>>>> For documentation about the Bundle Repository, it might be worth >>>>> looking at the OSGi R5 Enterprise Specs (also at [1]). Chapter 132 >>>>> describes the OSGi Repository Service. Since version 2.0.x this is now >>>>> also implemented by Felix OBR so using that gives you a standard API >>>>> to work with the Repository. >>>>> >>>>> Cheers, >>>>> >>>>> David >>>>> >>>>> [1] http://www.osgi.org/Download/Release5 >>>>> >>>>> On 5 August 2014 20:38, Tim McIver <[email protected]> wrote: >>>>>> Hello, >>>>>> >>>>>> I'm using Apache Felix in an embedded fashion. I'm attempting to access >>>>>> my own bundle repository so I install and start the bundle repository >>>>>> bundle like so: >>>>>> >>>>>> // install the Felix OBR bundle >>>>>> Bundle obrBundle = null; >>>>>> try { >>>>>> obrBundle = >>>>>> m_felix.getBundleContext().installBundle("file:/home/tim/workspace/clojure/lambdaprime/metascrape-ui/lib/org.apache.felix.bundlerepository-2.0.2.jar"); >>>>>> >>>>>> } catch (BundleException e) { >>>>>> System.err.println("Error installing Felix OBR bundle."); >>>>>> e.printStackTrace(); >>>>>> } >>>>>> >>>>>> // start the Felix OBR bundle >>>>>> if (obrBundle != null) { >>>>>> try { >>>>>> obrBundle.start(); >>>>>> } catch (BundleException e) { >>>>>> System.err.println("Could not start Felix OBR bundle."); >>>>>> e.printStackTrace(); >>>>>> } >>>>>> } >>>>>> >>>>>> I have a private method to get a RepositoryAdmin: >>>>>> >>>>>> private static RepositoryAdmin getRepositoryAdmin(BundleContext ctx) { >>>>>> ServiceReference ref = >>>>>> ctx.getServiceReference(RepositoryAdmin.class.getName()); >>>>>> if (ref != null) { >>>>>> return (RepositoryAdmin)ctx.getService(ref); >>>>>> } >>>>>> return null; >>>>>> } >>>>>> >>>>>> But when this method is called, I get the following exception: >>>>>> >>>>>> java.lang.ClassCastException: >>>>>> org.apache.felix.bundlerepository.impl.RepositoryAdminImpl cannot be >>>>>> cast to org.apache.felix.bundlerepository.RepositoryAdmin >>>>>> >>>>>> I'm using felix.jar from the bin directory of of the 4.4.1 distribution >>>>>> and using org.apache.felix.bundlerepository-2.0.2.jar for the bundle >>>>>> repository. Any ideas what my issue is? >>>>>> >>>>>> By the way, is there javadoc for Felix? I can't seem to find any. >>>>>> >>>>>> Thanks, >>>>>> Tim >>>>>> >>>>>> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: [email protected] >>>>>> For additional commands, e-mail: [email protected] >>>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: [email protected] >>>>> For additional commands, e-mail: [email protected] >>>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: [email protected] >>>> For additional commands, e-mail: [email protected] >>>> >>>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: [email protected] >>> For additional commands, e-mail: [email protected] >>> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]

