osgi in anger - tara simpson

52
OSGi In Anger A Case Study

Upload: mfrancis

Post on 27-May-2015

2.559 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: OSGi In Anger - Tara Simpson

OSGi In AngerA Case Study

Page 2: OSGi In Anger - Tara Simpson

Aepona?

• Instil customer for 3 years

• Provider of products into Telco space

• Focus on ‘Network as a Service’

• Think abstractions over operator capabilities

Page 3: OSGi In Anger - Tara Simpson

Telecom Web Services(In a Nutshell)

• SOAP/REST web services offering simplified APIs over SMS, MMS, Location, Conference Calling, etc

• Endpoints provisioned on a per-partner basis

• Endpoints backed by per-partner runtime policy enforcement

Page 4: OSGi In Anger - Tara Simpson

And Much More

• Billing

• Reporting

• Alarms

• Fault Reporting

• System deployed with null implementations of optional features

Page 5: OSGi In Anger - Tara Simpson

nodeA

OAM

SMS

Architecture

TLX

MMS

nodeB

OAM

MMS

TLX

SMS

container(i.e. JVM)

Portal(JBoss)

DEVKIT(Eclipse)

containergroup

Page 6: OSGi In Anger - Tara Simpson

Container Groups

MMS MMS

Load Balancer

Container Group

Page 7: OSGi In Anger - Tara Simpson

Runtime

• Equinox-based stack

• Initial bundles defined by config.ini

• Bundles can be remotely installed, uninstalled, activated, etc

• Managed by Eclipse RCP plug-in or command line (telnet & Command Provider)

Page 8: OSGi In Anger - Tara Simpson

A Potted History

• Project started in late 2006

• Began life as Artix-based stack

• Fairly large, ~10000 unit tests

• Evolved to OSGi 2007

Page 9: OSGi In Anger - Tara Simpson

The OAM

• Operations, Administration and Maintenance component spec’ed in 2007

• Used to create, delete, monitor & manage a multi-container (JVM) environment

• Two key requirements: (a) 99.999% uptime (b) ability to DYNAMICALLY install, uninstall and patch components

Page 10: OSGi In Anger - Tara Simpson

A Leap of Faith

• But for the wrong(ish) reasons

• OAM provided compelling reason for OSGi

• OSGi chosen mainly because it enabled hot-deploys

• Not because of enforced modularity or service-oriented design

Page 11: OSGi In Anger - Tara Simpson

Perceived Downside

• OSGi insists on everything being made ‘modular’

• But aren’t we already modular?

• Don’t we partition our software effectively?1000s of unit tests say we do!

Page 12: OSGi In Anger - Tara Simpson

Umm..NO!

• In retrospect, system far from modular

• Layers not partitioned cleanly

• Code not open for extension

• Free-for-all on code base

Page 13: OSGi In Anger - Tara Simpson

Life Before OSGi

• Single source tree

• Spring Configuration Hell

• Extensibility issues - PS work polluting core product

• Build issues

Page 14: OSGi In Anger - Tara Simpson

Evolving to OSGi

• How do we develop? Tools?

• How do we build? Ant, Maven?

• What to do with Artix, Spring & Hibernate?

• How to modularise existing code stream?

• How much time ($) is this going to take?

• No prior OSGi experience

Page 15: OSGi In Anger - Tara Simpson

Eclipse PDE

• OSGi is first class citizen

• Single project defines ‘target platform’

• Per-customer PSF (Team Project Set) files

• Export bundles directly to TWS

• We like PDE - but we don’t know any better!

Page 16: OSGi In Anger - Tara Simpson

Ant Build

• build.xml copies projects into launcher-prescribed directory structure and then kicks off launcher

• Heavy use of Eclipse features

• Considerable effort migrating projects over, but minimal effort in maintaining

• 400+ projects, features, fragments

Page 17: OSGi In Anger - Tara Simpson

Baby Steps

• No big bang

• Artix converted to single bundle

• Common code refactored into core bundle

• Services deployed as mega-bundles, built from single source tree

• Gradual migration to OSGi services

Page 18: OSGi In Anger - Tara Simpson

Hibernate

• Used bnd to create hibernate bundle

• Used DynamicImport-Package: * to find all exported mapping files & pojos

• Added Antlr & all hibernate jar files to internal classpath

• Works, but less than ideal

Page 19: OSGi In Anger - Tara Simpson

Spring DM

• Consistent programming model with existing Spring infrastructure/knowledge

• No issues with proxy-based approach

• Outside of core, only use Spring DM

• Inside core, mixture of Spring DM and direct OSGi, but only when necessary

Page 20: OSGi In Anger - Tara Simpson

Early Mistakes

• Failed to appreciate beauty of whiteboard pattern: publish/subscribe really should be replaced with export/track

• Modules not delineated using OSGi services - services enable dynamism & enforce better design

• Forgetting to unget services

Page 21: OSGi In Anger - Tara Simpson

Gradual Modularisation

• Services migrated one at a time

• Initially, layers broken into modules with public and private parts

• Eventually, modules refactored to be service oriented

• Code base significantly cleaner

Page 22: OSGi In Anger - Tara Simpson

Service(e.g. SMS)

ISmsActivityFactory

Life Before OSGi

ParlayX

ISmsDaoSmsMessage

SmsActivity

ICallback

Adapter

Gateway/Network

* ALL PUBLIC

Page 23: OSGi In Anger - Tara Simpson

Service(e.g. SMS)

Life With OSGi

ParlayX

SmsMessage

SmsActivity

ISmsSenderAdapter - public

Gateway

SmsSender

ISmsDaoISmsDaoISmsDaoAdapter - private

OSGi service POJO

Page 24: OSGi In Anger - Tara Simpson

Note to Self

• OSGi did not make me this way!

• But it encouraged me to step back...

• And be even more clinical in my separations

Page 25: OSGi In Anger - Tara Simpson

Reality Check

• Developers rarely have the good grace to hide implementation details!

• Developers who struggle with partitioning and layering will struggle even more with OSGi

• OSGi requires that you think more & be more disciplined

Page 26: OSGi In Anger - Tara Simpson

Today

• Extensive use of services & properties

• Heavy use of Spring DM

• Moderate use of the OSGi API

• Little use of compendium services

Page 27: OSGi In Anger - Tara Simpson

Design• Layered

• Service-Oriented

• Event-Driven

• Loosely-Coupled

• Dynamic/Modular!

Service(e.g. SMS)

core

WebService(e.g. SMS)

Adapter

OSGi services

OSGi services

Shared OSGi

services

Page 28: OSGi In Anger - Tara Simpson

Overall Philosophy

• Avoid the API at all costs

• Necessarily complex and wonderfully subtle - e.g. returning null from a tracker

• Well documented but good practice hard to come by

• Hard to unit test - especially trackers

• Instead use Spring DM wherever possible

Page 29: OSGi In Anger - Tara Simpson

Using the OSGi API

• Only 1 activator across 150 production bundles

• BundleContext injected via Spring DM BundleContextAware

• Primarily used to track & register services

• Also used to track bundles e.g. update property accessor when bundle installed, signal OAM when bundle fails to install

Page 30: OSGi In Anger - Tara Simpson

Idiomatic OSGi

• What is good practice? A catalog of idioms/patterns would be useful, very useful

/** * Property accessor tracker that creates describer's associated * policy description based on properties extracted from exported * policy accessor service. Once created the service is immediately * 'untracked'. */ private class PropertyAccessorTracker implements ServiceTrackerCustomizer {

public Object addingService(final ServiceReference serviceReference) { final IPropertyAccessor propertyAccessor = (IPropertyAccessor) bundleContext.getService(serviceReference); policyDescription = createPolicyDescription(propertyAccessor); bundleContext.ungetService(serviceReference); debug("Created policy description ", policyDescription); return null; }

public void modifiedService(final ServiceReference serviceReference, final Object service) { // Do nothing }

public void removedService(final ServiceReference serviceReference, final Object service) { // Do nothing - no need for unget } }

Page 31: OSGi In Anger - Tara Simpson

Fragments

• Used extensively to configure bundles in customer specific ways

• Used to house unit tests (10000+)

• One test fragment for every production bundle

• Fragments containing code cannot be unit tested. Therefore avoid.

Page 32: OSGi In Anger - Tara Simpson

Testing

• Focus mostly on behavioural & interaction-based unit testing

• Unit tests live in fragments

• Dedicated team for end-to-end testing

• Many parts of API mockable, except for trackers. Grumble.

Page 33: OSGi In Anger - Tara Simpson

Features

• Eclipse features describe pre-canned applications/features

• Parsed into config.ini files at build time

• Deployed under <install-dir>/conf/apps/<feature>/config.ini

• Each feature in conf/apps presented as a deployable application on front-end

Page 34: OSGi In Anger - Tara Simpson

OSGi Services

• Modules (mostly) communicate through services

• Services enable ALL extension points

• Lower layers define and export interfaces; consumed by higher layers

• Lower layers define and track interfaces; implemented & exported by higher layers

Page 35: OSGi In Anger - Tara Simpson

serviceweb service proxy

MethodInterceptorInvoker

IMethodInterceptorIMethodInterceptorIMethodInterceptor

Exported OSGi serviceWith service properties:order=1targetMethods=sendSms

Dynamic Method Interception

Page 36: OSGi In Anger - Tara Simpson

IMethodInterceptorimport org.aopalliance.intercept.MethodInterceptor;

/** * Method interceptor that enables any bundle to intercept * a service invocation. Implementations of this interface * are expected to be exported as an OSGi, along with 2 * properties: * <ul> * <li>an 'order' property used to determine the order in which * exported interceptors are invoked compared to each other</li> * <li>an optional set of comma separated 'targetMethods' method * names defining the method(s) that the interceptor should be * applied to</li> * </ul> * * Typically implementations will extend {@link AbstractMethodInterceptor} * rather than implement this interface directly. * * @see AbstractMethodInterceptor */public interface IMethodInterceptor extends MethodInterceptor {}

Page 37: OSGi In Anger - Tara Simpson

Canned Method Interceptors

• Address Normalisation: Enables white & black listing

• Group Address Resolution: Send to ‘group:abc’ => send to many

• Reporting: On every system transaction

Page 38: OSGi In Anger - Tara Simpson

serviceweb service proxy

PolicyEnforcer

EnforceablePolicyEnforceablePolicyEnforceablePolicy

Created using IPolicyDescriber (an OSGi service)

Policy Enforcement

Page 39: OSGi In Anger - Tara Simpson

Tracking Lists/** * Provider of policy descriptions ({@link PolicyDescription}s), derived * from their service policy description ({@link IPolicyDescriber}) * counterpart. */public class PolicyProvider implements IPolicyProvider {

private List<IPolicyDescriber> describers;

/** * Sets the list of policy describers being tracked. * The supplied list is expected to be a Spring-backed * list that automatically proxies and tracks the actual * policy describers. * @param describers a set of policy describers to be used */ @Required public void setPolicyDescribers(final List<IPolicyDescriber> describers) { this.describers = describers; } ...

<bean id="policyProvider" class="com.aepona.tws.core.policy.support.PolicyProvider"> <property name="policyDescribers" ref="policyDescribers" /> </bean> <osgi:list id="policyDescribers" interface="com.aepona.tws.core.policy.IPolicyDescriber" cardinality="0..N" />

Page 40: OSGi In Anger - Tara Simpson

Mobile Originated Events

• How to publish asynchronous SMS notifications and delivery receipts to third party applications?

• More generally - how do we publish events from lower layers to higher layers?

Page 41: OSGi In Anger - Tara Simpson

NetworkThird PartyApplication

Service

Mobile Originated Events

?

Page 42: OSGi In Anger - Tara Simpson

Back to the Whiteboard

• Lower layer defines and tracks ‘publisher’ interface

• Higher layer implements and exports publisher

Page 43: OSGi In Anger - Tara Simpson

Whiteboard

SmsNotificationPublisher

ISmsNotificationPublisherSmsNotificationHandler

<<implements>>

to TPA

from network

Exported as OSGi service

Tracks ISmsNotificationPublisher

Page 44: OSGi In Anger - Tara Simpson

Lifecycle Events

• Web service endpoints come and go

• How do we inform interested parties of such events?

• They may need to stop ongoing transactions e.g. in the network layer

Page 45: OSGi In Anger - Tara Simpson

OSGi as an Event Bus

• Whiteboard pattern pervades system

• Core defines and tracks ‘listener’ services

• Bundles implement and export listener implementations

• Layers are massively decoupled from one another

Page 46: OSGi In Anger - Tara Simpson

Service Listener/** * Interface to be implemented classes interested in service events. * Any instance of a type that implements this interface and that is * exported as an OSGi service will be informed of service lifecycle * events. Events are fired <i>asynchronously</i> but sequentially. * <p> * Implementations should not tie up the invoking thread. In other * words the {@link #serviceChanged(ServiceEvent)} method should * return as quickly as possible. */public interface IServiceListener {

/** * Receives notification that a service lifecycle event * has occurred. * * @param serviceEvent the service event */ void serviceChanged(ServiceEvent serviceEvent);}

Page 47: OSGi In Anger - Tara Simpson

Service Event/** * A service event describing a service lifecycle change. * Service events are categorized as: * <pre> * create - signals that a service has been provisioned * update - signals that a service has been updated * dispose - signals that a service has been disposed * destroy - signals that a service has been destroyed * </pre> * An 'update' event signals that a service has been updated * without having to recreate the endpoint from scratch. * If an update requires that a service is re-provisioned * (because its service name has changed), then a 'destroy' * followed by a 'create' event will be emitted. */public final class ServiceEvent {

/** * Returns a service create event. * @param serviceName the newly created service name * @return a create service event */ public static ServiceEvent createEvent(final ServiceName serviceName) { return new ServiceEvent(CREATE, serviceName); }...

Page 48: OSGi In Anger - Tara Simpson

Handling Service Events/** * Purges expired location notification requests from the system. * An expired notification is one that has sent the maximum number * of notifications or has reached its duration limit - both limits * are specified when the notification is created. */public class LocationNotificationTerminator implements ILocationNotificationTerminator, IServiceListener, InitializingBean, DisposableBean {

private ILocationNotificationCriteriaDao criteriaDao;

/** * Deletes data associated with a destroyed service */ public void serviceChanged(final ServiceEvent serviceEvent) { if (serviceEvent.isDestroyEvent()) { logger.debug("Stopping all notifications for " + serviceEvent.getServiceName()); stopAll(criteriaDao.findByServiceName(serviceEvent.getServiceName())); } }...

Page 49: OSGi In Anger - Tara Simpson

Service Adapters

• When deployed inside operator TWS talks to single CORBA-based adapter

• When deployed outside operator TWS proxies onto multiple operator APIs

• Goal is unified API - OneAPI

• Each operator has own service adapter OSGi service

Page 50: OSGi In Anger - Tara Simpson

OneAPI WebService

Service

IServiceAdapter

IServiceAdapter

IServiceAdapter

Exported as OSGi ServiceWith ‘name’ property name=orange

Service Adapters

sprint

vodafone

orange

• Need to support new operator, simply drop new adapter bundle

Page 51: OSGi In Anger - Tara Simpson

Modularity Matters

• TWS is large - without OSGi it would, right now, be a mess

• Modularity enforces better discipline

• Modular designs are more extensible

• Modular designs are easier to test

• Modular designs are cheaper

Page 52: OSGi In Anger - Tara Simpson

Personal Opinion

• First I couldn’t live without Design By Contract

• Then I couldn’t live without BDD & DI

• Now I dread life without OSGi

• Enforced modularity and OSGi services are indispensable design tools