killbill-uncached

Refactor KillbillActivator so it exports only one OSGIKillbill

2/7/2013 12:34:13 AM

Details

diff --git a/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java b/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java
new file mode 100644
index 0000000..ea3b5a9
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/osgi/api/OSGIKillbill.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.osgi.api;
+
+
+import javax.sql.DataSource;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.analytics.api.sanity.AnalyticsSanityApi;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.beatrix.bus.api.ExternalBus;
+import com.ning.billing.catalog.api.CatalogUserApi;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
+import com.ning.billing.entitlement.api.transfer.EntitlementTransferApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.InvoiceMigrationApi;
+import com.ning.billing.invoice.api.InvoicePaymentApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
+import com.ning.billing.overdue.OverdueUserApi;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.tenant.api.TenantUserApi;
+import com.ning.billing.usage.api.UsageUserApi;
+import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.ExportUserApi;
+import com.ning.billing.util.api.TagUserApi;
+
+/**
+ * This interface encapsulates all the OSGI interfaces seen by the Killbill OSGI plugins
+ */
+public interface OSGIKillbill {
+
+    /**
+     * Used  by the OSGI bundles to interact with Killbill through APIs
+     *
+     * @return the matching API
+     */
+    public AccountUserApi getAccountUserApi();
+    public AnalyticsSanityApi getAnalyticsSanityApi();
+    public AnalyticsUserApi getAnalyticsUserApi();
+    public CatalogUserApi getCatalogUserApi();
+    public EntitlementMigrationApi getEntitlementMigrationApi();
+    public EntitlementTimelineApi getEntitlementTimelineApi();
+    public EntitlementTransferApi getEntitlementTransferApi();
+    public EntitlementUserApi getEntitlementUserApi();
+    public InvoiceMigrationApi getInvoiceMigrationApi();
+    public InvoicePaymentApi getInvoicePaymentApi();
+    public InvoiceUserApi getInvoiceUserApi();
+    public OverdueUserApi getOverdueUserApi();
+    public PaymentApi getPaymentApi();
+    public TenantUserApi getTenantUserApi();
+    public UsageUserApi getUsageUserApi();
+    public AuditUserApi getAuditUserApi();
+    public CustomFieldUserApi getCustomFieldUserApi();
+    public ExportUserApi getExportUserApi();
+    public TagUserApi getTagUserApi();
+
+    /**
+     * Used by the OSGI bundles to register interest into Killbill events
+     *
+     * @return the externalBus
+     */
+    public ExternalBus getExternalBus();
+
+
+    /**
+     * Used by the OSGI bundles to discover their configuration
+     *
+     * @return the PluginConfigServiceApi
+     */
+    public PluginConfigServiceApi getPluginConfigServiceApi();
+
+
+    /**
+     * Used by the OSGI bundles to be able to access their own sql tables
+     * @return the dataSource for the OSGI bundles
+     */
+    public DataSource getDataSource();
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java
new file mode 100644
index 0000000..315dfa9
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/DefaultOSGIKillbill.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.osgi;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.sql.DataSource;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.analytics.api.sanity.AnalyticsSanityApi;
+import com.ning.billing.analytics.api.user.AnalyticsUserApi;
+import com.ning.billing.beatrix.bus.api.ExternalBus;
+import com.ning.billing.catalog.api.CatalogUserApi;
+import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
+import com.ning.billing.entitlement.api.transfer.EntitlementTransferApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.invoice.api.InvoiceMigrationApi;
+import com.ning.billing.invoice.api.InvoicePaymentApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.osgi.api.OSGIKillbill;
+import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
+import com.ning.billing.osgi.glue.DefaultOSGIModule;
+import com.ning.billing.overdue.OverdueUserApi;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.tenant.api.TenantUserApi;
+import com.ning.billing.usage.api.UsageUserApi;
+import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.ExportUserApi;
+import com.ning.billing.util.api.TagUserApi;
+
+public class DefaultOSGIKillbill implements OSGIKillbill {
+
+    private final AccountUserApi accountUserApi;
+    private final AnalyticsSanityApi analyticsSanityApi;
+    private final AnalyticsUserApi analyticsUserApi;
+    private final CatalogUserApi catalogUserApi;
+    private final EntitlementMigrationApi entitlementMigrationApi;
+    private final EntitlementTimelineApi entitlementTimelineApi;
+    private final EntitlementTransferApi entitlementTransferApi;
+    private final EntitlementUserApi entitlementUserApi;
+    private final InvoiceMigrationApi invoiceMigrationApi;
+    private final InvoicePaymentApi invoicePaymentApi;
+    private final InvoiceUserApi invoiceUserApi;
+    private final OverdueUserApi overdueUserApi;
+    private final PaymentApi paymentApi;
+    private final TenantUserApi tenantUserApi;
+    private final UsageUserApi usageUserApi;
+    private final AuditUserApi auditUserApi;
+    private final CustomFieldUserApi customFieldUserApi;
+    private final ExportUserApi exportUserApi;
+    private final TagUserApi tagUserApi;
+
+    private final ExternalBus externalBus;
+    private final PluginConfigServiceApi configServiceApi;
+
+    private final DataSource dataSource;
+
+    @Inject
+    public DefaultOSGIKillbill(final @Named(DefaultOSGIModule.OSGI_NAMED) DataSource dataSource,
+                               final AccountUserApi accountUserApi,
+                               final AnalyticsSanityApi analyticsSanityApi,
+                               final AnalyticsUserApi analyticsUserApi,
+                               final CatalogUserApi catalogUserApi,
+                               final EntitlementMigrationApi entitlementMigrationApi,
+                               final EntitlementTimelineApi entitlementTimelineApi,
+                               final EntitlementTransferApi entitlementTransferApi,
+                               final EntitlementUserApi entitlementUserApi,
+                               final InvoiceMigrationApi invoiceMigrationApi,
+                               final InvoicePaymentApi invoicePaymentApi,
+                               final InvoiceUserApi invoiceUserApi,
+                               final OverdueUserApi overdueUserApi,
+                               final PaymentApi paymentApi,
+                               final TenantUserApi tenantUserApi,
+                               final UsageUserApi usageUserApi,
+                               final AuditUserApi auditUserApi,
+                               final CustomFieldUserApi customFieldUserApi,
+                               final ExportUserApi exportUserApi,
+                               final TagUserApi tagUserApi,
+                               final ExternalBus externalBus,
+                               final PluginConfigServiceApi configServiceApi) {
+        this.dataSource = dataSource;
+        this.accountUserApi = accountUserApi;
+        this.analyticsSanityApi = analyticsSanityApi;
+        this.analyticsUserApi = analyticsUserApi;
+        this.catalogUserApi = catalogUserApi;
+        this.entitlementMigrationApi = entitlementMigrationApi;
+        this.entitlementTimelineApi = entitlementTimelineApi;
+        this.entitlementTransferApi = entitlementTransferApi;
+        this.entitlementUserApi = entitlementUserApi;
+        this.invoiceMigrationApi = invoiceMigrationApi;
+        this.invoicePaymentApi = invoicePaymentApi;
+        this.invoiceUserApi = invoiceUserApi;
+        this.overdueUserApi = overdueUserApi;
+        this.paymentApi = paymentApi;
+        this.tenantUserApi = tenantUserApi;
+        this.usageUserApi = usageUserApi;
+        this.auditUserApi = auditUserApi;
+        this.customFieldUserApi = customFieldUserApi;
+        this.exportUserApi = exportUserApi;
+        this.tagUserApi = tagUserApi;
+        this.externalBus = externalBus;
+        this.configServiceApi = configServiceApi;
+    }
+
+    @Override
+    public AccountUserApi getAccountUserApi() {
+        return accountUserApi;
+    }
+
+    @Override
+    public AnalyticsSanityApi getAnalyticsSanityApi() {
+        return analyticsSanityApi;
+    }
+
+    @Override
+    public AnalyticsUserApi getAnalyticsUserApi() {
+        return analyticsUserApi;
+    }
+
+    @Override
+    public CatalogUserApi getCatalogUserApi() {
+        return catalogUserApi;
+    }
+
+    @Override
+    public EntitlementMigrationApi getEntitlementMigrationApi() {
+        return entitlementMigrationApi;
+    }
+
+    @Override
+    public EntitlementTimelineApi getEntitlementTimelineApi() {
+        return entitlementTimelineApi;
+    }
+
+    @Override
+    public EntitlementTransferApi getEntitlementTransferApi() {
+        return entitlementTransferApi;
+    }
+
+    @Override
+    public EntitlementUserApi getEntitlementUserApi() {
+        return entitlementUserApi;
+    }
+
+    @Override
+    public InvoiceMigrationApi getInvoiceMigrationApi() {
+        return invoiceMigrationApi;
+    }
+
+    @Override
+    public InvoicePaymentApi getInvoicePaymentApi() {
+        return invoicePaymentApi;
+    }
+
+    @Override
+    public InvoiceUserApi getInvoiceUserApi() {
+        return invoiceUserApi;
+    }
+
+    @Override
+    public OverdueUserApi getOverdueUserApi() {
+        return overdueUserApi;
+    }
+
+    @Override
+    public PaymentApi getPaymentApi() {
+        return paymentApi;
+    }
+
+    @Override
+    public TenantUserApi getTenantUserApi() {
+        return tenantUserApi;
+    }
+
+    @Override
+    public UsageUserApi getUsageUserApi() {
+        return usageUserApi;
+    }
+
+    @Override
+    public AuditUserApi getAuditUserApi() {
+        return auditUserApi;
+    }
+
+    @Override
+    public CustomFieldUserApi getCustomFieldUserApi() {
+        return customFieldUserApi;
+    }
+
+    @Override
+    public ExportUserApi getExportUserApi() {
+        return exportUserApi;
+    }
+
+    @Override
+    public TagUserApi getTagUserApi() {
+        return tagUserApi;
+    }
+
+    @Override
+    public ExternalBus getExternalBus() {
+        return externalBus;
+    }
+
+    @Override
+    public PluginConfigServiceApi getPluginConfigServiceApi() {
+        return configServiceApi;
+    }
+
+    @Override
+    public DataSource getDataSource() {
+        return dataSource;
+    }
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java b/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
index b505635..0655cf9 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/glue/DefaultOSGIModule.java
@@ -16,21 +16,31 @@
 
 package com.ning.billing.osgi.glue;
 
+import javax.sql.DataSource;
+
 import org.skife.config.ConfigurationObjectFactory;
 
+import com.ning.billing.osgi.DefaultOSGIKillbill;
 import com.ning.billing.osgi.KillbillActivator;
+import com.ning.billing.osgi.api.OSGIKillbill;
 import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
 import com.ning.billing.osgi.pluginconf.DefaultPluginConfigServiceApi;
 import com.ning.billing.osgi.pluginconf.PluginFinder;
 import com.ning.billing.util.config.OSGIConfig;
 
 import com.google.inject.AbstractModule;
+import com.google.inject.name.Names;
 
 public class DefaultOSGIModule extends AbstractModule {
 
+    public static final String OSGI_NAMED = "osgi";
+
     protected void installConfig() {
         final OSGIConfig config = new ConfigurationObjectFactory(System.getProperties()).build(OSGIConfig.class);
         bind(OSGIConfig.class).toInstance(config);
+
+        final OSGIDataSourceConfig osgiDataSourceConfig = new ConfigurationObjectFactory(System.getProperties()).build(OSGIDataSourceConfig.class);
+        bind(OSGIDataSourceConfig.class).toInstance(osgiDataSourceConfig);
     }
 
     @Override
@@ -39,5 +49,8 @@ public class DefaultOSGIModule extends AbstractModule {
         bind(KillbillActivator.class).asEagerSingleton();
         bind(PluginFinder.class).asEagerSingleton();
         bind(PluginConfigServiceApi.class).to(DefaultPluginConfigServiceApi.class).asEagerSingleton();
+        bind(OSGIKillbill.class).to(DefaultOSGIKillbill.class).asEagerSingleton();
+        bind(OSGIDataSourceProvider.class).asEagerSingleton();
+        bind(DataSource.class).annotatedWith(Names.named(OSGI_NAMED)).toProvider(OSGIDataSourceProvider.class).asEagerSingleton();
     }
 }
diff --git a/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceConfig.java b/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceConfig.java
new file mode 100644
index 0000000..ba06292
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceConfig.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.osgi.glue;
+
+import org.skife.config.Config;
+import org.skife.config.Default;
+import org.skife.config.Description;
+import org.skife.config.TimeSpan;
+
+public interface OSGIDataSourceConfig {
+
+    static String DATA_SOURCE_PROP_PREFIX = "com.ning.billing.osgi.";
+
+    @Description("The jdbc url for the database")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.url")
+    @Default("jdbc:mysql://127.0.0.1:3306/killbill")
+    String getJdbcUrl();
+
+    @Description("The jdbc user name for the database")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.user")
+    @Default("root")
+    String getUsername();
+
+    @Description("The jdbc password for the database")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.password")
+    @Default("root")
+    String getPassword();
+
+    @Description("The minimum allowed number of idle connections to the database")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.minIdle")
+    @Default("1")
+    int getMinIdle();
+
+    @Description("The maximum allowed number of active connections to the database")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.maxActive")
+    @Default("10")
+    int getMaxActive();
+
+    @Description("How long to wait before a connection attempt to the database is considered timed out")
+    @Config(DATA_SOURCE_PROP_PREFIX + "jdbc.connectionTimeout")
+    @Default("10s")
+    TimeSpan getConnectionTimeout();
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceProvider.java b/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceProvider.java
new file mode 100644
index 0000000..673aae3
--- /dev/null
+++ b/osgi/src/main/java/com/ning/billing/osgi/glue/OSGIDataSourceProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.osgi.glue;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.sql.DataSource;
+
+import com.jolbox.bonecp.BoneCPConfig;
+import com.jolbox.bonecp.BoneCPDataSource;
+
+public class OSGIDataSourceProvider implements Provider<DataSource> {
+
+    private final BoneCPConfig config;
+
+    @Inject
+    public OSGIDataSourceProvider(final OSGIDataSourceConfig config) {
+        this.config = createConfig(config.getJdbcUrl(), config.getUsername(), config.getPassword());
+    }
+
+    @Override
+    public DataSource get() {
+        return new BoneCPDataSource(config);
+    }
+
+    private BoneCPConfig createConfig(final String dbiString, final String userName, final String pwd) {
+        final BoneCPConfig dbConfig = new BoneCPConfig();
+        dbConfig.setJdbcUrl(dbiString);
+        dbConfig.setUsername(userName);
+        dbConfig.setPassword(pwd);
+        dbConfig.setMinConnectionsPerPartition(1);
+        dbConfig.setMaxConnectionsPerPartition(30);
+        dbConfig.setConnectionTimeout(10, TimeUnit.SECONDS);
+        dbConfig.setPartitionCount(1);
+        dbConfig.setDefaultTransactionIsolation("REPEATABLE_READ");
+        dbConfig.setDisableJMX(false);
+        dbConfig.setLazyInit(true);
+        return dbConfig;
+    }
+}
diff --git a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
index 1367f4f..586aa12 100644
--- a/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
+++ b/osgi/src/main/java/com/ning/billing/osgi/KillbillActivator.java
@@ -22,120 +22,17 @@ import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
-import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.analytics.api.sanity.AnalyticsSanityApi;
-import com.ning.billing.analytics.api.user.AnalyticsUserApi;
-import com.ning.billing.beatrix.bus.api.ExternalBus;
-import com.ning.billing.catalog.api.CatalogUserApi;
-import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
-import com.ning.billing.entitlement.api.transfer.EntitlementTransferApi;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
-import com.ning.billing.invoice.api.InvoiceMigrationApi;
-import com.ning.billing.invoice.api.InvoicePaymentApi;
-import com.ning.billing.invoice.api.InvoiceUserApi;
-import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
-import com.ning.billing.overdue.OverdueUserApi;
-import com.ning.billing.payment.api.PaymentApi;
-import com.ning.billing.tenant.api.TenantUserApi;
-import com.ning.billing.usage.api.UsageUserApi;
-import com.ning.billing.util.api.AuditUserApi;
-import com.ning.billing.util.api.CustomFieldUserApi;
-import com.ning.billing.util.api.ExportUserApi;
-import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.osgi.api.OSGIKillbill;
 
 public class KillbillActivator implements BundleActivator {
 
-    private final AccountUserApi accountUserApi;
-    private final AnalyticsSanityApi analyticsSanityApi;
-    private final AnalyticsUserApi analyticsUserApi;
-    private final CatalogUserApi catalogUserApi;
-    private final EntitlementMigrationApi entitlementMigrationApi;
-    private final EntitlementTimelineApi entitlementTimelineApi;
-    private final EntitlementTransferApi entitlementTransferApi;
-    private final EntitlementUserApi entitlementUserApi;
-    private final InvoiceMigrationApi invoiceMigrationApi;
-    private final InvoicePaymentApi invoicePaymentApi;
-    private final InvoiceUserApi invoiceUserApi;
-    private final OverdueUserApi overdueUserApi;
-    private final PaymentApi paymentApi;
-    private final TenantUserApi tenantUserApi;
-    private final UsageUserApi usageUserApi;
-    private final AuditUserApi auditUserApi;
-    private final CustomFieldUserApi customFieldUserApi;
-    private final ExportUserApi exportUserApi;
-    private final TagUserApi tagUserApi;
+    private final OSGIKillbill osgiKillbill;
 
-    private final ExternalBus externalBus;
-    private final PluginConfigServiceApi configServiceApi;
-
-    private volatile ServiceRegistration accountUserApiRegistration = null;
-    private volatile ServiceRegistration analyticsSanityApiRegistration = null;
-    private volatile ServiceRegistration analyticsUserApiRegistration = null;
-    private volatile ServiceRegistration catalogUserApiRegistration = null;
-    private volatile ServiceRegistration entitlementMigrationApiRegistration = null;
-    private volatile ServiceRegistration entitlementTimelineApiRegistration = null;
-    private volatile ServiceRegistration entitlementTransferApiRegistration = null;
-    private volatile ServiceRegistration entitlementUserApiRegistration = null;
-    private volatile ServiceRegistration invoiceMigrationApiRegistration = null;
-    private volatile ServiceRegistration invoicePaymentApiRegistration = null;
-    private volatile ServiceRegistration invoiceUserApiRegistration = null;
-    private volatile ServiceRegistration meterUserApiRegistration = null;
-    private volatile ServiceRegistration overdueUserApiRegistration = null;
-    private volatile ServiceRegistration paymentApiRegistration = null;
-    private volatile ServiceRegistration tenantUserApiRegistration = null;
-    private volatile ServiceRegistration usageUserApiRegistration = null;
-    private volatile ServiceRegistration auditUserApiRegistration = null;
-    private volatile ServiceRegistration customFieldUserApiRegistration = null;
-    private volatile ServiceRegistration exportUserApiRegistration = null;
-    private volatile ServiceRegistration tagUserApiRegistration = null;
-
-    private volatile ServiceRegistration externalBusRegistration = null;
-    private volatile ServiceRegistration configServiceApiRegistration = null;
+    private volatile ServiceRegistration osgiKillbillRegistration;
 
     @Inject
-    public KillbillActivator(final AccountUserApi accountUserApi,
-                             final AnalyticsSanityApi analyticsSanityApi,
-                             final AnalyticsUserApi analyticsUserApi,
-                             final CatalogUserApi catalogUserApi,
-                             final EntitlementMigrationApi entitlementMigrationApi,
-                             final EntitlementTimelineApi entitlementTimelineApi,
-                             final EntitlementTransferApi entitlementTransferApi,
-                             final EntitlementUserApi entitlementUserApi,
-                             final InvoiceMigrationApi invoiceMigrationApi,
-                             final InvoicePaymentApi invoicePaymentApi,
-                             final InvoiceUserApi invoiceUserApi,
-                             final OverdueUserApi overdueUserApi,
-                             final PaymentApi paymentApi,
-                             final TenantUserApi tenantUserApi,
-                             final UsageUserApi usageUserApi,
-                             final AuditUserApi auditUserApi,
-                             final CustomFieldUserApi customFieldUserApi,
-                             final ExportUserApi exportUserApi,
-                             final TagUserApi tagUserApi,
-                             final ExternalBus externalBus,
-                             final PluginConfigServiceApi configServiceApi) {
-        this.accountUserApi = accountUserApi;
-        this.analyticsSanityApi = analyticsSanityApi;
-        this.analyticsUserApi = analyticsUserApi;
-        this.catalogUserApi = catalogUserApi;
-        this.entitlementMigrationApi = entitlementMigrationApi;
-        this.entitlementTimelineApi = entitlementTimelineApi;
-        this.entitlementTransferApi = entitlementTransferApi;
-        this.entitlementUserApi = entitlementUserApi;
-        this.invoiceMigrationApi = invoiceMigrationApi;
-        this.invoicePaymentApi = invoicePaymentApi;
-        this.invoiceUserApi = invoiceUserApi;
-        this.overdueUserApi = overdueUserApi;
-        this.paymentApi = paymentApi;
-        this.tenantUserApi = tenantUserApi;
-        this.usageUserApi = usageUserApi;
-        this.auditUserApi = auditUserApi;
-        this.customFieldUserApi = customFieldUserApi;
-        this.exportUserApi = exportUserApi;
-        this.tagUserApi = tagUserApi;
-        this.externalBus = externalBus;
-        this.configServiceApi = configServiceApi;
+    public KillbillActivator(final OSGIKillbill osgiKillbill) {
+        this.osgiKillbill = osgiKillbill;
     }
 
     @Override
@@ -144,120 +41,14 @@ public class KillbillActivator implements BundleActivator {
     }
 
     private void registerServices(final BundleContext context) {
-        accountUserApiRegistration = context.registerService(AccountUserApi.class.getName(), accountUserApi, null);
-        analyticsSanityApiRegistration = context.registerService(AnalyticsSanityApi.class.getName(), analyticsSanityApi, null);
-        analyticsUserApiRegistration = context.registerService(AnalyticsUserApi.class.getName(), analyticsUserApi, null);
-        catalogUserApiRegistration = context.registerService(CatalogUserApi.class.getName(), catalogUserApi, null);
-        entitlementMigrationApiRegistration = context.registerService(EntitlementMigrationApi.class.getName(), entitlementMigrationApi, null);
-        entitlementTimelineApiRegistration = context.registerService(EntitlementTimelineApi.class.getName(), entitlementTimelineApi, null);
-        entitlementTransferApiRegistration = context.registerService(EntitlementTransferApi.class.getName(), entitlementTransferApi, null);
-        entitlementUserApiRegistration = context.registerService(EntitlementUserApi.class.getName(), entitlementUserApi, null);
-        invoiceMigrationApiRegistration = context.registerService(InvoiceMigrationApi.class.getName(), invoiceMigrationApi, null);
-        invoicePaymentApiRegistration = context.registerService(InvoicePaymentApi.class.getName(), invoicePaymentApi, null);
-        invoiceUserApiRegistration = context.registerService(InvoiceUserApi.class.getName(), invoiceUserApi, null);
-        overdueUserApiRegistration = context.registerService(OverdueUserApi.class.getName(), overdueUserApi, null);
-        paymentApiRegistration = context.registerService(PaymentApi.class.getName(), paymentApi, null);
-        tenantUserApiRegistration = context.registerService(TenantUserApi.class.getName(), tenantUserApi, null);
-        usageUserApiRegistration = context.registerService(UsageUserApi.class.getName(), usageUserApi, null);
-        auditUserApiRegistration = context.registerService(AuditUserApi.class.getName(), auditUserApi, null);
-        customFieldUserApiRegistration = context.registerService(CustomFieldUserApi.class.getName(), customFieldUserApi, null);
-        exportUserApiRegistration = context.registerService(ExportUserApi.class.getName(), exportUserApi, null);
-        tagUserApiRegistration = context.registerService(TagUserApi.class.getName(), tagUserApi, null);
-
-        externalBusRegistration = context.registerService(ExternalBus.class.getName(), externalBus, null);
-        configServiceApiRegistration = context.registerService(PluginConfigServiceApi.class.getName(), configServiceApi, null);
+        osgiKillbillRegistration = context.registerService(OSGIKillbill.class.getName(), osgiKillbill, null);
     }
 
     @Override
     public void stop(final BundleContext context) throws Exception {
-        if (accountUserApiRegistration != null) {
-            accountUserApiRegistration.unregister();
-            accountUserApiRegistration = null;
-        }
-        if (analyticsSanityApiRegistration != null) {
-            analyticsSanityApiRegistration.unregister();
-            analyticsSanityApiRegistration = null;
-        }
-        if (analyticsUserApiRegistration != null) {
-            analyticsUserApiRegistration.unregister();
-            analyticsUserApiRegistration = null;
-        }
-        if (catalogUserApiRegistration != null) {
-            catalogUserApiRegistration.unregister();
-            catalogUserApiRegistration = null;
-        }
-        if (entitlementMigrationApiRegistration != null) {
-            entitlementMigrationApiRegistration.unregister();
-            entitlementMigrationApiRegistration = null;
-        }
-        if (entitlementTimelineApiRegistration != null) {
-            entitlementTimelineApiRegistration.unregister();
-            entitlementTimelineApiRegistration = null;
-        }
-        if (entitlementTransferApiRegistration != null) {
-            entitlementTransferApiRegistration.unregister();
-            entitlementTransferApiRegistration = null;
-        }
-        if (entitlementUserApiRegistration != null) {
-            entitlementUserApiRegistration.unregister();
-            entitlementUserApiRegistration = null;
-        }
-        if (invoiceMigrationApiRegistration != null) {
-            invoiceMigrationApiRegistration.unregister();
-            invoiceMigrationApiRegistration = null;
-        }
-        if (invoicePaymentApiRegistration != null) {
-            invoicePaymentApiRegistration.unregister();
-            invoicePaymentApiRegistration = null;
-        }
-        if (invoiceUserApiRegistration != null) {
-            invoiceUserApiRegistration.unregister();
-            invoiceUserApiRegistration = null;
-        }
-        if (meterUserApiRegistration != null) {
-            meterUserApiRegistration.unregister();
-            meterUserApiRegistration = null;
-        }
-        if (overdueUserApiRegistration != null) {
-            overdueUserApiRegistration.unregister();
-            overdueUserApiRegistration = null;
-        }
-        if (paymentApiRegistration != null) {
-            paymentApiRegistration.unregister();
-            paymentApiRegistration = null;
-        }
-        if (tenantUserApiRegistration != null) {
-            tenantUserApiRegistration.unregister();
-            tenantUserApiRegistration = null;
-        }
-        if (usageUserApiRegistration != null) {
-            usageUserApiRegistration.unregister();
-            usageUserApiRegistration = null;
-        }
-        if (auditUserApiRegistration != null) {
-            auditUserApiRegistration.unregister();
-            auditUserApiRegistration = null;
-        }
-        if (customFieldUserApiRegistration != null) {
-            customFieldUserApiRegistration.unregister();
-            customFieldUserApiRegistration = null;
-        }
-        if (exportUserApiRegistration != null) {
-            exportUserApiRegistration.unregister();
-            exportUserApiRegistration = null;
-        }
-        if (tagUserApiRegistration != null) {
-            tagUserApiRegistration.unregister();
-            tagUserApiRegistration = null;
-        }
-        if (externalBusRegistration != null) {
-            externalBusRegistration.unregister();
-            externalBusRegistration = null;
-        }
-
-        if (configServiceApiRegistration != null) {
-            configServiceApiRegistration.unregister();
-            configServiceApiRegistration = null;
+        if (osgiKillbillRegistration != null) {
+            osgiKillbillRegistration.unregister();
+            osgiKillbillRegistration = null;
         }
     }
 
diff --git a/osgi-bundles/hello/src/main/java/com/ning/billing/osgi/bundles/hello/HelloActivator.java b/osgi-bundles/hello/src/main/java/com/ning/billing/osgi/bundles/hello/HelloActivator.java
index f815253..c0019d4 100644
--- a/osgi-bundles/hello/src/main/java/com/ning/billing/osgi/bundles/hello/HelloActivator.java
+++ b/osgi-bundles/hello/src/main/java/com/ning/billing/osgi/bundles/hello/HelloActivator.java
@@ -31,6 +31,7 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.beatrix.bus.api.ExtBusEvent;
 import com.ning.billing.beatrix.bus.api.ExternalBus;
+import com.ning.billing.osgi.api.OSGIKillbill;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentPluginApi;
@@ -43,12 +44,17 @@ import com.google.common.eventbus.Subscribe;
 
 public class HelloActivator implements BundleActivator {
 
+    private OSGIKillbill osgiKillbill;
+
+    private volatile ServiceReference<OSGIKillbill> osgiKillbillReference;
+
     private volatile boolean isRunning;
     private volatile ServiceRegistration paymentInfoPluginRegistration;
 
     @Override
     public void start(final BundleContext context) {
-        isRunning = true;
+        this.isRunning = true;
+        fetchOSGIKIllbill(context);
         System.out.println("Hello world from HelloActivator!");
 
         doSomeWorkWithKillbillApis(context);
@@ -58,7 +64,9 @@ public class HelloActivator implements BundleActivator {
 
     @Override
     public void stop(final BundleContext context) {
-        isRunning = false;
+        this.isRunning = false;
+        releaseOSGIKIllbill(context);
+        this.osgiKillbill = null;
         System.out.println("Good bye world from HelloActivator!");
     }
 
@@ -74,9 +82,8 @@ public class HelloActivator implements BundleActivator {
             @Override
             public void run() {
                 while (isRunning) {
-                    @SuppressWarnings("unchecked")
-                    final ServiceReference<AccountUserApi> accountUserApiReference = (ServiceReference<AccountUserApi>) context.getServiceReference(AccountUserApi.class.getName());
-                    final AccountUserApi accountUserApi = context.getService(accountUserApiReference);
+
+                    final AccountUserApi accountUserApi = osgiKillbill.getAccountUserApi();
 
                     try {
                         final List<Account> accounts = accountUserApi.getAccounts(tenantContext);
@@ -86,10 +93,6 @@ public class HelloActivator implements BundleActivator {
                         System.err.println("Interrupted in HelloActivator");
                     } catch (Exception e) {
                         System.err.println("Error in HelloActivator: " + e.getLocalizedMessage());
-                    } finally {
-                        if (accountUserApiReference != null) {
-                            context.ungetService(accountUserApiReference);
-                        }
                     }
                 }
             }
@@ -98,17 +101,27 @@ public class HelloActivator implements BundleActivator {
     }
 
     private void registerForKillbillEvents(final BundleContext context) {
-        @SuppressWarnings("unchecked")
-        final ServiceReference<ExternalBus> externalBusReference = (ServiceReference<ExternalBus>) context.getServiceReference(ExternalBus.class.getName());
         try {
-            final ExternalBus externalBus = context.getService(externalBusReference);
+            final ExternalBus externalBus = osgiKillbill.getExternalBus();
             externalBus.register(this);
         } catch (Exception e) {
             System.err.println("Error in HelloActivator: " + e.getLocalizedMessage());
         } finally {
-            if (externalBusReference != null) {
-                context.ungetService(externalBusReference);
-            }
+        }
+    }
+
+    private void fetchOSGIKIllbill(final BundleContext context) {
+        this.osgiKillbillReference = (ServiceReference<OSGIKillbill>) context.getServiceReference(OSGIKillbill.class.getName());
+        try {
+            this.osgiKillbill = context.getService(osgiKillbillReference);
+        } catch (Exception e) {
+            System.err.println("Error in HelloActivator: " + e.getLocalizedMessage());
+        }
+    }
+
+    private void releaseOSGIKIllbill(final BundleContext context) {
+        if (osgiKillbillReference != null) {
+            context.ungetService(osgiKillbillReference);
         }
     }
 
diff --git a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
index a8bb391..a25a8a5 100644
--- a/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
+++ b/osgi-bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/Activator.java
@@ -39,6 +39,7 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.osgi.api.OSGIKillbill;
 import com.ning.billing.osgi.api.config.PluginConfig.PluginType;
 import com.ning.billing.osgi.api.config.PluginConfigServiceApi;
 import com.ning.billing.osgi.api.config.PluginRubyConfig;
@@ -55,11 +56,13 @@ public class Activator implements BundleActivator {
 
     private final List<ServiceReference<?>> serviceReferences = new ArrayList<ServiceReference<?>>();
 
+    private OSGIKillbill osgiKillbill;
     private LogService logger = null;
     private JRubyPlugin plugin = null;
 
     public void start(final BundleContext context) throws Exception {
         logger = retrieveApi(context, LogService.class);
+        osgiKillbill = retrieveApi(context, OSGIKillbill.class);
         log(LogService.LOG_INFO, "JRuby bundle activated");
 
         doMagicToMakeJRubyAndFelixHappy();
@@ -76,6 +79,7 @@ public class Activator implements BundleActivator {
         }
 
         // Validate and instantiate the plugin
+
         final Map<String, Object> killbillApis = retrieveKillbillApis(context);
         plugin.instantiatePlugin(killbillApis);
 
@@ -84,9 +88,7 @@ public class Activator implements BundleActivator {
     }
 
     private PluginRubyConfig retrievePluginRubyConfig(final BundleContext context) {
-        @SuppressWarnings("unchecked")
-        final ServiceReference<PluginConfigServiceApi> pluginConfigServiceApiServiceReference = (ServiceReference<PluginConfigServiceApi>) context.getServiceReference(PluginConfigServiceApi.class.getName());
-        final PluginConfigServiceApi pluginConfigServiceApi = context.getService(pluginConfigServiceApiServiceReference);
+        final PluginConfigServiceApi pluginConfigServiceApi = osgiKillbill.getPluginConfigServiceApi();
         return pluginConfigServiceApi.getPluginRubyConfig(context.getBundle().getBundleId());
     }
 
@@ -119,25 +121,25 @@ public class Activator implements BundleActivator {
         final Map<String, Object> killbillUserApis = new HashMap<String, Object>();
 
         // See killbill/plugin.rb for the naming convention magic
-        killbillUserApis.put("account_user_api", retrieveApi(context, AccountUserApi.class));
-        killbillUserApis.put("analytics_sanity_api", retrieveApi(context, AnalyticsSanityApi.class));
-        killbillUserApis.put("analytics_user_api", retrieveApi(context, AnalyticsUserApi.class));
-        killbillUserApis.put("catalog_user_api", retrieveApi(context, CatalogUserApi.class));
-        killbillUserApis.put("entitlement_migration_api", retrieveApi(context, EntitlementMigrationApi.class));
-        killbillUserApis.put("entitlement_timeline_api", retrieveApi(context, EntitlementTimelineApi.class));
-        killbillUserApis.put("entitlement_transfer_api", retrieveApi(context, EntitlementTransferApi.class));
-        killbillUserApis.put("entitlement_user_api", retrieveApi(context, EntitlementUserApi.class));
-        killbillUserApis.put("invoice_migration_api", retrieveApi(context, InvoiceMigrationApi.class));
-        killbillUserApis.put("invoice_payment_api", retrieveApi(context, InvoicePaymentApi.class));
-        killbillUserApis.put("invoice_user_api", retrieveApi(context, InvoiceUserApi.class));
-        killbillUserApis.put("overdue_user_api", retrieveApi(context, OverdueUserApi.class));
-        killbillUserApis.put("payment_api", retrieveApi(context, PaymentApi.class));
-        killbillUserApis.put("tenant_user_api", retrieveApi(context, TenantUserApi.class));
-        killbillUserApis.put("usage_user_api", retrieveApi(context, UsageUserApi.class));
-        killbillUserApis.put("audit_user_api", retrieveApi(context, AuditUserApi.class));
-        killbillUserApis.put("custom_field_user_api", retrieveApi(context, CustomFieldUserApi.class));
-        killbillUserApis.put("export_user_api", retrieveApi(context, ExportUserApi.class));
-        killbillUserApis.put("tag_user_api", retrieveApi(context, TagUserApi.class));
+        killbillUserApis.put("account_user_api", osgiKillbill.getAccountUserApi());
+        killbillUserApis.put("analytics_sanity_api", osgiKillbill.getAnalyticsSanityApi());
+        killbillUserApis.put("analytics_user_api", osgiKillbill.getAnalyticsUserApi());
+        killbillUserApis.put("catalog_user_api", osgiKillbill.getCatalogUserApi());
+        killbillUserApis.put("entitlement_migration_api", osgiKillbill.getEntitlementMigrationApi());
+        killbillUserApis.put("entitlement_timeline_api", osgiKillbill.getEntitlementMigrationApi());
+        killbillUserApis.put("entitlement_transfer_api", osgiKillbill.getEntitlementTransferApi());
+        killbillUserApis.put("entitlement_user_api", osgiKillbill.getEntitlementUserApi());
+        killbillUserApis.put("invoice_migration_api", osgiKillbill.getInvoiceMigrationApi());
+        killbillUserApis.put("invoice_payment_api", osgiKillbill.getInvoicePaymentApi());
+        killbillUserApis.put("invoice_user_api", osgiKillbill.getInvoiceUserApi());
+        killbillUserApis.put("overdue_user_api", osgiKillbill.getOverdueUserApi());
+        killbillUserApis.put("payment_api", osgiKillbill.getPaymentApi());
+        killbillUserApis.put("tenant_user_api", osgiKillbill.getTagUserApi());
+        killbillUserApis.put("usage_user_api", osgiKillbill.getUsageUserApi());
+        killbillUserApis.put("audit_user_api", osgiKillbill.getAuditUserApi());
+        killbillUserApis.put("custom_field_user_api", osgiKillbill.getCustomFieldUserApi());
+        killbillUserApis.put("export_user_api", osgiKillbill.getExportUserApi());
+        killbillUserApis.put("tag_user_api", osgiKillbill.getTagUserApi());
 
         return killbillUserApis;
     }