killbill-memoizeit

Change Entitlement API to use exceptions instaed of null values Remove

5/8/2012 11:41:34 PM

Changes

overdue/pom.xml 7(+0 -7)

Details

diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
index 0dec9b9..69eb454 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
@@ -29,7 +29,7 @@ public interface ChargeThruApi {
      * @param subscriptionId
      * @return UUID of
      */
-    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId);
+    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) throws EntitlementBillingApiException;
     
     /**
      * Sets the charged through date for the subscription with that Id.
@@ -39,16 +39,4 @@ public interface ChargeThruApi {
      * @param context
      */
     public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context);
-
-    /**
-     * Sets the charged through date for the subscription with that Id. Within the context of a SQL Transaction
-     * 
-     * @param transactionalDao
-     * @param subscriptionId
-     * @param ctd
-     * @param context
-     */
-    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
-                                                     DateTime ctd, CallContext context);
-
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index 0e74f86..27a741d 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -38,7 +38,7 @@ public interface EntitlementUserApi {
 
     public List<Subscription> getSubscriptionsForKey(String bundleKey);
     
-    public Subscription getBaseSubscription(UUID bundleId);
+    public Subscription getBaseSubscription(UUID bundleId) throws EntitlementUserApiException;
 
     public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey, CallContext context)
         throws EntitlementUserApiException;
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index f6856eb..f31ece4 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -59,6 +59,7 @@ public enum ErrorCode {
     ENT_GET_INVALID_BUNDLE_ID(1081, "Could not find a bundle matching id %s"),
     ENT_INVALID_SUBSCRIPTION_ID(1082, "Unknown subscription %s"),
     ENT_GET_INVALID_BUNDLE_KEY(1083, "Could not find a bundle matching key %s"),
+    ENT_GET_NO_SUCH_BASE_SUBSCRIPTION(1084, "Could not base subscription for bundle %s"),
 
     /* Repair */
     ENT_REPAIR_INVALID_DELETE_SET(1091, "Event %s is not deleted for subscription %s but prior events were"),
@@ -80,6 +81,8 @@ public enum ErrorCode {
     
     ENT_BUNDLE_IS_OVERDUE_BLOCKED(1090, "Changes to this bundle are blocked by overdue enforcement (%s :  %s)"),
     ENT_ACCOUNT_IS_OVERDUE_BLOCKED(1091, "Changes to this account are blocked by overdue enforcement (%s)"),
+ 
+    
     /*
     *
     * Range 2000 : CATALOG
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
index 4399176..74764b3 100644
--- a/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueUserApi.java
@@ -17,13 +17,14 @@
 package com.ning.billing.overdue;
 
 import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.overdue.config.api.BillingState;
 import com.ning.billing.overdue.config.api.OverdueError;
 
 public interface OverdueUserApi {
 
-    public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException;
+    public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException, EntitlementUserApiException;
 
     public <T extends Blockable> void setOverrideBillingStateForAccount(T overdueable, BillingState<T> state) throws OverdueError;
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java
index 7bde4a2..1c3cfc5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultChargeThruApi.java
@@ -16,11 +16,9 @@ w * Copyright 2010-2011 Ning, Inc.
 
 package com.ning.billing.entitlement.api.billing;
 
-import java.util.Date;
 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;
 
@@ -30,19 +28,16 @@ import com.ning.billing.entitlement.api.SubscriptionFactory;
 import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.entitlement.engine.dao.SubscriptionSqlDao;
-import com.ning.billing.util.ChangeType;
-import com.ning.billing.util.audit.dao.AuditSqlDao;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextFactory;
 
 public class DefaultChargeThruApi implements ChargeThruApi {
-	private static final Logger log = LoggerFactory.getLogger(DefaultChargeThruApi.class);
+
+    private static final Logger log = LoggerFactory.getLogger(DefaultChargeThruApi.class);
 
     private final EntitlementDao entitlementDao;
     private final SubscriptionFactory subscriptionFactory;
   
-    private static final String SUBSCRIPTION_TABLE_NAME = "subscriptions";
 
     @Inject
     public DefaultChargeThruApi(final CallContextFactory factory, final SubscriptionFactory subscriptionFactory, final EntitlementDao dao, final AccountUserApi accountApi) {
@@ -65,23 +60,4 @@ public class DefaultChargeThruApi implements ChargeThruApi {
             .setPaidThroughDate(subscription.getPaidThroughDate());
         entitlementDao.updateChargedThroughDate(new SubscriptionData(builder), context);
     }
-
-    @Override
-    public void setChargedThroughDateFromTransaction(final Transmogrifier transactionalDao, final UUID subscriptionId,
-                                                     final DateTime ctd, final CallContext context) {
-        SubscriptionSqlDao subscriptionSqlDao = transactionalDao.become(SubscriptionSqlDao.class);
-        SubscriptionData subscription = (SubscriptionData) subscriptionSqlDao.getSubscriptionFromId(subscriptionId.toString());
-
-        if (subscription == null) {
-            log.warn("Subscription not found when setting CTD.");
-        } else {
-            DateTime chargedThroughDate = subscription.getChargedThroughDate();
-            if (chargedThroughDate == null || chargedThroughDate.isBefore(ctd)) {
-                subscriptionSqlDao.updateChargedThroughDate(subscriptionId.toString(),
-                        ctd.toDate(), context);
-                AuditSqlDao auditSqlDao = transactionalDao.become(AuditSqlDao.class);
-                auditSqlDao.insertAuditFromTransaction(SUBSCRIPTION_TABLE_NAME, subscriptionId.toString(), ChangeType.UPDATE, context);
-            }
-        }
-    }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index 115c60b..ce18d37 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -61,19 +61,32 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
         this.subscriptionFactory = subscriptionFactory;
     }
 
+    
     @Override
-    public SubscriptionBundle getBundleFromId(UUID id) {
-        return dao.getSubscriptionBundleFromId(id);
+    public SubscriptionBundle getBundleFromId(UUID id) throws EntitlementUserApiException {
+        SubscriptionBundle result = dao.getSubscriptionBundleFromId(id);
+        if (result == null) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_GET_INVALID_BUNDLE_ID, id.toString());
+        }
+        return result;
     }
 
     @Override
-    public Subscription getSubscriptionFromId(UUID id) {
-        return dao.getSubscriptionFromId(subscriptionFactory, id);
+    public Subscription getSubscriptionFromId(UUID id) throws EntitlementUserApiException {
+        Subscription result = dao.getSubscriptionFromId(subscriptionFactory, id);
+        if (result == null) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_SUBSCRIPTION_ID, id);
+        }
+        return result;
     }
 
     @Override
-    public SubscriptionBundle getBundleForKey(String bundleKey) {
-        return dao.getSubscriptionBundleFromKey(bundleKey);
+    public SubscriptionBundle getBundleForKey(String bundleKey) throws EntitlementUserApiException {
+        SubscriptionBundle result =  dao.getSubscriptionBundleFromKey(bundleKey);
+        if (result == null) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_GET_INVALID_BUNDLE_KEY, bundleKey);
+        }
+        return result;
     }
 
     @Override
@@ -92,8 +105,12 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
     }
 
     @Override
-    public Subscription getBaseSubscription(UUID bundleId) {
-        return dao.getBaseSubscription(subscriptionFactory, bundleId);
+    public Subscription getBaseSubscription(UUID bundleId) throws EntitlementUserApiException {
+        Subscription result =  dao.getBaseSubscription(subscriptionFactory, bundleId);
+        if (result == null) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_GET_NO_SUCH_BASE_SUBSCRIPTION, bundleId);
+        }
+        return result;
     }
     
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index 0b064bb..fb30979 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -153,11 +153,6 @@ public class DefaultInvoiceDao implements InvoiceDao {
     @Override
     public void create(final Invoice invoice, final CallContext context) {
         
-        final InvoiceCreationEvent event = new DefaultInvoiceCreationEvent(invoice.getId(), invoice.getAccountId(),
-                invoice.getBalance(), invoice.getCurrency(),
-                invoice.getInvoiceDate(),
-                context.getUserToken());
-
         invoiceSqlDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
             @Override
             public Void inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
@@ -178,9 +173,6 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     FixedPriceInvoiceItemSqlDao fixedPriceInvoiceItemDao = transactional.become(FixedPriceInvoiceItemSqlDao.class);
                     fixedPriceInvoiceItemDao.batchCreateFromTransaction(fixedPriceInvoiceItems, context);
 
-                    setChargedThroughDates(transactional, fixedPriceInvoiceItems, recurringInvoiceItems, context);
-
-                    // STEPH Why do we need that? Are the payments not always null at this point?
                     List<InvoicePayment> invoicePayments = invoice.getPayments();
                     InvoicePaymentSqlDao invoicePaymentSqlDao = transactional.become(InvoicePaymentSqlDao.class);
                     invoicePaymentSqlDao.batchCreateFromTransaction(invoicePayments, context);
@@ -190,18 +182,10 @@ public class DefaultInvoiceDao implements InvoiceDao {
                     auditSqlDao.insertAuditFromTransaction("recurring_invoice_items", getIdsFromInvoiceItems(recurringInvoiceItems), ChangeType.INSERT, context);
                     auditSqlDao.insertAuditFromTransaction("fixed_invoice_items", getIdsFromInvoiceItems(fixedPriceInvoiceItems), ChangeType.INSERT, context);
                     auditSqlDao.insertAuditFromTransaction("invoice_payments", getIdsFromInvoicePayments(invoicePayments), ChangeType.INSERT, context);
-
-                }
-                try {
-                    eventBus.postFromTransaction(event, transactional);
-                } catch (EventBusException e) {
-                    log.warn("Failed to post invoice event for invoiceId " + invoice.getId(), e);
                 }
                 return null;
             }
         });
-
-
     }
 
     private List<String> getIdsFromInvoiceItems(List<InvoiceItem> invoiceItems) {
@@ -377,34 +361,4 @@ public class DefaultInvoiceDao implements InvoiceDao {
             }
         }
     }
-    
-    private void setChargedThroughDates(final InvoiceSqlDao dao, final Collection<InvoiceItem> fixedPriceItems,
-                                        final Collection<InvoiceItem> recurringItems, CallContext context) {
-        Map<UUID, DateTime> chargeThroughDates = new HashMap<UUID, DateTime>();
-        addInvoiceItemsToChargeThroughDates(chargeThroughDates, fixedPriceItems);
-        addInvoiceItemsToChargeThroughDates(chargeThroughDates, recurringItems);
-
-        for (UUID subscriptionId : chargeThroughDates.keySet()) {
-            if(subscriptionId != null) {
-                DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
-                log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
-                billingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
-            }
-        }
-    }
-
-    private void addInvoiceItemsToChargeThroughDates(Map<UUID, DateTime> chargeThroughDates, Collection<InvoiceItem> items) {
-        for (InvoiceItem item : items) {
-            UUID subscriptionId = item.getSubscriptionId();
-            DateTime endDate = item.getEndDate();
-
-            if (chargeThroughDates.containsKey(subscriptionId)) {
-                if (chargeThroughDates.get(subscriptionId).isBefore(endDate)) {
-                    chargeThroughDates.put(subscriptionId, endDate);
-                }
-            } else {
-                chargeThroughDates.put(subscriptionId, endDate);
-            }
-        }
-    }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
index 53093a2..32d444d 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -17,7 +17,9 @@
 package com.ning.billing.invoice;
 
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.SortedSet;
 import java.util.UUID;
 
@@ -32,15 +34,20 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
 import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceCreationEvent;
 import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.user.DefaultEmptyInvoiceEvent;
+import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.model.BillingEventSet;
+import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.Bus.EventBusException;
@@ -53,7 +60,7 @@ import com.ning.billing.util.globallocker.GlobalLocker.LockerService;
 import com.ning.billing.util.globallocker.LockFailedException;
 
 public class InvoiceDispatcher {
-	private final static Logger log = LoggerFactory.getLogger(InvoiceDispatcher.class);
+    private final static Logger log = LoggerFactory.getLogger(InvoiceDispatcher.class);
     private final static int NB_LOCK_TRY = 5;
 
     private final InvoiceGenerator generator;
@@ -69,12 +76,12 @@ public class InvoiceDispatcher {
 
     @Inject
     public InvoiceDispatcher(final InvoiceGenerator generator, final AccountUserApi accountUserApi,
-                             final BillingApi billingApi,
-                             final InvoiceDao invoiceDao,
-                             final InvoiceNotifier invoiceNotifier,
-                             final GlobalLocker locker,
-                             final Bus eventBus,
-                             final Clock clock) {
+            final BillingApi billingApi,
+            final InvoiceDao invoiceDao,
+            final InvoiceNotifier invoiceNotifier,
+            final GlobalLocker locker,
+            final Bus eventBus,
+            final Clock clock) {
         this.generator = generator;
         this.billingApi = billingApi;
         this.accountUserApi = accountUserApi;
@@ -89,7 +96,7 @@ public class InvoiceDispatcher {
     }
 
     public void processSubscription(final SubscriptionEvent transition,
-                                    final CallContext context) throws InvoiceApiException {
+            final CallContext context) throws InvoiceApiException {
         UUID subscriptionId = transition.getSubscriptionId();
         DateTime targetDate = transition.getEffectiveTransitionTime();
         log.info("Got subscription transition from InvoiceListener. id: " + subscriptionId.toString() + "; targetDate: " + targetDate.toString());
@@ -98,25 +105,24 @@ public class InvoiceDispatcher {
     }
 
     public void processSubscription(final UUID subscriptionId, final DateTime targetDate,
-                                    final CallContext context) throws InvoiceApiException {
-        if (subscriptionId == null) {
-            log.error("Failed handling entitlement change.", new InvoiceApiException(ErrorCode.INVOICE_INVALID_TRANSITION));
-            return;
-        }
-
-        UUID accountId = billingApi.getAccountIdFromSubscriptionId(subscriptionId);
-        if (accountId == null) {
+            final CallContext context) throws InvoiceApiException {
+        try {
+            if (subscriptionId == null) {
+                log.error("Failed handling entitlement change.", new InvoiceApiException(ErrorCode.INVOICE_INVALID_TRANSITION));
+                return;
+            }
+            UUID accountId = billingApi.getAccountIdFromSubscriptionId(subscriptionId);
+            processAccount(accountId, targetDate, false, context);
+        } catch (EntitlementBillingApiException e) {
             log.error("Failed handling entitlement change.",
                     new InvoiceApiException(ErrorCode.INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID, subscriptionId.toString()));
-            return;
         }
-
-        processAccount(accountId, targetDate, false, context);
+        return;
     }
-    
+
     public Invoice processAccount(final UUID accountId, final DateTime targetDate,
-                                  final boolean dryRun, final CallContext context) throws InvoiceApiException {
-		GlobalLock lock = null;
+            final boolean dryRun, final CallContext context) throws InvoiceApiException {
+        GlobalLock lock = null;
         try {
             lock = locker.lockWithNumberOfTries(LockerService.INVOICE, accountId.toString(), NB_LOCK_TRY);
 
@@ -134,15 +140,7 @@ public class InvoiceDispatcher {
         return null;
     }
 
-    private void postEmptyInvoiceEvent(final UUID accountId, final UUID userToken) {
-        try {
-            BusEvent event = new DefaultEmptyInvoiceEvent(accountId, clock.getUTCNow(), userToken);
-            eventBus.post(event);
-        } catch (EventBusException e){
-            log.error("Failed to post DefaultEmptyInvoiceNotification event for account {} ", accountId, e);
-        }
-    }
-
+   
     private Invoice processAccountWithLock(final UUID accountId, final DateTime targetDate,
             final boolean dryRun, final CallContext context) throws InvoiceApiException {
         try {
@@ -159,7 +157,8 @@ public class InvoiceDispatcher {
                 log.info("Generated null invoice.");
                 outputDebugData(events, invoices);
                 if (!dryRun) {
-                    postEmptyInvoiceEvent(accountId, context.getUserToken());
+                    BusEvent event = new DefaultEmptyInvoiceEvent(accountId, clock.getUTCNow(), context.getUserToken());
+                    postEvent(event, accountId);
                 }
             } else {
                 log.info("Generated invoice {} with {} items.", invoice.getId().toString(), invoice.getNumberOfItems());
@@ -172,6 +171,17 @@ public class InvoiceDispatcher {
                 outputDebugData(events, invoices);
                 if (!dryRun) {
                     invoiceDao.create(invoice, context);
+
+                    List<InvoiceItem> fixedPriceInvoiceItems = invoice.getInvoiceItems(FixedPriceInvoiceItem.class);
+                    List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
+                    setChargedThroughDates(fixedPriceInvoiceItems, recurringInvoiceItems, context);
+
+                    final InvoiceCreationEvent event = new DefaultInvoiceCreationEvent(invoice.getId(), invoice.getAccountId(),
+                            invoice.getBalance(), invoice.getCurrency(),
+                            invoice.getInvoiceDate(),
+                            context.getUserToken());
+
+                    postEvent(event, accountId);
                 }
             }
 
@@ -186,6 +196,47 @@ public class InvoiceDispatcher {
         }
     }
 
+    private void setChargedThroughDates(final Collection<InvoiceItem> fixedPriceItems,
+            final Collection<InvoiceItem> recurringItems, CallContext context) {
+
+        Map<UUID, DateTime> chargeThroughDates = new HashMap<UUID, DateTime>();
+        addInvoiceItemsToChargeThroughDates(chargeThroughDates, fixedPriceItems);
+        addInvoiceItemsToChargeThroughDates(chargeThroughDates, recurringItems);
+
+        for (UUID subscriptionId : chargeThroughDates.keySet()) {
+            if(subscriptionId != null) {
+                DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
+                log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
+                billingApi.setChargedThroughDate(subscriptionId, chargeThroughDate, context);
+            }
+        }
+    }
+    
+    private void postEvent(final BusEvent event, final UUID accountId) {
+        try {
+            eventBus.post(event);
+        } catch (EventBusException e){
+            log.error(String.format("Failed to post event {} for account {} ", event.getBusEventType(), accountId), e);
+        }
+    }
+
+
+    private void addInvoiceItemsToChargeThroughDates(Map<UUID, DateTime> chargeThroughDates, Collection<InvoiceItem> items) {
+        for (InvoiceItem item : items) {
+            UUID subscriptionId = item.getSubscriptionId();
+            DateTime endDate = item.getEndDate();
+
+            if (chargeThroughDates.containsKey(subscriptionId)) {
+                if (chargeThroughDates.get(subscriptionId).isBefore(endDate)) {
+                    chargeThroughDates.put(subscriptionId, endDate);
+                }
+            } else {
+                chargeThroughDates.put(subscriptionId, endDate);
+            }
+        }
+    }
+
+
     private void outputDebugData(Collection<BillingEvent> events, Collection<Invoice> invoices) {
         if (VERBOSE_OUTPUT) {
             log.info("Events");
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index 5d7d14f..a7b0f09 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -132,7 +132,7 @@ public class TestDefaultInvoiceMigrationApi extends InvoicingTestBase {
 
 		busService.getBus().start();
 
-        ((ZombieControl)billingApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
+        ((ZombieControl)billingApi).addResult("setChargedThroughDate", BrainDeadProxyFactory.ZOMBIE_VOID);
 		migrationInvoiceId = createAndCheckMigrationInvoice();
 		regularInvoiceId = generateRegularInvoice();
 
@@ -189,11 +189,10 @@ public class TestDefaultInvoiceMigrationApi extends InvoicingTestBase {
                 fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
                 BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
 
-		BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
-        ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
+		((ZombieControl)billingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
 
         InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
-		InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, entitlementBillingApi,
+		InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, billingApi,
                                                              invoiceDao, invoiceNotifier, locker, busService.getBus(), clock);
 
         CallContext context = new DefaultCallContextFactory(clock).createCallContext("Migration test", CallOrigin.TEST, UserType.TEST);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index e591dfa..26403d0 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -115,7 +115,7 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
         context = new DefaultCallContextFactory(clock).createCallContext("Miracle Max", CallOrigin.TEST, UserType.TEST);
 
 		busService.getBus().start();
-		((ZombieControl)billingApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
+		((ZombieControl)billingApi).addResult("setChargedThroughDate", BrainDeadProxyFactory.ZOMBIE_VOID);
 	}
 
 	@AfterClass(alwaysRun = true)
@@ -155,13 +155,12 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
                 fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
                 BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
 
-		BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
-		((ZombieControl) entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
+		((ZombieControl) billingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
 
 		DateTime target = new DateTime();
 
         InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
-		InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, entitlementBillingApi, invoiceDao,
+		InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, billingApi, invoiceDao,
                                                              invoiceNotifier, locker, busService.getBus(), clock);
 
 		Invoice invoice = dispatcher.processAccount(accountId, target, true, context);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index aeb3f7a..67c5b5c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -92,7 +92,6 @@ public class SubscriptionResource implements BaseJaxrsResource {
         try {
             UUID uuid = UUID.fromString(subscriptionId);
             Subscription subscription = entitlementApi.getSubscriptionFromId(uuid);
-
             SubscriptionJsonNoEvents json = new SubscriptionJsonNoEvents(subscription);
             return Response.status(Status.OK).entity(json).build();
         } catch (EntitlementUserApiException e) {
@@ -101,7 +100,6 @@ public class SubscriptionResource implements BaseJaxrsResource {
             } else {
                 throw e;
             }
-
         }
     }
   
@@ -185,14 +183,13 @@ public class SubscriptionResource implements BaseJaxrsResource {
                     return operationResponse;
                 }
                 try {
-                return getSubscription(subscriptionId);
+                    return getSubscription(subscriptionId);
                 } catch (EntitlementUserApiException e) {
                     if (e.getCode() == ErrorCode.ENT_GET_INVALID_BUNDLE_ID.getCode()) {
                         return Response.status(Status.NO_CONTENT).build();
                     } else {
                         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
                     }
-
                 }
             }
         };
@@ -333,13 +330,10 @@ public class SubscriptionResource implements BaseJaxrsResource {
                 return callback.doResponseOk(operationValue);
             } catch (EntitlementUserApiException e) {
                 log.info(String.format("Failed to complete operation"), e);
-                //throw new WebApplicationException(Response.Status.BAD_REQUEST);
                 return Response.status(Status.BAD_REQUEST).build();
             } catch (InterruptedException e) {
-                //throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);                
                 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
             } catch (TimeoutException e) {
-                //throw new WebApplicationException(Response.Status.fromStatusCode(408));                
                 return Response.status(Status.fromStatusCode(408)).build();   
             } finally {
                 if (waiter != null) {
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java
index 3d340da..bc0b0bd 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java
@@ -50,27 +50,17 @@ public class BlockingEntitlementUserApi implements EntitlementUserApi {
 
     public SubscriptionBundle getBundleFromId(UUID id) throws EntitlementUserApiException {
         SubscriptionBundle bundle = entitlementUserApi.getBundleFromId(id);
-        if(bundle == null) {
-            throw new EntitlementUserApiException(ErrorCode.ENT_GET_INVALID_BUNDLE_ID, id);
-        }
         return new BlockingSubscriptionBundle(bundle, blockingApi);
     }
 
     public Subscription getSubscriptionFromId(UUID id) throws EntitlementUserApiException {
         Subscription subscription = entitlementUserApi.getSubscriptionFromId(id);
-        if(subscription == null) {
-            throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_SUBSCRIPTION_ID, id);
-        }
         return new BlockingSubscription(subscription, blockingApi, checker);
     }
 
     
     public SubscriptionBundle getBundleForKey(String bundleKey) throws EntitlementUserApiException {
         SubscriptionBundle bundle = entitlementUserApi.getBundleForKey(bundleKey);
-        if(bundle == null) {
-            throw new EntitlementUserApiException(ErrorCode.ENT_GET_INVALID_BUNDLE_KEY, bundleKey);
-        }
-
         return new BlockingSubscriptionBundle(bundle, blockingApi);
     }
 
@@ -101,7 +91,7 @@ public class BlockingEntitlementUserApi implements EntitlementUserApi {
         return result;
     }
 
-    public Subscription getBaseSubscription(UUID bundleId) {
+    public Subscription getBaseSubscription(UUID bundleId) throws EntitlementUserApiException {
         return new BlockingSubscription(entitlementUserApi.getBaseSubscription(bundleId), blockingApi, checker);
     }
 
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
index 07dccb8..b1c5558 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
@@ -34,6 +34,7 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
@@ -51,7 +52,8 @@ public class BillCycleDayCalculator {
 		this.entitlementApi = entitlementApi;
 	}
 
-	protected int calculateBcd(SubscriptionBundle bundle, Subscription subscription, final SubscriptionEvent transition, final Account account) throws CatalogApiException, AccountApiException {
+	protected int calculateBcd(SubscriptionBundle bundle, Subscription subscription, final SubscriptionEvent transition, final Account account)
+	throws CatalogApiException, AccountApiException, EntitlementUserApiException {
 
 	    Catalog catalog = catalogService.getFullCatalog();
 		
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
index e8945c5..3f14062 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountUserApi;
@@ -35,6 +36,7 @@ import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
@@ -108,27 +110,22 @@ public class DefaultBillingApi implements BillingApi {
         } catch (AccountApiException e) {
             log.warn("Failed while getting BillingEvent", e);
         }
-
         blockCalculator.insertBlockingEvents(result);
-
         return result;
     }
 
 
     @Override
-    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) {
-        return chargeThruApi.getAccountIdFromSubscriptionId(subscriptionId);
+    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) throws EntitlementBillingApiException {
+        UUID result = chargeThruApi.getAccountIdFromSubscriptionId(subscriptionId);
+        if (result == null) {
+            throw new EntitlementBillingApiException(ErrorCode.ENT_INVALID_SUBSCRIPTION_ID, subscriptionId.toString());
+        }
+        return result;
     }
 
     @Override
     public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context) {
         chargeThruApi.setChargedThroughDate(subscriptionId, ctd, context);
     }
-
-    @Override
-    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
-            DateTime ctd, CallContext context) {
-        chargeThruApi.setChargedThroughDateFromTransaction(transactionalDao, subscriptionId, ctd, context);
-    }
-
 }

overdue/pom.xml 7(+0 -7)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index 1fc7dbf..2182ffc 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -105,13 +105,6 @@
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <groups>fast,slow, stress</groups>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
                 <executions>
                     <execution>
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
index 092911d..8a9ea68 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -22,6 +22,7 @@ import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingApi;
@@ -35,7 +36,7 @@ import com.ning.billing.overdue.service.ExtendedOverdueService;
 import com.ning.billing.overdue.wrapper.OverdueWrapper;
 import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
 
-public class DefaultOverdueUserApi implements OverdueUserApi{
+public class DefaultOverdueUserApi implements OverdueUserApi { 
 
     
     private final OverdueWrapperFactory factory;
@@ -62,7 +63,7 @@ public class DefaultOverdueUserApi implements OverdueUserApi{
     }
     
     @Override
-    public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException {
+    public <T extends Blockable> OverdueState<T> refreshOverdueStateFor(T overdueable) throws OverdueError, CatalogApiException, EntitlementUserApiException {
         OverdueWrapper<T> wrapper = factory.createOverdueWrapperFor(overdueable);
         return wrapper.refresh();
     } 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
index 640ca9a..d47f3f3 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculator.java
@@ -27,6 +27,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.google.inject.Inject;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.junction.api.Blockable;
@@ -56,7 +57,7 @@ public abstract class BillingStateCalculator<T extends Blockable> {
         this.clock = clock;
     }
     
-    public abstract BillingState<T> calculateBillingState(T overdueable);
+    public abstract BillingState<T> calculateBillingState(T overdueable) throws EntitlementUserApiException;
     
     protected DateTime earliest(SortedSet<Invoice> unpaidInvoices) {
         return unpaidInvoices.first().getInvoiceDate();
diff --git a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
index 544420f..89a7cc6 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/calculator/BillingStateCalculatorBundle.java
@@ -29,6 +29,7 @@ import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.invoice.api.Invoice;
@@ -50,7 +51,7 @@ public class BillingStateCalculatorBundle  extends BillingStateCalculator<Subscr
     }
     
     @Override
-    public BillingStateBundle calculateBillingState(SubscriptionBundle bundle) {
+    public BillingStateBundle calculateBillingState(SubscriptionBundle bundle) throws EntitlementUserApiException {
         
         SortedSet<Invoice> unpaidInvoices = unpaidInvoicesForBundle(bundle.getId(), bundle.getAccountId());
  
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
index 892ad05..0223803 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -17,6 +17,7 @@
 package com.ning.billing.overdue.wrapper;
 
 import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingApi;
 import com.ning.billing.overdue.OverdueState;
@@ -48,12 +49,12 @@ public class OverdueWrapper<T extends Blockable> {
         this.overdueStateApplicator = overdueStateApplicator;
     }
 
-    public OverdueState<T> refresh() throws OverdueError, CatalogApiException {
+    public OverdueState<T> refresh() throws OverdueError, CatalogApiException, EntitlementUserApiException {
         OverdueState<T> nextOverdueState;
         BillingState<T> billingState = billingStateCalcuator.calculateBillingState(overdueable);
         String previousOverdueStateName = api.getBlockingStateFor(overdueable).getStateName();
         nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
-        if(!previousOverdueStateName.equals(nextOverdueState.getName())) {
+        if (!previousOverdueStateName.equals(nextOverdueState.getName())) {
             overdueStateApplicator.apply(overdueable, nextOverdueState, nextOverdueState, overdueStateSet.dateOfNextCheck(billingState, clock.getUTCNow())); 
         }
 
diff --git a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
index 3d5b855..bb7ece3 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/calculator/TestBillingStateCalculatorBundle.java
@@ -86,7 +86,8 @@ public class TestBillingStateCalculatorBundle extends TestBillingStateCalculator
     }
     
     @Test(groups = {"fast"}, enabled=true)
-    public void testcalculateBillingStateForBundle() {
+    public void testcalculateBillingStateForBundle() throws Exception {
+        
        UUID thisBundleId = new UUID(0L,0L);
        UUID thatBundleId = new UUID(0L,1L);