killbill-aplcache
Changes
invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java 8(+3 -5)
server/pom.xml 57(+56 -1)
server/src/test/resources/catalog-weapons-xml 641(+641 -0)
Details
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index a22491b..d6752e9 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -49,6 +49,7 @@ public class DefaultAccount extends ExtendedEntityBase implements Account {
private final String phone;
private final String updatedBy;
private final DateTime updatedDate;
+
//intended for creation and migration
public DefaultAccount(final String createdBy, final DateTime createdDate,
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
index 60e0a14..70beb4c 100644
--- a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -16,7 +16,6 @@
package com.ning.billing.account.glue;
-import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.AbstractModule;
import com.ning.billing.account.api.AccountService;
@@ -29,8 +28,6 @@ import com.ning.billing.account.dao.AuditedAccountDao;
public class AccountModule extends AbstractModule {
private void installConfig() {
- final AccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(AccountConfig.class);
- bind(AccountConfig.class).toInstance(config);
}
protected void installAccountDao() {
diff --git a/api/src/main/java/com/ning/billing/config/CatalogConfig.java b/api/src/main/java/com/ning/billing/config/CatalogConfig.java
index 21be358..97f4957 100644
--- a/api/src/main/java/com/ning/billing/config/CatalogConfig.java
+++ b/api/src/main/java/com/ning/billing/config/CatalogConfig.java
@@ -19,7 +19,7 @@ package com.ning.billing.config;
import org.skife.config.Config;
import org.skife.config.Default;
-public interface CatalogConfig {
+public interface CatalogConfig extends KillbillConfig {
@Config("killbill.catalog.uri")
@Default("jar:///com/ning/billing/irs/catalog/NingCatalog.xml")
diff --git a/api/src/main/java/com/ning/billing/config/EntitlementConfig.java b/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
index 1b6f3e2..c73530f 100644
--- a/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
+++ b/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
@@ -19,21 +19,27 @@ package com.ning.billing.config;
import org.skife.config.Config;
import org.skife.config.Default;
-public interface EntitlementConfig {
+import com.google.common.annotations.VisibleForTesting;
+public interface EntitlementConfig extends NotificationConfig, KillbillConfig {
+
+ @Override
@Config("killbill.entitlement.dao.claim.time")
@Default("60000")
public long getDaoClaimTimeMs();
+ @Override
@Config("killbill.entitlement.dao.ready.max")
@Default("10")
public int getDaoMaxReadyEvents();
+ @Override
@Config("killbill.entitlement.engine.notifications.sleep")
@Default("500")
public long getNotificationSleepTimeMs();
+ @Override
@Config("killbill.notifications.off")
@Default("false")
- public boolean isEventProcessingOff();
+ public boolean isNotificationProcessingOff();
}
diff --git a/api/src/main/java/com/ning/billing/config/InvoiceConfig.java b/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
index f56d3c2..18972eb 100644
--- a/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
+++ b/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
@@ -19,23 +19,27 @@ package com.ning.billing.config;
import org.skife.config.Config;
import org.skife.config.Default;
-public interface InvoiceConfig {
+public interface InvoiceConfig extends NotificationConfig, KillbillConfig {
+ @Override
@Config("killbill.invoice.dao.claim.time")
@Default("60000")
public long getDaoClaimTimeMs();
+ @Override
@Config("killbill.invoice.dao.ready.max")
@Default("10")
public int getDaoMaxReadyEvents();
+ @Override
@Config("killbill.invoice.engine.notifications.sleep")
@Default("500")
public long getNotificationSleepTimeMs();
+ @Override
@Config("killbill.notifications.off")
@Default("false")
- public boolean isEventProcessingOff();
+ public boolean isNotificationProcessingOff();
@Config("killbill.invoice.maxNumberOfMonthsInFuture")
@Default("36")
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
index 304cb0b..447b5b7 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
@@ -37,6 +37,7 @@ import com.ning.billing.beatrix.lifecycle.DefaultLifecycle;
import com.ning.billing.beatrix.lifecycle.Lifecycle;
import com.ning.billing.catalog.api.CatalogService;
import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.dbi.DBIProvider;
import com.ning.billing.dbi.DbiConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
@@ -47,7 +48,6 @@ import com.ning.billing.invoice.glue.InvoiceModule;
import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.payment.api.PaymentService;
import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
-import com.ning.billing.payment.setup.PaymentConfig;
import com.ning.billing.payment.setup.PaymentModule;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 55ea2cf..fe1765c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -33,6 +33,7 @@ import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.config.EntitlementConfig;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.alignment.TimedPhase;
import com.ning.billing.entitlement.api.EntitlementService;
@@ -60,7 +61,6 @@ import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.Bus.EventBusException;
-import com.ning.billing.util.notificationq.NotificationConfig;
import com.ning.billing.util.notificationq.NotificationQueue;
import com.ning.billing.util.notificationq.NotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
@@ -131,7 +131,7 @@ public class Engine implements EventListener, EntitlementService {
new NotificationConfig() {
@Override
public boolean isNotificationProcessingOff() {
- return config.isEventProcessingOff();
+ return config.isNotificationProcessingOff();
}
@Override
public long getNotificationSleepTimeMs() {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
index 5107d71..e14aa78 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
@@ -19,19 +19,17 @@ package com.ning.billing.invoice.notification;
import java.util.UUID;
import org.joda.time.DateTime;
-import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.config.InvoiceConfig;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.invoice.InvoiceListener;
import com.ning.billing.invoice.api.DefaultInvoiceService;
-import com.ning.billing.util.bus.Bus;
-import com.ning.billing.util.notificationq.NotificationConfig;
-import com.ning.billing.util.notificationq.NotificationKey;
+
import com.ning.billing.util.notificationq.NotificationQueue;
import com.ning.billing.util.notificationq.NotificationQueueService;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
@@ -85,7 +83,7 @@ public class DefaultNextBillingDateNotifier implements NextBillingDateNotifier
new NotificationConfig() {
@Override
public boolean isNotificationProcessingOff() {
- return config.isEventProcessingOff();
+ return config.isNotificationProcessingOff();
}
@Override
public long getNotificationSleepTimeMs() {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
index fc58dbc..2cca322 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
@@ -63,7 +63,7 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
@Override
public long getNotificationSleepTimeMs() {throw new UnsupportedOperationException();}
@Override
- public boolean isEventProcessingOff() {throw new UnsupportedOperationException();}
+ public boolean isNotificationProcessingOff() {throw new UnsupportedOperationException();}
@Override
public int getNumberOfMonthsInFuture() {return 36;}
};
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 6e6b9b3..8c3baf3 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -79,14 +79,14 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
}
@Override
- public boolean isEventProcessingOff() {
- throw new UnsupportedOperationException();
- }
-
- @Override
public int getNumberOfMonthsInFuture() {
return 36;
}
+
+ @Override
+ public boolean isNotificationProcessingOff() {
+ throw new UnsupportedOperationException();
+ }
};
private final InvoiceGenerator generator;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index da10dab..8af2657 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -44,7 +44,7 @@ public class AccountJson {
private final String country;
private final String phone;
-
+/*
public AccountJson(Account account) {
this.acountId = account.getId().toString();
this.name = account.getName();
@@ -63,6 +63,8 @@ public class AccountJson {
this.phone = account.getPhone();
}
+*/
+
public AccountData toAccountData() {
return new AccountData() {
@Override
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index e0583e3..0496213 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -70,7 +70,7 @@ public class AccountResource {
if (account == null) {
return Response.status(Status.NOT_FOUND).build();
}
- AccountJson json = new AccountJson(account);
+ AccountJson json = null; /* new AccountJson(account); */
return Response.status(Status.OK).entity(json).build();
}
@@ -84,7 +84,7 @@ public class AccountResource {
if (account == null) {
return Response.status(Status.NOT_FOUND).build();
}
- AccountJson json = new AccountJson(account);
+ AccountJson json = null; /* new AccountJson(account); */
return Response.status(Status.OK).entity(json).build();
}
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index c014b45..e7e8b1e 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoicePaymentApi;
import com.ning.billing.invoice.model.DefaultInvoicePayment;
@@ -39,7 +40,6 @@ import com.ning.billing.payment.RetryService;
import com.ning.billing.payment.dao.PaymentDao;
import com.ning.billing.payment.provider.PaymentProviderPlugin;
import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
-import com.ning.billing.payment.setup.PaymentConfig;
public class DefaultPaymentApi implements PaymentApi {
private final PaymentProviderPluginRegistry pluginRegistry;
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
index fc9c149..bdad7c6 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPluginRegistry.java
@@ -22,7 +22,8 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.StringUtils;
import com.google.inject.Inject;
-import com.ning.billing.payment.setup.PaymentConfig;
+import com.ning.billing.config.PaymentConfig;
+
public class PaymentProviderPluginRegistry {
private final String defaultPlugin;
diff --git a/payment/src/main/java/com/ning/billing/payment/RetryService.java b/payment/src/main/java/com/ning/billing/payment/RetryService.java
index d03b241..d189159 100644
--- a/payment/src/main/java/com/ning/billing/payment/RetryService.java
+++ b/payment/src/main/java/com/ning/billing/payment/RetryService.java
@@ -26,6 +26,7 @@ import com.ning.billing.util.clock.Clock;
import org.joda.time.DateTime;
import com.google.inject.Inject;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
@@ -33,7 +34,7 @@ import com.ning.billing.payment.api.PaymentApi;
import com.ning.billing.payment.api.PaymentAttempt;
import com.ning.billing.payment.api.PaymentInfo;
import com.ning.billing.payment.api.PaymentStatus;
-import com.ning.billing.payment.setup.PaymentConfig;
+
import com.ning.billing.util.notificationq.NotificationKey;
import com.ning.billing.util.notificationq.NotificationQueue;
import com.ning.billing.util.notificationq.NotificationQueueService;
diff --git a/payment/src/main/java/com/ning/billing/payment/setup/PaymentModule.java b/payment/src/main/java/com/ning/billing/payment/setup/PaymentModule.java
index 0c769fd..de4bf3c 100644
--- a/payment/src/main/java/com/ning/billing/payment/setup/PaymentModule.java
+++ b/payment/src/main/java/com/ning/billing/payment/setup/PaymentModule.java
@@ -21,6 +21,7 @@ import java.util.Properties;
import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.AbstractModule;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.payment.RequestProcessor;
import com.ning.billing.payment.RetryService;
import com.ning.billing.payment.api.DefaultPaymentApi;
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
index 97aa31e..8faf1f3 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
@@ -20,6 +20,7 @@ import org.apache.commons.collections.MapUtils;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provider;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.mock.BrainDeadProxyFactory;
import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
index c8f79bc..b0999da 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.inject.Provider;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.MockAccountDao;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
import com.ning.billing.invoice.dao.InvoiceDao;
import com.ning.billing.invoice.dao.MockInvoiceDao;
diff --git a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
index 1379267..6d8102a 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestRetryService.java
@@ -41,6 +41,7 @@ import com.google.inject.Inject;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.glue.AccountModuleWithMocks;
import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.config.PaymentConfig;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.glue.InvoiceModuleWithMocks;
import com.ning.billing.invoice.model.RecurringInvoiceItem;
@@ -53,7 +54,6 @@ import com.ning.billing.payment.api.PaymentStatus;
import com.ning.billing.payment.dao.PaymentDao;
import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
-import com.ning.billing.payment.setup.PaymentConfig;
import com.ning.billing.payment.setup.PaymentTestModuleWithMocks;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.clock.Clock;
server/pom.xml 57(+56 -1)
diff --git a/server/pom.xml b/server/pom.xml
index 083600d..bba0dd1 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -29,10 +29,59 @@
<logback.version>1.0.1</logback.version>
<metrics.version>2.1.1</metrics.version>
<slf4j.version>1.6.4</slf4j.version>
- <skeleton.version>0.1.0</skeleton.version>
+ <skeleton.version>0.1.1-SNAPSHOT</skeleton.version>
+ <async-http-client.version>1.6.5</async-http-client.version>
</properties>
<dependencies>
+
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-deploy</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-xml</artifactId>
+ <version>${jetty.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+
+
<!-- NOT in master POM; include version as well -->
<dependency>
<groupId>org.weakref</groupId>
@@ -185,6 +234,12 @@
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning</groupId>
+ <artifactId>async-http-client</artifactId>
+ <version>${async-http-client.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
diff --git a/server/src/main/java/com/ning/billing/server/config/KillbillServerConfig.java b/server/src/main/java/com/ning/billing/server/config/KillbillServerConfig.java
index e3e1d96..65e6faa 100644
--- a/server/src/main/java/com/ning/billing/server/config/KillbillServerConfig.java
+++ b/server/src/main/java/com/ning/billing/server/config/KillbillServerConfig.java
@@ -18,4 +18,5 @@ package com.ning.billing.server.config;
public interface KillbillServerConfig
{
+
}
diff --git a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
index 451d5c3..df96364 100644
--- a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
+++ b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
@@ -15,21 +15,27 @@
*/
package com.ning.billing.server.listeners;
+import java.util.Set;
+
import com.ning.billing.beatrix.lifecycle.DefaultLifecycle;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
+import com.ning.billing.lifecycle.KillbillService;
import com.ning.billing.server.config.KillbillServerConfig;
import com.ning.billing.server.healthchecks.KillbillHealthcheck;
import com.ning.billing.server.modules.KillbillServerModule;
+import com.ning.billing.server.util.ServerUtil;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.BusService;
import com.ning.jetty.base.modules.ServerModuleBuilder;
import com.ning.jetty.core.listeners.SetupServer;
+import com.ning.jetty.jdbi.config.DaoConfig;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Injector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.management.RuntimeErrorException;
import javax.servlet.ServletContextEvent;
public class KillbillGuiceListener extends SetupServer
@@ -44,12 +50,27 @@ public class KillbillGuiceListener extends SetupServer
@Override
public void contextInitialized(ServletContextEvent event)
{
+
+
final ServerModuleBuilder builder = new ServerModuleBuilder()
.addConfig(KillbillServerConfig.class)
.addHealthCheck(KillbillHealthcheck.class)
.addJMXExport(KillbillHealthcheck.class)
.addModule(new KillbillServerModule())
.addJerseyResource("com.ning.billing.jaxrs.resources");
+/*
+ //
+ // Dynamically add all killbill configs
+ //
+ try {
+ Set<Class<?>> configs = ServerUtil.getKillbillConfig("com.ning.billing.config", "killbill-api", "com.ning.billing.config.KillbillConfig");
+ for (Class<?> cur : configs) {
+ builder.addConfig(cur);
+ }
+ } catch(ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ */
guiceModule = builder.build();
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index 8b46cb8..5f03b42 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -32,6 +32,7 @@ import com.ning.billing.payment.setup.PaymentModule;
import com.ning.billing.util.glue.BusModule;
import com.ning.billing.util.glue.CallContextModule;
import com.ning.billing.util.glue.ClockModule;
+import com.ning.billing.util.glue.FieldStoreModule;
import com.ning.billing.util.glue.NotificationQueueModule;
import com.ning.billing.util.glue.TagStoreModule;
import com.ning.jetty.jdbi.guice.providers.DBIProvider;
@@ -68,7 +69,10 @@ public class KillbillServerModule extends AbstractModule
protected void installKillbillModules()
{
- install(new BusModule());
+ install(new FieldStoreModule());
+ install(new TagStoreModule());
+ install(new CatalogModule());
+ install(new BusModule());
install(new NotificationQueueModule());
install(new CallContextModule());
install(new AccountModule());
@@ -76,8 +80,6 @@ public class KillbillServerModule extends AbstractModule
install(new EntitlementModule());
install(new AnalyticsModule());
install(new PaymentModule());
- install(new TagStoreModule());
- install(new CatalogModule());
install(new BeatrixModule());
install(new ClockModule());
}
diff --git a/server/src/main/java/com/ning/billing/server/util/ServerUtil.java b/server/src/main/java/com/ning/billing/server/util/ServerUtil.java
new file mode 100644
index 0000000..7d03a67
--- /dev/null
+++ b/server/src/main/java/com/ning/billing/server/util/ServerUtil.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2010-2011 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.server.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarFile;
+
+import com.ning.billing.server.listeners.KillbillGuiceListener;
+
+public class ServerUtil {
+
+
+ // Look a lot like the ServiceFinder for Lifecycle in util; mught want to refactor that at some point.
+ public static Set<Class<?>> getKillbillConfig(final String packageFilter, final String jarFilter, final String interfaceFilter) throws ClassNotFoundException {
+ Object[] classPaths;
+
+ final Set<Class<?>> result = new HashSet<Class<?>>();
+
+ ClassLoader classLoader = KillbillGuiceListener.class.getClassLoader();
+ try {
+ classPaths = ((java.net.URLClassLoader) classLoader).getURLs();
+ } catch(ClassCastException cce){
+ classPaths = System.getProperty("java.class.path", "").split(File.pathSeparator);
+ }
+ Enumeration<?> files = null;
+ for (int h = 0; h < classPaths.length; h++) {
+
+ JarFile module = null;
+ File classPath = new File( (URL.class).isInstance(classPaths[h]) ?
+ ((URL)classPaths[h]).getFile() : classPaths[h].toString());
+
+ if (classPath.isDirectory()) {
+
+
+ List<String> dirListing = new ArrayList<String>();
+ recursivelyListDir(dirListing, classPath, new StringBuffer() );
+ files = Collections.enumeration(dirListing);
+
+ } else if (classPath.getName().endsWith(".jar")) {
+
+
+
+ String [] jarParts = classPath.getName().split("/");
+ String jarName = jarParts[jarParts.length - 1];
+
+ System.out.println(jarName);
+ if (jarFilter != null && jarName != null && ! jarName.startsWith(jarFilter)) {
+ continue;
+ }
+ try {
+ module = new JarFile(classPath);
+
+ files = module.entries();
+
+ } catch (MalformedURLException mue){
+ throw new ClassNotFoundException("Bad classpath. Error: " + mue.getMessage());
+ } catch (IOException io){
+ throw new ClassNotFoundException("jar file '" + classPath.getName() +
+ "' could not be instantiate from file path. Error: " + io.getMessage());
+ }
+ }
+
+ while ( files != null && files.hasMoreElements() ){
+ String fileName = files.nextElement().toString();
+
+ if (fileName.endsWith(".class")){
+ String className = fileName.replaceAll("/", ".").substring(0, fileName.length() - 6);
+ if (packageFilter != null) {
+ if (!className.startsWith(packageFilter)) {
+ continue;
+ }
+ }
+ Class<?> theClass = null;
+ try {
+ theClass = Class.forName(className, false, classLoader);
+ Class<?> [] classInterfaces = getInterfaces(theClass);
+ for (int i = 0; i < classInterfaces.length; i++) {
+ String interfaceName = classInterfaces[i].getName();
+ if (!interfaceFilter.equals(interfaceName) ) {
+ continue;
+ }
+ result.add((Class<?>) theClass);
+ }
+ } catch (NoClassDefFoundError e) {
+ continue;
+ }
+ }
+ }
+ if (module != null) {
+ try {
+ module.close();
+ } catch (IOException e) {
+
+ }
+ }
+ }
+ return result;
+ }
+
+ private static void recursivelyListDir(List<String> dirListing, File dir, StringBuffer relativePath){
+ int prevLen;
+ if (dir.isDirectory()) {
+ File[] files = dir.listFiles();
+ for(int i = 0; i < files.length; i++){
+ prevLen = relativePath.length();
+ recursivelyListDir(dirListing, files[i],
+ relativePath.append(prevLen == 0 ? "" : "/" ).append( files[i].getName()));
+ relativePath.delete(prevLen, relativePath.length());
+ }
+ } else {
+ dirListing.add(relativePath.toString());
+ }
+ }
+
+ private static Class<?> [] getInterfaces(Class<?> theClass) {
+ Class<?> [] classInterfaces = theClass.getInterfaces();
+ return classInterfaces;
+ }
+}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
new file mode 100644
index 0000000..ed8269a
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2010-2011 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.jaxrs;
+
+import static org.testng.Assert.assertNotNull;
+
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import java.util.UUID;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+
+
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.server.listeners.KillbillGuiceListener;
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.Response;
+import com.ning.jetty.core.CoreConfig;
+import com.ning.jetty.core.server.HttpServer;
+
+public class TestAccount {
+
+ private static final Logger log = LoggerFactory.getLogger(TestAccount.class);
+
+ public static final String HEADER_CONTENT_TYPE = "Content-type";
+ public static final String CONTENT_TYPE = "application/json";
+
+ private ObjectMapper mapper;
+
+ private HttpServer server;
+ private AsyncHttpClient httpClient;
+ private CoreConfig config;
+
+ CoreConfig getConfig() {
+ return new CoreConfig() {
+
+ @Override
+ public boolean isSSLEnabled() {
+ return false;
+ }
+ @Override
+ public boolean isJettyStatsOn() {
+ return false;
+ }
+ @Override
+ public int getServerSslPort() {
+ return 0;
+ }
+ @Override
+ public int getServerPort() {
+ return 8080;
+ }
+ @Override
+ public String getServerHost() {
+ return "127.0.0.1";
+ }
+ @Override
+ public String getSSLkeystorePassword() {
+ return null;
+ }
+ @Override
+ public String getSSLkeystoreLocation() {
+ return null;
+ }
+ @Override
+ public int getMinThreads() {
+ return 2;
+ }
+ @Override
+ public int getMaxThreads() {
+ return 100;
+ }
+ @Override
+ public String getLogPath() {
+ return "/var/tmp/.logs";
+ }
+ };
+ }
+
+ public static void loadSystemPropertiesFromClasspath(final String resource) {
+ final URL url = TestAccount.class.getResource(resource);
+ assertNotNull(url);
+
+ try {
+ System.getProperties().load( url.openStream() );
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @BeforeClass(groups="slow")
+ public void setup() throws Exception {
+
+ loadSystemPropertiesFromClasspath("/killbill.properties");
+
+ httpClient = new AsyncHttpClient();
+ server = new HttpServer();
+ config = getConfig();
+ mapper = new ObjectMapper();
+ final Iterable<EventListener> eventListeners = new Iterable<EventListener>() {
+ @Override
+ public Iterator<EventListener> iterator() {
+ ArrayList<EventListener> array = new ArrayList<EventListener>();
+ array.add(new KillbillGuiceListener());
+ return array.iterator();
+ }
+ };
+ server.configure(config, eventListeners, new HashMap<FilterHolder, String>());
+ server.start();
+ }
+
+
+ AccountJson getAccountJson() {
+ String accountId = UUID.randomUUID().toString();
+ String name = "yoyo bozo2";
+ int length = 4;
+ String externalKey = "xdfsdretuq";
+ String email = "yoyo@gmail.com";
+ int billCycleDay = 12;
+ String currency = "USD";
+ String paymentProvider = "paypal";
+ String timeZone = "UTC";
+ String address1 = "12 rue des ecoles";
+ String address2 = "Poitier";
+ String company = "Renault";
+ String state = "Poitou";
+ String country = "France";
+ String phone = "81 53 26 56";
+
+ AccountJson accountJson = new AccountJson(accountId, name, length, externalKey, email, billCycleDay, currency, paymentProvider, timeZone, address1, address2, company, state, country, phone);
+ return accountJson;
+ }
+
+ @Test(groups="slow")
+ public void testFoo() throws Exception {
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ AccountJson accountData = getAccountJson();
+
+ ObjectWriter objWriter = mapper.writer();
+
+ Writer writer = new StringWriter();
+ objWriter.writeValue(writer, accountData);
+ String baseJson = writer.toString();
+
+ log.info(baseJson);
+
+ AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
+
+ log.info(objFromJson.toString());
+ }
+
+
+ @Test(groups="slow")
+ public void testAccountOk() throws Exception {
+
+ final String accountPathPrefix = "/1.0/account";
+
+ AccountJson accountData = getAccountJson();
+ ObjectWriter objWriter = mapper.writer();
+
+ Writer writer = new StringWriter();
+ objWriter.writeValue(writer, accountData);
+ String baseJson = writer.toString();
+
+ try {
+ Thread.sleep(100000);
+ } catch (Exception e) {}
+
+ httpClient.preparePost(String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), accountPathPrefix))
+ .addHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE)
+ .setBody(baseJson)
+ .execute(new AsyncCompletionHandler<Integer>() {
+
+ @Override
+ public Integer onCompleted(Response response)
+ throws Exception {
+
+ int statusCode = response.getStatusCode();
+ URI uri = response.getUri();
+ return statusCode;
+ }
+ });
+ }
+}
server/src/test/resources/catalog-weapons-xml 641(+641 -0)
diff --git a/server/src/test/resources/catalog-weapons-xml b/server/src/test/resources/catalog-weapons-xml
new file mode 100644
index 0000000..8a97d57
--- /dev/null
+++ b/server/src/test/resources/catalog-weapons-xml
@@ -0,0 +1,641 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ ~ Copyright 2010-2011 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.
+ -->
+
+<!--
+Use cases covered so far:
+ Tiered Product (Pistol/Shotgun/Assault-Rifle)
+ Multiple changeEvent plan policies
+ Multiple PlanAlignment (see below, trial add-on alignments and rescue discount package)
+ Product transition rules
+ Add on (Scopes, Hoster)
+ Multi-pack addon (Extra-Ammo)
+ Addon Trial aligned to base plan (holster-monthly-regular)
+ Addon Trial aligned to creation (holster-monthly-special)
+ Rescue discount package (assault-rifle-annual-rescue)
+ Plan phase with a reccurring and a one off (refurbish-maintenance)
+ Phan with more than 2 phase (gunclub discount plans)
+
+Use Cases to do:
+ Tiered Add On
+ Riskfree period
+
+
+
+ -->
+<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
+
+ <effectiveDate>2011-01-01T00:00:00+00:00</effectiveDate>
+ <catalogName>Firearms</catalogName>
+
+ <currencies>
+ <currency>USD</currency>
+ <currency>EUR</currency>
+ <currency>GBP</currency>
+ </currencies>
+
+ <products>
+ <product name="Pistol">
+ <category>BASE</category>
+ </product>
+ <product name="Shotgun">
+ <category>BASE</category>
+ <available>
+ <addonProduct>Telescopic-Scope</addonProduct>
+ <addonProduct>Laser-Scope</addonProduct>
+ </available>
+ </product>
+ <product name="Assault-Rifle">
+ <category>BASE</category>
+ <included>
+ <addonProduct>Telescopic-Scope</addonProduct>
+ </included>
+ <available>
+ <addonProduct>Laser-Scope</addonProduct>
+ </available>
+ </product>
+ <product name="Telescopic-Scope">
+ <category>ADD_ON</category>
+ </product>
+ <product name="Laser-Scope">
+ <category>ADD_ON</category>
+ </product>
+ <product name="Holster">
+ <category>ADD_ON</category>
+ </product>
+ <product name="Extra-Ammo">
+ <category>ADD_ON</category>
+ </product>
+ <product name="Refurbish-Maintenance">
+ <category>ADD_ON</category>
+ </product>
+ </products>
+
+ <rules>
+ <changePolicy>
+ <changePolicyCase>
+ <phaseType>TRIAL</phaseType>
+ <policy>IMMEDIATE</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <toProduct>Assault-Rifle</toProduct>
+ <policy>IMMEDIATE</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <fromProduct>Pistol</fromProduct>
+ <toProduct>Shotgun</toProduct>
+ <policy>IMMEDIATE</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <toPriceList>rescue</toPriceList>
+ <policy>END_OF_TERM</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <fromBillingPeriod>MONTHLY</fromBillingPeriod>
+ <toBillingPeriod>ANNUAL</toBillingPeriod>
+ <policy>IMMEDIATE</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <fromBillingPeriod>ANNUAL</fromBillingPeriod>
+ <toBillingPeriod>MONTHLY</toBillingPeriod>
+ <policy>END_OF_TERM</policy>
+ </changePolicyCase>
+ <changePolicyCase>
+ <policy>END_OF_TERM</policy>
+ </changePolicyCase>
+ </changePolicy>
+ <changeAlignment>
+ <changeAlignmentCase>
+ <toPriceList>rescue</toPriceList>
+ <alignment>CHANGE_OF_PLAN</alignment>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
+ <fromPriceList>rescue</fromPriceList>
+ <toPriceList>rescue</toPriceList>
+ <alignment>CHANGE_OF_PRICELIST</alignment>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </changeAlignmentCase>
+ </changeAlignment>
+ <cancelPolicy>
+ <cancelPolicyCase>
+ <phaseType>TRIAL</phaseType>
+ <policy>IMMEDIATE</policy>
+ </cancelPolicyCase>
+ <cancelPolicyCase>
+ <policy>END_OF_TERM</policy>
+ </cancelPolicyCase>
+ </cancelPolicy>
+ <createAlignment>
+ <createAlignmentCase>
+ <product>Laser-Scope</product>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </createAlignmentCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ </createAlignment>
+ <billingAlignment>
+ <billingAlignmentCase>
+ <productCategory>ADD_ON</productCategory>
+ <alignment>BUNDLE</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <alignment>SUBSCRIPTION</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <alignment>ACCOUNT</alignment>
+ </billingAlignmentCase>
+ </billingAlignment>
+ <priceList>
+ <priceListCase>
+ <fromPriceList>rescue</fromPriceList>
+ <toPriceList>DEFAULT</toPriceList>
+ </priceListCase>
+ </priceList>
+ </rules>
+
+ <plans>
+ <plan name="pistol-monthly">
+ <product>Pistol</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice> <!-- empty price implies $0 -->
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>GBP</currency><value>29.95</value></price>
+ <price><currency>EUR</currency><value>29.95</value></price>
+ <price><currency>USD</currency><value>29.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="shotgun-monthly">
+ <product>Shotgun</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice></fixedPrice>
+ <!-- no price implies $0 -->
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ <number>-1</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>249.95</value></price>
+ <price><currency>EUR</currency><value>149.95</value></price>
+ <price><currency>GBP</currency><value>169.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="assault-rifle-monthly">
+ <product>Assault-Rifle</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>599.95</value></price>
+ <price><currency>EUR</currency><value>349.95</value></price>
+ <price><currency>GBP</currency><value>399.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="pistol-annual">
+ <product>Pistol</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>199.95</value></price>
+ <price><currency>EUR</currency><value>199.95</value></price>
+ <price><currency>GBP</currency><value>199.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="shotgun-annual">
+ <product>Shotgun</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>2399.95</value></price>
+ <price><currency>EUR</currency><value>1499.95</value></price>
+ <price><currency>GBP</currency><value>1699.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="assault-rifle-annual">
+ <product>Assault-Rifle</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>5999.95</value></price>
+ <price><currency>EUR</currency><value>3499.95</value></price>
+ <price><currency>GBP</currency><value>3999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="pistol-annual-gunclub-discount">
+ <product>Pistol</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>6</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>9.95</value></price>
+ <price><currency>EUR</currency><value>9.95</value></price>
+ <price><currency>GBP</currency><value>9.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>199.95</value></price>
+ <price><currency>EUR</currency><value>199.95</value></price>
+ <price><currency>GBP</currency><value>199.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="shotgun-annual-gunclub-discount">
+ <product>Shotgun</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>6</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>19.95</value></price>
+ <price><currency>EUR</currency><value>49.95</value></price>
+ <price><currency>GBP</currency><value>69.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>2399.95</value></price>
+ <price><currency>EUR</currency><value>1499.95</value></price>
+ <price><currency>GBP</currency><value>1699.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="assault-rifle-annual-gunclub-discount">
+ <product>Assault-Rifle</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>6</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>99.95</value></price>
+ <price><currency>EUR</currency><value>99.95</value></price>
+ <price><currency>GBP</currency><value>99.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>5999.95</value></price>
+ <price><currency>EUR</currency><value>3499.95</value></price>
+ <price><currency>GBP</currency><value>3999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="laser-scope-monthly">
+ <product>Laser-Scope</product>
+ <initialPhases>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>1</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>999.95</value></price>
+ <price><currency>EUR</currency><value>499.95</value></price>
+ <price><currency>GBP</currency><value>999.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>1999.95</value></price>
+ <price><currency>EUR</currency><value>1499.95</value></price>
+ <price><currency>GBP</currency><value>1999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="telescopic-scope-monthly">
+ <product>Telescopic-Scope</product>
+ <initialPhases>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>1</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>399.95</value></price>
+ <price><currency>EUR</currency><value>299.95</value></price>
+ <price><currency>GBP</currency><value>399.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>999.95</value></price>
+ <price><currency>EUR</currency><value>499.95</value></price>
+ <price><currency>GBP</currency><value>999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="extra-ammo-monthly">
+ <product>Extra-Ammo</product>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>999.95</value></price>
+ <price><currency>EUR</currency><value>499.95</value></price>
+ <price><currency>GBP</currency><value>999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ <plansAllowedInBundle>-1</plansAllowedInBundle> <!-- arbitrary number of these (multipack) -->
+ </plan>
+ <plan name="holster-monthly-regular">
+ <product>Holster</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>199.95</value></price>
+ <price><currency>EUR</currency><value>199.95</value></price>
+ <price><currency>GBP</currency><value>199.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="holster-monthly-special">
+ <product>Holster</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice>
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>199.95</value></price>
+ <price><currency>EUR</currency><value>199.95</value></price>
+ <price><currency>GBP</currency><value>199.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="assault-rifle-annual-rescue">
+ <product>Assault-Rifle</product>
+ <initialPhases>
+ <phase type="DISCOUNT">
+ <duration>
+ <unit>YEARS</unit>
+ <number>1</number>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>5999.95</value></price>
+ <price><currency>EUR</currency><value>3499.95</value></price>
+ <price><currency>GBP</currency><value>3999.95</value></price>
+ </recurringPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>5999.95</value></price>
+ <price><currency>EUR</currency><value>3499.95</value></price>
+ <price><currency>GBP</currency><value>3999.95</value></price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
+ <plan name="refurbish-maintenance">
+ <product>Refurbish-Maintenance</product>
+ <finalPhase type="FIXEDTERM">
+ <duration>
+ <unit>MONTHS</unit>
+ <number>12</number>
+ </duration>
+ <billingPeriod>MONTHLY</billingPeriod>
+ <recurringPrice>
+ <price><currency>USD</currency><value>199.95</value></price>
+ <price><currency>EUR</currency><value>199.95</value></price>
+ <price><currency>GBP</currency><value>199.95</value></price>
+ </recurringPrice>
+ <fixedPrice>
+ <price><currency>USD</currency><value>599.95</value></price>
+ <price><currency>EUR</currency><value>599.95</value></price>
+ <price><currency>GBP</currency><value>599.95</value></price>
+ </fixedPrice>
+ </finalPhase>
+ </plan>
+ </plans>
+ <priceLists>
+ <defaultPriceList name="DEFAULT">
+ <plans>
+ <plan>pistol-monthly</plan>
+ <plan>shotgun-monthly</plan>
+ <plan>assault-rifle-monthly</plan>
+ <plan>pistol-annual</plan>
+ <plan>shotgun-annual</plan>
+ <plan>assault-rifle-annual</plan>
+ <plan>laser-scope-monthly</plan>
+ <plan>telescopic-scope-monthly</plan>
+ <plan>extra-ammo-monthly</plan>
+ <plan>holster-monthly-regular</plan>
+ <plan>refurbish-maintenance</plan>
+ </plans>
+ </defaultPriceList>
+ <childPriceList name="gunclubDiscount">
+ <plans>
+ <plan>pistol-monthly</plan>
+ <plan>shotgun-monthly</plan>
+ <plan>assault-rifle-monthly</plan>
+ <plan>pistol-annual-gunclub-discount</plan>
+ <plan>shotgun-annual-gunclub-discount</plan>
+ <plan>assault-rifle-annual-gunclub-discount</plan>
+ <plan>holster-monthly-special</plan>
+ </plans>
+ </childPriceList>
+ <childPriceList name="rescue">
+ <plans>
+ <plan>assault-rifle-annual-rescue</plan>
+ </plans>
+ </childPriceList>
+ </priceLists>
+
+</catalog>
diff --git a/server/src/test/resources/killbill.properties b/server/src/test/resources/killbill.properties
new file mode 100644
index 0000000..251d154
--- /dev/null
+++ b/server/src/test/resources/killbill.properties
@@ -0,0 +1,11 @@
+com.ning.jetty.jdbi.url=jdbc:mysql://127.0.0.1:3306/killbill
+
+killbill.catalog.uri=file:src/test/resources/catalog-weapons.xml
+
+killbill.payment.provider.default=zuora-shadow
+killbill.payment.engine.events.off=false
+killbill.payment.retry.days=8,8,8
+
+user.timezone=UTC
+
+
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
index c0c88fe..e12b8a7 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
@@ -24,6 +24,7 @@ import org.joda.time.DateTime;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
import com.ning.billing.util.notificationq.dao.NotificationSqlDao;
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
index 3b96ee4..bf8652c 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
@@ -18,6 +18,7 @@ package com.ning.billing.util.notificationq;
import org.skife.jdbi.v2.IDBI;
import com.google.inject.Inject;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.clock.Clock;
public class DefaultNotificationQueueService extends NotificationQueueServiceBase {
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
index a4f4c97..eb3f269 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
@@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.Hostname;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
index 4d56b03..828608a 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
@@ -18,6 +18,8 @@ package com.ning.billing.util.notificationq;
import org.joda.time.DateTime;
+import com.ning.billing.config.NotificationConfig;
+
public interface NotificationQueueService {
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
index 56423a0..90c27b0 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
import com.google.inject.Inject;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.clock.Clock;
public abstract class NotificationQueueServiceBase implements NotificationQueueService {
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
index 1c40988..ae66819 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
@@ -25,6 +25,7 @@ import java.util.TreeSet;
import org.joda.time.DateTime;
import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.notificationq.NotificationLifecycle.NotificationLifecycleState;
import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueueService.java b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueueService.java
index e9ce90e..9af43c1 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueueService.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueueService.java
@@ -17,6 +17,7 @@
package com.ning.billing.util.notificationq;
import com.google.inject.Inject;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.util.clock.Clock;
public class MockNotificationQueueService extends NotificationQueueServiceBase {
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
index fefbcdb..e2718a9 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
@@ -50,6 +50,7 @@ import com.google.common.collect.Collections2;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.name.Names;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;