I am embedding 3rd party JARs in pom.xml. The JARs have few classes which are not part of any package but I want to export these classes using the tag. Please help me how to do the same.
An OSGi bundle cannot import the default package, so there's no use in exporting it from your bundle.
Since you want to export the API, I assume you have one or more other bundles that need to use it. If you are in control of those bundles, I recommend that you try to wrap your own API around the classes that you need to make available. Create this API in a package of your own liking and export that package with the Export-Package header in your jar. See also this SO post: wrap-third-party-jar-that-imports-from-default-package-using-bndtools.
Related
For publishing with SSL using the Endpoint I need to access classes under the packages com.sun.net.httpserver.*
Using the Eclipse IDE I found a way to use this classes. But exporting the bundles and running them in another equinox OSGi Installation I can't start the bundle throwing the following error:
java.lang.NoClassDefFoundError: com/sun/net/httpserver/HttpsConfigurator
Anyone an Idea how to solve this issue?
Thanks!
The package you're referring to is part of the JDK. You need to expose it, to make it available in OSGi and you have two options:
The first, and in most cases preferred option, is to expose this package through the system bundle. The OSGi framework has a property that you can set to do this:
org.osgi.framework.system.packages.extra=...
As its value, you provide it with a comma separated list of packages that you want to expose, on top of the ones that are already exposed by the framework. In your case, at least com.sun.net.httpserver, but there might be more packages that you need. In this case, also make sure that the bundle that uses this package imports this package.
The second option is to use a mechanism used boot delegation. It should only be used as a last resort, as it breaks modularity and if it's not used carefully it might lead to other problems. Again, this is a property that you need to set:
org.osgi.framework.bootdelegation=*
Here, you can provide a comma separated list of packages that should be loaded by the boot class loader. Wildcards are supported (as seen in the example above) but you are encouraged to be as specific as possible, so in your case for example use com.sun.* as the value.
How can resource of a bundle be shared with other bundle(but not just one)?
For example I don't want to duplicate the images or properties file to all bundles, instead I want to access them from a single place.
I tried to use Fragment-Host, but there is not possible to specify multiple bundles(at least I do not know how)
eg:
<!-rest of the pom-->
<instructions>
<Fragment-Host>
com.bundlehost
</Fragment-Host>
</instructions>
As Dmytro notes, you can use OSGi API methods to access the resources in any bundle. However the harder question is this: how do you know from which bundle to access these resources, and how do you know where they are located within the bundle?
If you just make assumptions or hard-code the answer, then you end up with a very brittle system and a hidden coupling between the bundles. Then when somebody deploys your bundles into an application but doesn't include the resource bundle, everything breaks. This defeats the point of modularity.
You can use Bundle.getEntryPaths() and Bundle.getEntry() to get bundle resources. To read content use URL.openStream()
You can also use normal package imports and exports to ensure the resources are on the class path of the consuming bundle. See, for example, access common property file inside bundle with osgi.
I am learning osgi framework. It says osgi works on strict class loading environment. I am unable to get what is Strict ClassLoading. Please help i am unable to get the concept
Thanks
Strict classloading means that a module (bundle) has to explicitly specify what it needs. In OSGi this is done using Manifest headers. Import-Package lists the packages and their version ranges the bundle needs and Export-Package lists the packages and their versions the bundle offers. In the OSGi runtime you then have a classloader per bundle that wires the bundles according to the exports and imports.
You should not define these headers by hand though. There is a nice tool named bnd or in maven the maven bundle plugin from felix which does most of the work for you. In this tutorial you find how this works in practice:
http://www.liquid-reality.de/x/DIBZ
You will see that I actually do not define to much by hand there. So build the code and into the meta-inf/Manifest to see what it does.
strict class loading environment means that the appropriate headers of the class need to be specified. for example the class path and the import-package
In the following senario
I'm wrapping an external jar file (read a dependency I've no control over) and wrapping this in a service to be exposed over RMI.
I'd like my service interface to also be exported as a maven dependency however as it will be returning classes defined in the dependency this means that the dependency itself will be used as a dependency of my service interface.
Unfortunatly the origional jar file contains many classes that are not relevant to my exposed service.
Is it possible to depend on just a few classes in that jar file in maven (possibly by extracting and repackaging the few classes that are relevant)?
uberbig_irrelevant.jar
com.uberbig.beans <-- Need this package or a few classes in it.
com.uberbig.everythingElse
Service project includes all of uberbig jar. But exposes a service BeanService which has a call which returns an insance of com.uberbig.beans.IntrestingLightWeightSerialiasbleBean.
Service interface project needs to have a bean definition that looks like
interface BeanFetcher {
public IntrestingLightWeightSerialiasbleBean fetchBeanById(long beanId);
}
So ideally my serviceInterface jar file would only include the BeanFetcher interface. The definition of IntrestingLightWeightSerialiasbleBean and any direct dependencies of IntrestingLightWeightSerialiasbleBean.
The project is for use internally and won't be publically exposed so there should be no problems repackaging so long as the repackaged bean definitions are binary and searially compatable with the external jar file.
Any Suggestions?
Possibly related question Maven depend on project - no jar but classes
Maybe I could use something from the dependency:copy section of the maven-dependency-plugin but I haven't figured out how to do that.
I think you got the plugin right, but not the goal. You should use dependency:unpack instead.
You should be able to use an inclusion filter to extract only the classes you need, and then repack them into your own jar. (The service interface jar if you do it in the service interface project, but you can just as well set up a separate project.)
Create your own repackaged jar and put it in your local repo. And hope you've actually identified all dependencies, accounting for reflection, etc. IMO not really worth it.
You may be able to do it automatically (with the associated increased risk) by using ProGuard/etc. to pull out unused classes etc. That could be done on your own artifact as well, for example, by making an all-in-one jar via jarjar/onejar/etc.
I have a class with dependencies which I want to hot deploy without restarting the dependencies. The class has an interface but there's only one concrete implementation.
Initially I created a single bundle with exported the interface and registered the implementation using activator and implementation classes which were not exported. However, if I update the bundle, bundles which use the registered service get restarted after the update when PackageAdmin#refreshPackages is called (this is automatic when using fileinstall).
I have fixed this by creating a separate api bundle.
Is this the best way to achieve this?
Would you ever have a bundle which exports its api and includes the implementation in the same bundle. As far as I can see any give bundle would either export all its classes or no classes. What am I missing?
It is definitely a best practice to separate API bundles from their implementations in OSGi. If you do this, then any bundle that uses the API only needs to import classes from the API bundle, which can allow you to change implementations at runtime without restarting your dependent bundles.
Ideally your implementation bundle would implement the interface and export implementation as a service on the API provided interface. This allows the client bundles to utilize the service without referencing the implementation bundle.
In Apache Sling we do both: major APIs are in their own bundles, but for smaller things like extensions or optional components we often provide the default implementation in the same bundle as the API.
In the latter case, you can still allow for those default services to be replaceable, for example using service ranking values when you want to override them.
A bundle does not have to export all its classes, our bundles which include default services export just the API packages (and the default implementations are in different packages, obviously).
Unless there is a hard requirement to be able to replace implementation at runtime, without restarting client bundles, I would personally advocate keeping the explicit dependency link between API and implementation (either by including impl classes in the API bundle, or by having the API bundle import implementation packages from the impl. bundle).
The pb with the patterns suggested above is that they break the dependency chain. The benefits of dependency management go far beyond simple API compatibility, they also include ensuring predictable, consistent runtime behavior, as well as compatibility with the deployment ecosystem, and all of those require managing the implementation dependencies.