OSGi DevCon 2013
OSGi applications are assembled from loosely coupled bundles communicating via services. While this model provides huge flexibility and the ability to reuse components, it creates a challenge for the assembler of the application since it is unclear which bundles are needed, which are optional and which are unnecessary.
For example some dependencies are implicit, such as the provider of a service or an extender. We do not want to prematurely lock down these dependencies at build time, but at deployment time a specific provider must be found otherwise the application will fail to behave as expected. Furthermore when third-party libraries are used they often contain static dependencies on additional libraries, which in turn contain additional dependencies, and so on. Much time is wasted in finding a set of bundles that will actually resolve and run in the OSGi environment, and once such a set is found, developers tend to fear making changes to it.
The generic requirements and capabilities model introduced in OSGi Release 4.3, along with the standard Repository and Resolver specifications introduced in OSGi Release 5, provide answers for both of these problems. Using capabilities, we can describe dependencies in an abstract way without prematurely binding to specific providers. Using the resolver, we can narrow our focus to the very small set of bundles that describe our application at the top level, and allow all other dependencies to be computed and managed for us.
This talk begins with a brief technical overview of the new 4.3 and 5.0 specifications and how they can be used to assemble applications with ease. We then demonstrate both development tooling and a runtime platform that can be used to put these ideas into practice.
5. NO YOU CAN’T
• Example: missing import: org.wtf.
• Google for org.wtf, find that it’s part of bundle
com.acme.fml
• Download and install com.acme.fml, now you have
more missing imports: org.thingummy,
javax.whatever (version 3.0.2.SNAPSHOT).
• Go round again... and again... and again...
Friday, 29 March 13
6. THIS IS NOT A JOB
FOR HUMAN BEANS
Friday, 29 March 13
9. Nothing’s Happening
• Oh you’re using Declarative Services! Did you
remember to include org.apache.felix.scr?
• Oh you’re using Blueprint. Did you remember to
include org.apache.aries.blueprint?
• Oh you’re using JPA. Did you remember to include
org.eclipse.gemini.jpa?
Friday, 29 March 13
10. Extender/Whiteboard
• NO direct/static dependency
• Dependency is implicit: without the extender, nothing
happens.
• NO diagnostic error messages
Friday, 29 March 13
11. Not Really Solutions
• Deployment Admin Packages
• Eclipse Features
• Virgo Plans/PARs
• Karaf KARs/Features
• etc...
Friday, 29 March 13
15. Simple API!
public interface Repository {
Map<Requirement, Collection<Capability>> findProviders(
Collection<? extends Requirement> requirements);
}
Friday, 29 March 13
16. Repository
• Can return Resources from anywhere
• Should have knowledge of capabilities and
requirements of the resources it manages
• Database? XML file? Just an implementation detail.
Friday, 29 March 13
18. Generating an Index
• RepoIndex: https://github.com/osgi/bindex
• Standalone library, also command line,ANT, OSGi
service, etc.
Friday, 29 March 13
19. Repository Implementations
• RI from Red Hat: github.com/jbosgi/jbosgi-repository
• bnd “Fixed Indexed Repo”
• Just needs a URI to an index
• bnd “Local Indexed Repo”
• Mutable, based on local file-system folder
• Automatically reindexes on deploy
Friday, 29 March 13
21. Simple API!
public interface Resolver {
Map<Resource, List<Wire>> resolve(ResolveContext context)
throws ResolutionException;
}
Friday, 29 March 13
22. Resolver Result
• Returns a Delta: new Resources, new Wires
• Can be used by OSGi Framework
• Use outside OSGi to discover resources
Friday, 29 March 13
23. DO NOT IMPLEMENT
• Implementing a Resolver is HARD
• Resolver is very generic.You almost certainly don’t
NEED to implement your own
Friday, 29 March 13
24. Resolver Implementation
• Just One: The RI from Apache Felix
• Used in Felix Framework
• Soon to be used in Equinox Framework
• Used by Subsystems Specification
• Used by Bnd(tools)
• Soon to be used in Paremus Nimble
Friday, 29 March 13
25. So the Resolver talks to the
Repository, right?
Friday, 29 March 13
32. Not So Simple API!
public abstract class ResolveContext {
public Collection<Resource> getMandatoryResources() {
return emptyCollection();
}
public Collection<Resource> getOptionalResources() {
return emptyCollection();
}
public abstract Map<Resource, Wiring> getWirings();
public abstract List<Capability> findProviders(Requirement requirement);
public abstract boolean isEffective(Requirement requirement);
public abstract int insertHostedCapability(List<Capability> capabilities,
HostedCapability hostedCapability);
}
Friday, 29 March 13
33. getMandatoryResources()
• This is our starting point
• List of resources that must be present in the result
• Bndtools creates a single dummy Resource containing
the input Requirements
Friday, 29 March 13
34. getOptionalResources()
• List of resources we hope will be present in the result
• Failure to resolve one of these doesn’t break the whole
resolution
Friday, 29 March 13
35. getWirings()
• Map of existing resolved resources and their wires
• Inside OSGi, this is the already resolved bundles
• In Bndtools this is empty
Friday, 29 March 13
36. findProviders()
• Here’s the meat!
• The Resolver wants to resolve a requirement...
• ... asks us to find the candidate Capabilities to satisfy it
• We return a ranked collection of Capabilities
• Typically we talk to our Repositories
• Resolver tries to use the highest ranked candidate, but
no promises.
Friday, 29 March 13
37. GOTCHA
• Don’t go to Repositories for JRE packages etc.
• Always check system bundle capabilities first.
• Some Resources have “self-requirements”, e.g.
importing package exported by same bundle.
• Always check first if the resource’s own capabilities
satisfy the requirement
Friday, 29 March 13
39. insertHostedCapability()
• Oh Mummy...
• Insert fragment capabilities into the list returned by
findProviders(), at the correct position
• More proof that fragments are horrible.
Friday, 29 March 13
40. Implementations
• Felix and Equinox Frameworks
• BndrunResolveContext in bnd project takes a .bndrun
file as input
Friday, 29 March 13
43. Effective
• Some requirements are “effective” at different times
• E.g.: Require-Capability: osgi.service;filter:=...
• Should Not block resolution by the OSGi
Framework
•Should guide OBR/Nimble/Bndtools to add a provider
to the result
Friday, 29 March 13
45. Effective
• Requirements are only effective in OSGi Framework
resolution if effective == “resolve”
• ... but “resolve” is the default, so omitting the
“effective:” directive also works.
• Other Resolve Contexts (e.g. Bndtools) can decide by
implementing isEffective(Requirement).
Friday, 29 March 13
46. effective:=active
• No value for “effective:” is defined by OSGi other than
“resolve”
• “active” is a convention for requirements that apply to
active bundles.
• E.g.: extenders, whiteboard, services, etc
Friday, 29 March 13
48. Choice
• Your app requires a Web container, e.g.
osgi.extender;filter:=“(osgi.extender
=osgi.wab)”
• Tomcat and Jetty are both available.
• It only makes sense to have one! How do we decide?
Friday, 29 March 13
49. Choice
• It’s all down to ResolveContext.findProviders()
• Ranked preference, Resolver tries to pick highest.
• Or we return just one.
Friday, 29 March 13
50. Current State-of-the-Art
• “Repository Path”
• Resources from earlier repos are preferred over later
repos.
• Forces us to have many, granular repos.
• Probably won’t scale.
Friday, 29 March 13
51. Future?
• Interactive Resolve.
• Ask the user, but cache the answer (...for how long?)
• Policies
• “Prefer Jetty over Tomcat”
• Repository Filters
Friday, 29 March 13
53. What is an Application??
• A small number of bundles defining the high-level
functionality.
• All of the dependencies of the above.
• Curate your top-level bundles.
•Generate your dependency lists.
Friday, 29 March 13
54. Caution
• When should we resolve?
• The result can change if repo contents change!
• Resolve => Test => Resolve => Deploy to Prod... bang!
• WYTIWYR
• Persist your resolution result.
Friday, 29 March 13