Java Tech & Tools | OSGi Best Practices | Emily Jiang


Published on

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

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • WSAD512_IntroToPortal.ppt Page of 32
  • .
  • On the provider side, the BillingServiceImpl is another POJO implementing a Java interface for which a service is registered by the Blueprint container when the Billing bundle is started. By default beans are created with “singleton” scope which means only a single instance is created by the container. If the bean maintains any state then it can be declared with “prototype” scope so that the container creates a new instance each time it needs to inject the dependency into a client.
  • Here is a simple example of an eCommerce bundle which contains a “shop” bean which uses a BillingService provided by another bundle. The Blueprint container locates the Billing Service provider and injects it into the shop bean at runtime. OSGi services are dynamic so if the service provider can be changed then the blueprint container is able to dynamically rewire the reference to a new service without impacting the shop bean instance.
  • What best practices used? BP4 - Separate API from implementations BP5 - Share services not implementations BP6 – Make bundles loosely coupled & highly cohesive BP7 - Use Blueprint If you show the source code, the following three best practices can be included: BP1 - Use Import-Package instead of Require-Bundle BP2 - Avoid split packages BP3 - Version bundles and packages
  • 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:
    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) </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:;bundle-version=2.0.0 </ul><ul>MANIFEST.MF ... Import-Package:;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.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 Enterprise OSGi YouTube Channel: </ul>
    76. 76. <ul>Copyright and Trademarks </ul><ul>© IBM Corporation 2011. All Rights Reserved. IBM, the IBM logo, and 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 </ul>