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.

Java Tech & Tools | OSGi Best Practices | Emily Jiang

2,079 views

Published on

Published in: Technology, Education
  • Be the first to comment

Java Tech & Tools | OSGi Best Practices | Emily Jiang

  1. 1. OSGi Best Practices Emily Jiang, IBM OSGi Developer, Apache Aries Committer [email_address]
  2. 2. <ul></ul><ul>AGENDA </ul><ul><ul><li>Why OSGi? </li></ul></ul><ul><ul><li>What is OSGi? </li></ul></ul><ul><ul><li>How to best use OSGi? </li></ul></ul>
  3. 3. <ul><ul><li>Jars have no modularization characteristics </li></ul></ul><ul><ul><ul><li>No “jar scoped” access modifiers.
  4. 4. No means for a jar to declare its dependencies.
  5. 5. No versioning. </li></ul></ul></ul><ul>Modularization in Java </ul><ul></ul><ul>Jar </ul><ul>Package </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Package </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Package </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul>
  6. 6. <ul>Problems with Global Java ClassPath </ul><ul>Java VM </ul><ul>log4j </ul><ul>barcode4j </ul><ul>axis </ul><ul>batik </ul><ul>commons </ul><ul>derby </ul><ul>fop </ul><ul>ezmorph </ul><ul>freemarker </ul><ul>httpunit </ul><ul>jakarta </ul><ul>jcl </ul><ul>json </ul><ul>jdbm </ul><ul>jdom </ul><ul>jenks </ul><ul>jpos18 </ul><ul>jython </ul><ul>looks </ul><ul>lucene </ul><ul>mail </ul><ul>mx4j </ul><ul>naming </ul><ul>jetty </ul><ul>poi </ul><ul>resolver </ul><ul>rome </ul><ul>serializer </ul><ul>servlets </ul><ul>tomcat </ul><ul>velocity </ul><ul>ws-commons </ul><ul>xalan </ul><ul>wsdl4j </ul><ul>xerces </ul><ul>xmlgraphics </ul><ul>xmlrpc </ul><ul>xmlapis </ul><ul>.. </ul><ul>geronimo </ul><ul>bsh </ul><ul>bsf </ul><ul>guiapp </ul><ul>hhfacility </ul><ul>manufact. </ul><ul>marketing </ul><ul>minerva </ul><ul>accounting </ul><ul>assetmaint </ul><ul>base </ul><ul>bi </ul><ul>catalina </ul><ul>common </ul><ul>oagis </ul><ul>order </ul><ul>ebay </ul><ul>content </ul><ul>datafile </ul><ul>ecommerce </ul><ul>entity </ul><ul>googlebase </ul><ul>ofbiz </ul><ul>widget </ul><ul>minilang </ul><ul>party </ul><ul>pos. </ul><ul>product </ul><ul>workeffort </ul><ul>workflow </ul><ul>… </ul><ul>sunjce_prov. </ul><ul>plugin </ul><ul>jsse </ul><ul>jce </ul><ul>rt </ul><ul>dnsns </ul><ul>.. </ul><ul>… </ul><ul>Class Not Found Exception </ul><ul>Begin Here </ul>
  7. 7. <ul>Problems with EARs/WARs </ul><ul>Enterprise Applications have isolated classpaths but… </ul><ul><ul><li>No Sharing </li></ul></ul><ul><ul><ul><li>Common libraries/frameworks in apps and memory </li></ul></ul></ul><ul><ul><li>Version conflicts </li></ul></ul><ul>webA.war WEB-INF/classes/servletA.class </ul><ul>WEB-INF/lib/spring.jar WEB-INF/lib/commons-logging.jar WEB-INF/lib/junit.jar … </ul><ul>webB.war WEB-INF/classes/servletB.class </ul><ul>WEB-INF/lib/spring.jar WEB-INF/lib/commons-logging.jar WEB-INF/lib/junit.jar … </ul><ul>webC.war WEB-INF/classes/servletC.class </ul><ul>WEB-INF/lib/spring.jar WEB-INF/lib/commons-logging.jar WEB-INF/lib/junit.jar … </ul><ul>plankton.v1 </ul><ul>plankton.v2 </ul>
  8. 8. <ul></ul><ul>AGENDA </ul><ul><ul><li>Why OSGi? </li></ul></ul><ul><ul><li>What is OSGi? </li></ul></ul><ul><ul><li>How to best use OSGi? </li></ul></ul>
  9. 9. <ul>What is OSGi? </ul><ul>“ The dynamic module system for Java” </ul><ul><ul><li>Mature 10-year old technology
  10. 10. Governed by OSGi Alliance: http://www.osgi.org
  11. 11. Used inside just about all Java-based middleware </li></ul></ul><ul><ul><ul><li>IBM WebSphere, Oracle WebLogic, Red Hat JBoss, Sun GlassFish, Paremus Service Fabric, Eclipse Platform, Apache Geronimo, (non-exhaustive list) http://www.osgi.org/wiki/uploads/News/2008_09_16_worldwide_market.pdf </li></ul></ul></ul><ul>Jar </ul><ul>Jar </ul><ul></ul><ul>Explicit exports </ul><ul>Explicit dependencies </ul><ul><li>Package </li></ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul><li>Package </li></ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul><ul>Class </ul>
  12. 12. <ul>OSGi Bundles and Class Loading </ul><ul>OSGi Bundle – A jar containing: </ul><ul><ul><li>Classes and resources.
  13. 13. OSGi Bundle manifest. </li></ul></ul><ul>What’s in the manifest: </ul><ul><ul><li>Bundle-Version: Multiple versions of bundles can live concurrently.
  14. 14. Import-Package: What packages from other bundles does this bundle depend upon?
  15. 15. Export-Package: What packages from this bundle are visible and reusable outside of the bundle? </li></ul></ul><ul>Class Loading </ul><ul><ul><li>Each bundle has its own loader.
  16. 16. No flat or monolithic classpath.
  17. 17. Class sharing and visibility decided by declarative dependencies, not by class loader hierarchies.
  18. 18. OSGi framework works out the dependencies including versions. </li></ul></ul><ul>Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: MyService bundle Bundle-SymbolicName: com.sample.myservice Bundle-Version : 1.0.0 Bundle-Activator : com.sample.myservice.Activator Import-Package: com.something.i.need;version=&quot;1.1.2&quot; Export-Package: com.myservice.api;version=&quot;1.0.0&quot; </ul><ul>Bundle </ul>
  19. 19. <ul>OSGi Bundle </ul>Bundles have a dynamic lifecycle <ul><li>Can come and go independently </li></ul><ul>Bundle </ul>
  20. 20. <ul>OSGi Service Registry </ul><ul><li>Service </li></ul><ul><ul><li>An object associated with a list of classes (usually interfaces) it provides
  21. 21. Dynamic (can come and go), framed by bundle lifecycle
  22. 22. Services are the primary means of collaboration between bundles. </li></ul></ul><ul>S </ul>
  23. 23. <ul></ul><ul>AGENDA </ul><ul><ul><li>Why OSGi? </li></ul></ul><ul><ul><li>What is OSGi? </li></ul></ul><ul><ul><li>How to best use OSGi? </li></ul></ul>
  24. 24. <ul>BP1 - Use Import-Package not Require-Bundle </ul><ul><li>Require-Bundle </li></ul><ul><ul><li>Tightly coupled with a particular bundle with the specified symbolic name and version
  25. 25. High coupling between bundles
  26. 26. Import all packages
  27. 27. Bundle version management </li></ul></ul><ul><li>Import-Package </li></ul><ul><ul><li>Can wire to any bundles exporting the specified package
  28. 28. Loose coupling between bundles
  29. 29. Only import the package you need
  30. 30. Package version management </li></ul></ul><ul>MANIFEST.MF ... Require-Bundle: com.ibm.ws.service;bundle-version=2.0.0 </ul><ul>MANIFEST.MF ... Import-Package: com.ibm.ws.service.api;version=2.0.0 </ul>
  31. 31. <ul>BP2 - Avoid split packages </ul><ul><li>Split package </li></ul><ul><ul><li>A package is exported by two bundles at the same version and the set of classes provided by each bundle differs. </li></ul></ul><ul><li>Why? </li></ul><ul><ul><li>Leads to the use of Require-Bundle, compromising the extent to which systems using the bundles can be extended and maintained. </li></ul></ul><ul><li>How? </li></ul><ul><ul><li>Keep all of the classes from any one package in a single bundle </li></ul></ul>
  32. 32. <ul>BP2 - Split Package examples </ul><ul>API B </ul><ul>Implementation C </ul><ul>org.hal.a 1.0.0 </ul><ul>Bundle C has to use 'Require-Bundle' to ensure that it has classes from both parts of the API </ul><ul>Figure 1. Consumers of split packages need to use the Require-Bundle header </ul><ul>API A </ul><ul>org.hal .api 1.0.0 </ul><ul>org.hal.a pi 1.0.0 </ul>
  33. 33. <ul>BP2 - Split Package examples </ul><ul>API A </ul><ul>Implementation C </ul><ul>org.hal.a 1.0.0 </ul><ul>Figure 2. A complete package exported from a single bundle maintains high bundle cohesion </ul><ul>org.hal.api 1.0.0 </ul>
  34. 34. <ul>BP3 - Version bundles and packages </ul><ul><li>What is semantic versioning? </li></ul><ul><ul><li>Uses a major.minor.micro.qualifier numbering scheme </li></ul></ul><ul><ul><ul><li>Major - Packages with versions that have different major parts are not compatible both for providers as well as consumers.
  35. 35. Minor – API enhancement, e.g. adding methods to an API
  36. 36. Micro – bug fixing
  37. 37. Qualifier – identifier such as timestamp
  38. 38. Example: 1.1.2.20101122am, 1.0.0, 2.0 </li></ul></ul></ul><ul><ul><li>Changes in major: a binary incompatible, minor: enhanced API, micro: no API changes </li></ul></ul><ul><li>Why? </li></ul><ul><ul><li>Clients can protect themselves against API changes that might break them. </li></ul></ul>
  39. 39. <ul>BP3 - Version bundles and packages examples </ul><ul>Figure 3: A client and an implementation can use either of two equivalently versioned packages </ul><ul>Figure 4: How a client and implementation are affected differently by a minor API version change </ul><ul>Implementation A </ul><ul>Imports: org.hal.a [1.0, 1.1) </ul><ul>API A </ul><ul>org.hal.a 1.0.0 </ul><ul>API B </ul><ul>org.hal.a 1.0.0 </ul><ul>Client A </ul><ul>Imports: org.hal.a [1.0, 2.0) </ul><ul>API B </ul><ul>org.hal.a 1.1.0 </ul><ul>API A </ul><ul>org.hal.a 1.0.0 </ul><ul>Client A </ul><ul>Imports: org.hal.a [1.0, 2.0) </ul><ul>Client B </ul><ul>Imports: org.hal.a [1.1, 2.0) </ul><ul>Implementation B </ul><ul>Imports: org.hal.a [1.1, 1.2) </ul><ul>Implementation A </ul><ul>Imports: org.hal.a [1.0, 1.1) </ul>
  40. 40. <ul>BP3 - Version bundles and packages examples </ul><ul>Figure 5. How clients and implementations are similarly affected by a major API version change </ul><ul>API A </ul><ul>org.hal.a 1.0.0 </ul><ul>org.hal.a 2.0.0 </ul><ul>API B </ul><ul>Client A </ul><ul>Imports: org.hal.a [1.0, 2.0) </ul><ul>Client B </ul><ul>Imports: org.hal.a [2.0, 3.0) </ul><ul>Implementation B </ul><ul>Imports: org.hal.a [2.0, 2.1) </ul><ul>Implementation A </ul><ul>Imports: org.hal.a [1.0, 1.1) </ul>
  41. 41. <ul>BP4 - Separate API from Implementations </ul><ul><li>Why? </li></ul><ul><ul><li>Great flexibility
  42. 42. Many implementation bundles -> enable more services provided
  43. 43. Reduce package dependencies -> reduce circular dependencies </li></ul></ul><ul><li>How? </li></ul><ul><ul><li>Put API classes in one bundle
  44. 44. Put implementation classes in a separate bundle </li></ul></ul>
  45. 45. <ul>BP4 - Separate API and implementation examples </ul><ul>Figure 6. Badly designed provider bundle where the API and implementation classes are in the same bundle </ul><ul>API + Implementation </ul><ul>org.hal.myapi </ul><ul>org.hal.a.impl </ul><ul>Both API and implementation packages imported by client </ul><ul>Client </ul><ul>org.hal.b.client </ul>
  46. 46. <ul>BP5 - Share services not implementations </ul><ul><li>Use the OSGi service registry to construct instances
  47. 47. Why? </li></ul><ul><ul><li>Able to obtain an instance of an implementation without knowing which one
  48. 48. Achieve a loosely coupling of client, API and implementation </li></ul></ul><ul><li>How? </li></ul><ul><ul><li>Register an instance of the API interface in the OSGi service registry
  49. 49. Register an implementation of the OSGi ServiceFactory interface in the OSGi service registry. </li></ul></ul>
  50. 50. <ul>BP4 & 5 - examples </ul><ul>org.hal.myapi </ul><ul>API and implementation packages in different bundles but still imported by client </ul><ul>Implementation </ul><ul>org.hal.a.impl </ul><ul>Figure 7. Badly designed provider bundles where the API and implementation classes have been separated </ul><ul>API </ul><ul>Client </ul><ul>org.hal.b.client </ul>
  51. 51. <ul>BP4 & 5 - examples </ul><ul>Figure 8: Well designed provider bundles where the API and implementation classes have been separated </ul><ul>API </ul><ul>org.hal.myapi </ul><ul>Client </ul><ul>org.hal.b.client </ul><ul>Client and implementation in separate bundles, both import API. Client uses implementation through a service defined by the API. </ul><ul>Implementation </ul><ul>org.hal.a.impl </ul>
  52. 52. <ul>Using services can be hard! </ul><ul>@Override </ul><ul>public void serviceChanged(ServiceEvent event) </ul><ul>{ ServiceReference ref = event.getServiceReference(); </ul><ul>if ( ls .get() == null && event.getType() == ServiceEvent. REGISTERED ) { </ul><ul>ls .set((LogService) ctx .getService(ref)); </ul><ul>} else if ( ls .get() != null && event.getType() == ServiceEvent. UNREGISTERING && ref == lr .get()) { ref = ctx .getServiceReference(LogService. class .getName()); </ul><ul>if (ref != null ) { </ul><ul>ls .set((LogService) ctx .getService(ref)); lr .set(ref); </ul><ul>} } } </ul><ul>private BundleContext ctx ; </ul><ul>private AtomicReference<LogService> ls = new AtomicReference<LogService>(); private AtomicReference<ServiceReference> lr = new AtomicReference<ServiceReference>(); </ul><ul>public void start(BundleContext ctx) throws InvalidSyntaxException </ul><ul>{ </ul><ul>this . ctx = ctx; </ul><ul>ctx.addServiceListener( this , &quot;(objectClass=org.osgi.service.log.LogService)&quot; ); ServiceReference ref = ctx.getServiceReference(LogService. class .getName()); </ul><ul>if (ref != null ) { </ul><ul>ls .set((LogService) ctx.getService(ref)); lr .set(ref); </ul><ul>} } </ul>
  53. 53. <ul>BP6 - Use Blueprint </ul><ul><li>Specifies a Dependency Injection container, standardizing established Spring conventions
  54. 54. Configuration and dependencies declared in XML “module blueprint”, which is a standardization of Spring “application context” XML. </li></ul><ul><ul><li>Extended for OSGi: publishes and consumes components as OSGi services </li></ul></ul><ul><li>Simplifies unit test outside either Java EE or OSGi r/t.
  55. 55. The Blueprint DI container can be a part of the server runtime (compared to the Spring container which is part of the application.) </li></ul><ul>dependencies injected </ul><ul>publishes service </ul><ul>consumes service </ul><ul>A static assembly and configuration of components (POJOs) ‏ </ul><ul>Blueprint bundle </ul><ul>OSGI-INF/blueprint/ blueprint.xml </ul>
  56. 56. <ul>BP6 - Blueprint service-bundle examples </ul><ul>public interface BillingService { void bill(Order o); </ul><ul>} </ul><ul>Billing </ul><ul>< blueprint > </ul><ul>< service ref = ”service” interface = ”org.example.bill.BillingService” /> < bean id = ”service” scope = ”prototype” class = ”org.example.bill.impl.BillingServiceImpl” /> </ul><ul></ blueprint > </ul><ul>Billing service bundle </ul><ul><li>“ prototype” scope indicates a new instance is created by the container for each use.
  57. 57. “ singleton” scope is the default. </li></ul>
  58. 58. <ul>BP6- Blueprint client-bundle examples </ul><ul>public class ShopImpl { </ul><ul>private BillingService billingService ; void setBillingService(BillingService srv) { </ul><ul>billingService = srv; </ul><ul>} </ul><ul>void process(Order o) { </ul><ul>billingService .bill(o); </ul><ul>} } </ul><ul>e-Commerce </ul><ul>< blueprint > </ul><ul>< bean id = ”shop” class = ”org.example.ecomm.ShopImpl” > < property name = ”billingService” ref = ”billingService” /> </ bean > < reference id = ”billingService” interface = ”org.example.bill.BillingService” /> </ul><ul></ blueprint > </ul><ul>e-Commerce bundle </ul><ul><li>injected service reference
  59. 59. service can change over time
  60. 60. can be temporarily absent without the bundle caring
  61. 61. managed by Blueprint container </li></ul>
  62. 62. <ul>BP7 – Make Bundles Loosely Coupled & Highly Cohesive </ul><ul>'Hairball' effect – one bundle has many package dependencies </ul><ul>org.hal.log.impl </ul><ul>Implementation </ul><ul>org.hal.log.impl </ul><ul>SomeotherAPI </ul><ul>DBAPI </ul><ul>TransactionsAPI </ul><ul>FileSystemAPI </ul><ul>JPAAPI </ul><ul>org.hal.fslog.impl </ul><ul>Figure 9. Poorly purposed system where a single bundle provides multiple implementations of the same API </ul><ul>API </ul><ul>org.hal.log.api </ul>
  63. 63. <ul>BP7 – Make Bundles Loosely Coupled & Highly Cohesive </ul><ul>Implementation </ul><ul>org.hal.DBlog.impl </ul><ul>DBAPI </ul><ul>API </ul><ul>org.hal.log.api </ul><ul>Implementation </ul><ul>org.hal.fslog.impl </ul><ul>FileSystemAPI </ul><ul>Implementation </ul><ul>org.hal.DBlog.impl </ul><ul>DBAPI </ul><ul>Implementation </ul><ul>org.hal.DBlog.impl </ul><ul>DBAPI </ul><ul>Figure 10. A well purposed system where each implementation of an API is provided by a separate bundle </ul>
  64. 64. <ul>BP8 – Use bundle repositories </ul>
  65. 65. <ul>Summary – OSGi Best Practices </ul><ul><ul><li>BP1 - Use Import-Package instead of Require-Bundle
  66. 66. BP2 - Avoid split packages
  67. 67. BP3 - Version bundles and packages
  68. 68. BP4 - Separate API from implementations
  69. 69. BP5 - Share services not implementations
  70. 70. BP6 - Use Blueprint
  71. 71. BP7 - Make bundles loosely coupled & highly cohesive
  72. 72. BP8 - Use Bundle Repositories </li></ul></ul>
  73. 73. <ul>Quiz – What best practices are used? </ul><ul>Blogging Service </ul><ul>Blog Persistence Service </ul><ul>blog-servlet </ul><ul>Web application bundle </ul><ul>META-INF/ persistence.xml </ul><ul>WEB-INF/ web.xml </ul><ul>OSGI-INF/blueprint/ blueprint.xml </ul><ul>OSGI-INF/blueprint/ blueprint.xml </ul><ul>JNDI </ul><ul>EM </ul><ul>blog </ul><ul>blog-persistence </ul><ul>blog-api </ul>
  74. 74. <ul>Questions? </ul>
  75. 75. <ul>Additional References </ul><ul>OSGi Best Practices www.ibm.com/developerworks/websphere/techjournal/1007_charters/1007_charters.html Enterprise OSGi YouTube Channel: www.youtube.com/user/EnterpriseOSGi </ul>
  76. 76. <ul>Copyright and Trademarks </ul><ul>© IBM Corporation 2011. All Rights Reserved. IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corp., registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other companies. A current list of IBM trademarks is available on the Web at “Copyright and trademark information” at www.ibm.com/legal/copytrade.shtml. </ul>

×