How can i control access to my bundles. I have a set of bundles that expose packages through export in MANIFEST.MF. Packages exposed are supposed to be used only within my set of bundles. No other external bundles should be allowed to use these packages using "import package".
Is there any way i can impose these restrictions?
You can take a look at OSGi Security (2.Security Layer OSGi Core Spec) to manage restrictions to various resources (bundles, packages, services etc.).
In your case you can set PackagePermission with IMPORT/EXPORT actions to your bundles. The other bundles will not have any permissions to import your packages.
First, is it a problem that someone else imports your package? Unless you're exporting implementations that no one should see (in which case you should reconsider your partitioning anyway), there is usually no problem in having some packages lying around that others may or may not import.
If you're sure you need to hide certain packages, there are no easy ways to do so. Some things that come to mind are
use a ResolverHook to restrict the visibility of your packages (only available from 4.3),
run your bundles in an embedded framework, and only expose the packages you want to share from that framework to the host.
However, both of these are pretty heavy-handed methods, and I would stay away from them unless you're e.g. building your own application server.
Related
I was wondering if it is somehow possible to create a fallback from one activation method to another?
Let's say i have a bundle that is activated via Declarative Services, but SCR is not installed on the application server in question. Is it possible to have a bundle with both Declarative Services and Blueprint activators, and decide the load order?
For example: Can i make a bundle and specify that it should be loaded by SCR if available, and Blueprints if SCR is not installed?
If you want to use SCR functionality and your bundle is installed in an app server that doesn't have SCR then the easiest answer is to install SCR. It's a single, small bundle, and it is a dependency of your bundle just as much as the packages etc that you depend on.
If you really cannot install SCR or rely on SCR already being available, then you need to write a BundleActivator. This is normally only necessary for very low-level "plumbing"-type bundles, or when running on extremely resource-constrained devices.
This is not possible. I think the best practice is to decide for one of the two. If you are concerned about additional dependencies you introduce then DS is the better choice as it only needs one bundle to work.
Can a OSGi bundle have two dependencies, each on a different version of the same OSGi bundle?
Can a OSGi package have two dependencies, each on a different version of the same OSGi package?
(I am trying to learn OSGi from the ground up. This question is just intended to help me understand the basic concepts. From reading online articles about OSGi services, I gather that such dependencies certainly wouldn't be recommended practice. But are they possible at all?)
(Update: rephrased the two questions.)
No. OSGi provides a consistent class space for a bundle. This means that it is only exposed to a single class of a given name. So a bundle cannot simultaneously see more than one version of a package at a time.
This does not mean that ClassCastExceptions are impossible since code your bundle is directly dependent on, can expose objects from their dependencies to your bundle. The proper use of uses constraints on export packages is important to prevent this.
Can a OSGi bundle depend on two different versions of another OSGi bundle at the same time?
Can an OSGi package depend on two different versions of another OSGi package at the same time?
Sort of. You can depend on ranges or specific versions of another OSGI bundle or package like this:
Import-Package: org.osgi.framework;version="[1.3,2.0)"
Not sure if that applies in the first section because bundles should not depend on other bundles, only packages. This is what 'Require-Bundle' does but is suggested you don't use it. Require-Bundle takes versions as well so theoretically it should support version ranges.
Once your OSGi bundle is resolved within OSGi, it will find the package of any of those versions. However, it can't resolve a package (org.osgi.framework) to two separate bundles (one which provides version 1.9 and one which provides 1.8). It will choose the most recent version based on SemVer.
If you try to specify it twice in Import-Package, you will get a 'Duplicate Import' error.
I'm just learning Websphere 8.5 and would like to know what is the simplest way to add a library, such as iText library so that it's available to all applications running on WAS.
I can see that both a Shared Library option is available in the Admin console and a some more advanced thing like "Business Level Application" which is made up of several assets.
What is the correct approach to achieve my goal ?
Thanks
You should not develop your applications with implicit dependencies which are in fact explicit. If the dependency is crucial for your application, it should be somehow marked as such.
With that said, there are two approaches in WebSphere - a shared library or OSGi bundle.
For the shared library concept, read Associating shared libraries with applications or modules.
If you use OSGi to develop your application(s), I'd recommend declare the dependencies in Application-Content of APPLICATION.MF and have them available in Internal or External bundle repositories.
I don't think BLA applies in your scenario, but would not be surprised to see how wrong I am.
p.s. Wonder why the question is tagged as websphere-7 since it refers to WebSphere 8.5?
What is the difference between spring source dm server specific Import-Bundle and OSGi's Require-Bundle?
I am confused whether to use Import-Bundle or Require-Bundle in my project.
Import-Bundle is similar to Require-Bundle, it creates a complete dependency on the other bundle, including that bundle's dependencies. This transitivity is bad because you have no idea what you depend, creating the infamous "big ball of mud" problem we're so familiar with in Object oriented programming.
In OO, we've found a solution to this entanglement by using interfaces, they separate implementation from specification. OSGi is built around a similar albeit of an higher order concept of service contracts. These contracts (interfaces, permissions, helper classes) are stored in a package. In contract based programming you depend on the contracts, not the implementations. Ergo, an OSGi bundle should depend on packages since they represent the contracts.
Import-Package <=> interface
Import-Bundle/Require-Bundle <=> implementation class
Import-Bundle is NOT OSGi, it is a proprietary Spring extension. It is a cleaner form for Require-Bundle; the uncleanliness was necessary to support some Eclipse use cases. The OSGi decided not to adopt this header since the Require-Bundle/Import-Bundle is fundamentally broken if you want to build systems from components.
Ideally you should try to rather use Import-Package instead. It makes you bundles less dependent on each other. It also allows to show that you only depend on a part of a bundle. This is also important for managing versions. In OSGi you can define the versions of exported packages independent of the bundle version. So you can make sure you only change versions of an API if it really changes. This can make your app much more manageable.
It's explained here at SpringSource
So summarizing: Import-Bundle will import all exported packages of a certain bundle, it will resolve that when deploying, while Require-Bundle really requires a bundle with that type, and that relationship stays that way during runtime.
Normally they would behave pretty much the same. For example it can be different when:
You have 'split packages': packages that exist in multiple bundles, you might 'lose' dependencies with Import-Package / Import-Bundle that you can only express with Require-Bundle (Note that you really should avoid split packages if you can)
I think the Bundle->Package resolution is when you deploy that bundle. If you redeploy the bundle with the exported bundles to a version with different export, I don't think the bundle will notice. To be honest I'm not exactly sure about this one.
All in all, I'd say stick with the OSGi standard: Import-Package or Require-Bundle if you really need it. You'll have a bit more headers but you'll so many more options in the long run.
OSGi allows for dependencies to be determined via Import-Package, which just wires up a single package (exported from any bundle), and Require-Bundle, which wires up to a specific named bundle's exports.
In building a greenfield OSGi application, which approach should I use to represent dependencies? Most of the bundles will be internal, but there will be some dependencies on external (open-source) bundles.
I believe Require-Bundle is an Eclipse thing (that has now made it in the OSGi spec to accommodate Eclipse). The "pure" OSGi way is to use Import-Package, as it specifically decouples the package from the bundle that provides it. You should be declaring dependencies on functionality that you need (the Java API provided by a certain version of a certain package) instead of where that functionality is coming from (which should not matter to you). This keeps the composition of bundles more flexible.
JavaScript analogy: This is like detecting whether a web browser supports a certain API versus inferring from what the user-agent string says what kind of browser it is.
Peter Kriens of the OSGi Alliance has more to say about this on the OSGi blog.
Probably the only case where you need to use Require-Bundle is if you have split packages, that is a package that is spread across multiple bundles. Split packages are of course highly discouraged.
Favour Import-Package over Require-Bundle.
Require-Bundle:
specifies the explicit bundle (and version) to use. If a requirde bundle needs to be refactored and a package moved elsewhere, then dependents will need changes to their MANIFEST.MF
gives you accesss to ALL exports of the bundle, regardless of what they are, and regardless of whether you need them. If the parts you don't need have their own dependencies you will need those to
bundles can be re-exported
although discouraged, allows the use of split packages, ie: a package that is spread across multiple bundles
can be used for non-code dependencies, eg: resources, Help etc.
Import-Package:
looser coupling, only the package (and version) is specified and the run-time finds the required bundle
Actual implementations can be swaped out
Dependent packages can be moved to different bundles by the package owner
But requires more metadata to be maintained (i.e: each package name) at lower levels of granularity
I believe Import-Package gives you looser coupling and should be preferred. I use it when declaring dependencies on packages that I don't own, such as slf4j, and I can swap implementations as I wish. I use Require-Bundle when the dependency is something I have control over, such as my own bundles, because any important change would have gone through myself anyway.
Avoid Import-Package.
As packages provide many-to-many relationships between bundles, they are prone to dependency cycles that are hard to detect and avoid.
Require-Bundle on the other hand, references a single bundle, making dependency graph protected from cycles by a trivial build-time check.
With Require-Bundle it is much easier to build layered architecture with isolated lower level of abstraction.
Import-Package should be better because, as previously said, you can move a package from one bundle to another without changing existing client's MANIFEST.MF
But...
There is a practical reason to use Require-Bundle if you are using Eclipse to develop your bundles:
Eclipse don't use packages as units of resolution. It uses bundles. That is, if you use one package of a bundle, Eclipse compiles your bundle without reporting any problem with the use of the rest of packages not imported from that bundle.
You could (you are human) think that everything is OK and upload your bundle for deployment but ... your bundle will break at runtime.
I'm sure about it because this problem has happened (to me!) today.
The good solution would be to change the Eclipse classpath container but... if this is not going to be done... you could decide to avoid this kind of problems requiring bundles, instead of packages, paying the mentioned price (no backward compatible code movement between bundles).
I'm not convinced that using Import-Package is better, because my default expectation when working with a bundle is to work with the associated public API. For that reason, Require-Bundle makes more sense.