Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Adaptto 2019 OSGi best practices


Published on

Many people have the feeling or experience that OSGi is hard to use as a developer.
Most of this comes down to either the modular classpath or the dynamic nature of OSGi.
This talk shows best practices for coping with those special properties of OSGi in a
elegant and simple way.

Some highlights:

- OSGi class loading is easier than you think
- Creating bundles with zero configuration
- How to avoid the need for start levels and still get proper ordering on startup
- Loose coupling and easy application assembly

Examples at:

Published in: Technology
  • by filling out a short survey? =>>
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Adaptto 2019 OSGi best practices

  1. 1. APACHE SLING & FRIENDS TECH MEETUP 2 - 4 SEPTEMBER 2019 OSGi best practices Christian Schneider Adobe
  2. 2. Christian Schneider 2 § Computer scientist at Adobe § Apache member and committer § Twitter @schneider_chris § Website
  3. 3. Agenda 3 • Create bundles the lean way • How to avoid Start Levels • Best practices around DS • Loose coupling and easy application assembly
  4. 4. 4 Creating bundles
  5. 5. How you used to create bundles 5 § Maven bundle plugin § Detailed setup in each pom.xml § Explicit export package with version Error prone Breaks with refactoring
  6. 6. How you used to create bundles 6 <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> … </instructions> </configuration> </plugin>
  7. 7. How you used to create bundles 7 <Export-Package> </Export-Package> <Import-Package>*;resolution:=optional, * </Import-Package> <Private-Package> org.apache.karaf.diagnostic.command, org.apache.karaf.diagnostic.common, … </Private-Package> <Bundle-Activator> org.apache.karaf.diagnostic.internal.Activator </Bundle-Activator> Source: Apache Karaf diagnostic plugin
  8. 8. Create bundles the lean way 8 § Use bnd-maven-plugin only in parent § In each bundle define exports, requirements and capabilities using OSGi R7 annotations § Imports are handled automatically § Use bnd.bnd file only in case you need manual override
  9. 9. Exporting a package 9 @org.osgi.annotation.versioning.Version(”1.2.0") @org.osgi.annotation.bundle.Export package my.package;
  10. 10. Use Semantic versioning 10 When do you need to increase a package version? Hard to do manually § Configure semantic versioning plugin § Current API is compared to last release § Build failure when a package export version increase is needed
  11. 11. 11 Start order and services
  12. 12. Why is start order frowned upon in OSGi? 12 § Allowing any order give the system room for optimization § Bundles can be uninstalled and installed at any time § Deadlocks on forced order React on services instead of enforcing start order
  13. 13. Why people use start oder 13 § Code requires certain state of system § How to make sure this state is reached? Start order looks like a good solution (at first)
  14. 14. How to not use services 14 ref = context.getServiceReference(HealthCheck.class); service = context.getService(ref); Why is this bad? § Have to check for null § Service may be not (yet) registered § If you repeat and wait you block threads § You need to unget the service after use
  15. 15. Is ServiceTracker better ? 15 tracker = new ServiceTracker<HealthCheck, HealthCheck>(context, HealthCheck.class, null); tracker.getService(); Not better than context.getService() ! We need something reactive !
  16. 16. 16 Component best practices
  17. 17. Always use a DI framework in OSGi 17 @Component Class MyClient { @Reference MyService myService; } Let Declarative Services solve this for you.
  18. 18. Internal components and wiring 18 § DS can only bind to services. § How do I keep a service internal to a component? Use a service class or interface from a private package
  19. 19. Never block in @Activate 19 @Activate public void activate(BundleContext context) { executor.execute(() -> { // Do some long running stuff context.registerService(Servlet.class, this, new Hashtable<>()); }); } Make blocking calls async and export service by hand.
  20. 20. 20 Be careful with adaptTo()
  21. 21. What is adaptTo() 21 § By coincidence a name of some conference J § Popular pattern in sling Session session = resolver.adaptTo(Session.class); Great pattern for simple cases but can have issues
  22. 22. Be careful with adaptTo() 22 § AdapterFactory services might not (yet) be present § Some adaptions get OSGi services via registry § Timing issues like to context.getService() Replace adaptTo() by service references if possible
  23. 23. Be careful with adaptTo() 23 PageManager pageManager = resolver.adaptTo(PageManager.class); null? What now?
  24. 24. Service reference instead of adaptTo() 24 @Reference private PageManagerFactory pageManagerFactory; … PageManager pageManager = pageManagerFactory.getPageManager(resolver); Always safe to use
  25. 25. 25 Loose coupling and easy application assembly
  26. 26. Loose coupling vs application assembly 26 Loose Coupling § Depend on interfaces not implementation § Whiteboard pattern achieves even better decoupling Assembly § Determine list of bundles to install § Should work with minimal definitions and resolver Application is loosely coupled but not enough information to find the bundles with service impls or whiteboards
  27. 27. HTTP Whiteboard 27 @Component( service = Servlet.class, property = "osgi.http.whiteboard.context.path=/ myservlet " ) public class MyServlet extends HttpServlet { … } § Achieves loose coupling § Assembly of application difficult
  28. 28. New Http Whiteboard 28 @Component(service = Servlet.class) @HttpWhiteboardServletPattern("/myservlet") public class MyServlet extends HttpServlet { … } New annotations: Easier configuration + requirements
  29. 29. Requirements & Capabilities drive assembly 29 Initial bundles / requirementsRepository List of bundles to run
  30. 30. Assembly in practice 30
  31. 31. 31 Questions?
  32. 32. Resources 32 § Follow me on Twitter @schneider_chris § Demo project § More links in the Demo project
  33. 33. 33 Backup
  34. 34. 34 Everything you need to know about OSGi class loading
  35. 35. OSGi class loading 35 Bundle A Bundle B Import pkgbpkga A pkgb B
  36. 36. OSGi class loading 36 What happens when you do new B() in OSGi? @Component Class A { @Activate void loaderTest() { ClassLoader clA = this.getClass().getClassLoader(); B b = new B(); ClassLoader clB = b.getClass().getClassLoader(); } } What is the ClassLoader of A and B and why?
  37. 37. OSGi class loading 37 § Manifest defines imported package and version ranges § Resolve wires each imported package to a bundle providing the package § On loading a class these locations are checked 1. Bound imports 2. Contents of the bundle 3. bootstrap ClassLoader
  38. 38. OSGi class loading 38 Classloading is delegated to other bundle So class B is loaded by ClassLoader of BundleB
  39. 39. OSGi class loading 39 A Class is always loaded by the ClassLoader of its own bundle