killbill-memoizeit

Changes

Details

diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index ba9dc2a..4af7004 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -51,12 +51,6 @@ public class AnalyticsListener {
             case CHANGE:
                 bstRecorder.subscriptionChanged(event);
                 break;
-            case PAUSE:
-                bstRecorder.subscriptionPaused(event);
-                break;
-            case RESUME:
-                bstRecorder.subscriptionResumed(event);
-                break;
             case UNCANCEL:
                 break;
             case PHASE:
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index 6bc4d7a..f476a59 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -19,6 +19,7 @@ package com.ning.billing.analytics;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
@@ -59,18 +60,6 @@ public class MockSubscription implements Subscription
     }
 
     @Override
-    public void pause()
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void resume()
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public UUID getId()
     {
         return ID;
@@ -159,4 +148,10 @@ public class MockSubscription implements Subscription
     public ProductCategory getCategory() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+            throws EntitlementUserApiException {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
index 0c3cf62..79bea58 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -72,32 +72,14 @@ public class TestAnalyticsListener
         Assert.assertEquals(dao.getTransitions(KEY).size(), 1);
         Assert.assertEquals(dao.getTransitions(KEY).get(0), firstBST);
 
-        // Pause it
-        final DateTime effectivePauseTransitionTime = new DateTime(DateTimeZone.UTC);
-        final DateTime requestedPauseTransitionTime = new DateTime(DateTimeZone.UTC);
-        final SubscriptionTransitionData pausedSubscriptionTransition = createPauseSubscriptionTransition(effectivePauseTransitionTime, requestedPauseTransitionTime, firstTransition.getNextState());
-        final BusinessSubscriptionTransition pausedBST = createExpectedPausedBST(pausedSubscriptionTransition.getId(), requestedPauseTransitionTime, effectivePauseTransitionTime, firstBST.getNextSubscription());
-        listener.handleSubscriptionTransitionChange(pausedSubscriptionTransition);
-        Assert.assertEquals(dao.getTransitions(KEY).size(), 2);
-        Assert.assertEquals(dao.getTransitions(KEY).get(1), pausedBST);
-
-        // Un-Pause it
-        final DateTime effectiveResumeTransitionTime = new DateTime(DateTimeZone.UTC);
-        final DateTime requestedResumeTransitionTime = new DateTime(DateTimeZone.UTC);
-        final SubscriptionTransitionData resumedSubscriptionTransition = createResumeSubscriptionTransition(requestedResumeTransitionTime, effectiveResumeTransitionTime, pausedSubscriptionTransition.getNextState());
-        final BusinessSubscriptionTransition resumedBST = createExpectedResumedBST(resumedSubscriptionTransition.getId(), requestedResumeTransitionTime, effectiveResumeTransitionTime, pausedBST.getNextSubscription());
-        listener.handleSubscriptionTransitionChange(resumedSubscriptionTransition);
-        Assert.assertEquals(dao.getTransitions(KEY).size(), 3);
-        Assert.assertEquals(dao.getTransitions(KEY).get(2), resumedBST);
-
         // Cancel it
         final DateTime effectiveCancelTransitionTime = new DateTime(DateTimeZone.UTC);
         final DateTime requestedCancelTransitionTime = new DateTime(DateTimeZone.UTC);
-        final SubscriptionTransitionData cancelledSubscriptionTransition = createCancelSubscriptionTransition(requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedSubscriptionTransition.getNextState());
-        final BusinessSubscriptionTransition cancelledBST = createExpectedCancelledBST(cancelledSubscriptionTransition.getId(), requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedBST.getNextSubscription());
+        final SubscriptionTransitionData cancelledSubscriptionTransition = createCancelSubscriptionTransition(requestedCancelTransitionTime, effectiveCancelTransitionTime, firstTransition.getNextState());
+        final BusinessSubscriptionTransition cancelledBST = createExpectedCancelledBST(cancelledSubscriptionTransition.getId(), requestedCancelTransitionTime, effectiveCancelTransitionTime, firstBST.getNextSubscription());
         listener.handleSubscriptionTransitionChange(cancelledSubscriptionTransition);
-        Assert.assertEquals(dao.getTransitions(KEY).size(), 4);
-        Assert.assertEquals(dao.getTransitions(KEY).get(3), cancelledBST);
+        Assert.assertEquals(dao.getTransitions(KEY).size(), 2);
+        Assert.assertEquals(dao.getTransitions(KEY).get(1), cancelledBST);
     }
 
     private BusinessSubscriptionTransition createExpectedFirstBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime)
@@ -107,20 +89,6 @@ public class TestAnalyticsListener
         return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, null, subscriptionState);
     }
 
-    private BusinessSubscriptionTransition createExpectedPausedBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
-    {
-        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPaused(plan);
-        final Subscription.SubscriptionState subscriptionState = Subscription.SubscriptionState.PAUSED;
-        return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, subscriptionState);
-    }
-
-    private BusinessSubscriptionTransition createExpectedResumedBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
-    {
-        final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionResumed(plan);
-        final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.ACTIVE;
-        return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, nextState);
-    }
-
     private BusinessSubscriptionTransition createExpectedCancelledBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
     {
         final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan);
@@ -180,19 +148,6 @@ public class TestAnalyticsListener
         );
     }
 
-    private SubscriptionTransitionData createPauseSubscriptionTransition(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final Subscription.SubscriptionState previousState)
-    {
-        final ApiEventType eventType = ApiEventType.PAUSE;
-        final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.PAUSED;
-        return createSubscriptionTransition(eventType, requestedTransitionTime, effectiveTransitionTime, previousState, nextState);
-    }
-
-    private SubscriptionTransitionData createResumeSubscriptionTransition(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final Subscription.SubscriptionState previousState)
-    {
-        final ApiEventType eventType = ApiEventType.RESUME;
-        final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.ACTIVE;
-        return createSubscriptionTransition(eventType, requestedTransitionTime, effectiveTransitionTime, previousState, nextState);
-    }
 
     private SubscriptionTransitionData createCancelSubscriptionTransition(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final Subscription.SubscriptionState previousState)
     {
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 0765f30..eafe210 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -19,6 +19,7 @@ package com.ning.billing.entitlement.api.user;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 
 import org.joda.time.DateTime;
@@ -36,18 +37,13 @@ public interface Subscription {
     throws EntitlementUserApiException;
 
     public void changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate)
-        throws EntitlementUserApiException ;
-
-    public void pause()
-        throws EntitlementUserApiException ;
-
-    public void resume()
-        throws EntitlementUserApiException ;
+        throws EntitlementUserApiException;
 
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+        throws EntitlementUserApiException;
 
     public enum SubscriptionState {
         ACTIVE,
-        PAUSED,
         CANCELLED
     }
 
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
index f4c971d..43f96c6 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
@@ -30,8 +30,7 @@ public interface SubscriptionTransition extends BusEvent {
         MIGRATE_ENTITLEMENT,
         CREATE,
         CHANGE,
-        PAUSE,
-        RESUME,
+        RE_CREATE,
         CANCEL,
         UNCANCEL,
         PHASE
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index fdcaa23..340f2cb 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -42,12 +42,16 @@ public enum ErrorCode {
     ENT_CREATE_AO_NOT_AVAILABLE(1019, "Can't create AddOn %s for BasePlan %s (Not available)"),
 
     /* Change plan */
-    ENT_CHANGE_NON_ACTIVE(1021, "Subscription %s is in state %s"),
-    ENT_CHANGE_FUTURE_CANCELLED(1022, "Subscription %s is future cancelled"),
+    ENT_CHANGE_NON_ACTIVE(1021, "Subscription %s is in state %s: Failed to change plan"),
+    ENT_CHANGE_FUTURE_CANCELLED(1022, "Subscription %s is future cancelled: Failed to change plan"),
     /* Cancellation */
-    ENT_CANCEL_BAD_STATE(1031, "Subscription %s is in state %s"),
+    ENT_CANCEL_BAD_STATE(1031, "Subscription %s is in state %s: Failed to cancel"),
+    /* Recreation */
+    ENT_RECREATE_BAD_STATE(1041, "Subscription %s is in state %s: Failed to recreate"),
+
     /* Un-cancellation */
-    ENT_UNCANCEL_BAD_STATE(1070, "Subscription %s was not in a cancelled state"),
+    ENT_UNCANCEL_BAD_STATE(1070, "Subscription %s was not in a cancelled state: Failed to uncancel plan"),
+
     /* Fetch */
     ENT_GET_NO_BUNDLE_FOR_SUBSCRIPTION(1080, "Could not find a bundle for subscription %s"),
     ENT_GET_INVALID_BUNDLE_ID(1081, "Could not find a bundle matching id %s"),
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
index 22065ac..fad00af 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
@@ -286,6 +286,7 @@ public class TestBasic {
         }
     }
 
+
     private void testBasePlanComplete(DateTime initialCreationDate, int billingDay,
                                       boolean proRationExpected) throws Exception {
         long DELAY = 5000;
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBusHandler.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBusHandler.java
index edc38a1..aa6dafd 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBusHandler.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBusHandler.java
@@ -80,16 +80,6 @@ public class TestBusHandler {
             notifyIfStackEmpty();
 
             break;
-        case PAUSE:
-            assertEqualsNicely(NextEvent.PAUSE);
-            notifyIfStackEmpty();
-
-            break;
-        case RESUME:
-            assertEqualsNicely(NextEvent.RESUME);
-            notifyIfStackEmpty();
-
-            break;
         case UNCANCEL:
             assertEqualsNicely(NextEvent.UNCANCEL);
             notifyIfStackEmpty();
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 5bd8596..1f312fd 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
@@ -123,7 +123,13 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
             switch(plan.getProduct().getCategory()) {
             case BASE:
                 if (baseSubscription != null) {
-                    throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_BP_EXISTS, bundleId);
+                    if (baseSubscription.getState() == SubscriptionState.ACTIVE) {
+                        throw new EntitlementUserApiException(ErrorCode.ENT_CREATE_BP_EXISTS, bundleId);
+                    } else {
+                        // If we do create on an existing CANCELLED BP, this is equivalent to call recreate on that Subscription.
+                        baseSubscription.recreate(spec, requestedDate);
+                        return baseSubscription;
+                    }
                 }
                 bundleStartDate = requestedDate;
                 break;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index 9a82a99..eb1f26d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -28,6 +28,7 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEventData;
 import com.ning.billing.entitlement.events.user.*;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.DefaultClock;
 import org.joda.time.DateTime;
@@ -56,10 +57,46 @@ public class SubscriptionApiService {
             String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate)
         throws EntitlementUserApiException {
 
+        SubscriptionData subscription = new SubscriptionData(builder, this, clock);
+        createFromSubscription(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate, processedDate, false);
+        return subscription;
+    }
+
+    public void recreatePlan(SubscriptionData subscription, PlanPhaseSpecifier spec, DateTime requestedDate)
+        throws EntitlementUserApiException {
+
+        SubscriptionState currentState = subscription.getState();
+        if (currentState != SubscriptionState.CANCELLED) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_RECREATE_BAD_STATE, subscription.getId(), currentState);
+        }
+        DateTime now = clock.getUTCNow();
+        requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
+        validateRequestedDate(subscription, now, requestedDate);
+
         try {
+            String realPriceList = (spec.getPriceListName() == null) ? PriceListSet.DEFAULT_PRICELIST_NAME : spec.getPriceListName();
+            Plan plan = catalogService.getFullCatalog().findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, requestedDate);
+            PlanPhase phase = plan.getAllPhases()[0];
+            if (phase == null) {
+                throw new EntitlementError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog",
+                        spec.getProductName(), spec.getBillingPeriod().toString(), realPriceList));
+            }
+
+            DateTime effectiveDate = requestedDate;
+            DateTime processedDate = now;
+
+            createFromSubscription(subscription, plan, spec.getPhaseType(), realPriceList, requestedDate, effectiveDate, processedDate, true);
+        } catch (CatalogApiException e) {
+            throw new EntitlementUserApiException(e);
+        }
+    }
 
-            SubscriptionData subscription = new SubscriptionData(builder, this, clock);
 
+    private void createFromSubscription(SubscriptionData subscription, Plan plan, PhaseType initialPhase,
+            String realPriceList, DateTime requestedDate, DateTime effectiveDate, DateTime processedDate, boolean reCreate)
+        throws EntitlementUserApiException {
+
+        try {
             TimedPhase [] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate);
             ApiEventCreate creationEvent = new ApiEventCreate(new ApiEventBuilder()
             .setSubscriptionId(subscription.getId())
@@ -81,14 +118,20 @@ public class SubscriptionApiService {
             if (nextPhaseEvent != null) {
                 events.add(nextPhaseEvent);
             }
-            dao.createSubscription(subscription, events);
+            if (reCreate) {
+                dao.recreateSubscription(subscription.getId(), events);
+            } else {
+                dao.createSubscription(subscription, events);
+            }
             subscription.rebuildTransitions(events, catalogService.getFullCatalog());
-            return subscription;
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
         }
     }
 
+
+
+
     public void cancel(SubscriptionData subscription, DateTime requestedDate, boolean eot)
         throws EntitlementUserApiException {
 
@@ -100,7 +143,7 @@ public class SubscriptionApiService {
 
             DateTime now = clock.getUTCNow();
             requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
-            validateRequestedDateOnChangeOrCancel(subscription, now, requestedDate);
+            validateRequestedDate(subscription, now, requestedDate);
 
             Plan currentPlan = subscription.getCurrentPlan();
             PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
@@ -130,7 +173,7 @@ public class SubscriptionApiService {
 
 
     public void uncancel(SubscriptionData subscription)
-    throws EntitlementUserApiException {
+        throws EntitlementUserApiException {
 
         if (!subscription.isSubscriptionFutureCancelled()) {
             throw new EntitlementUserApiException(ErrorCode.ENT_UNCANCEL_BAD_STATE, subscription.getId().toString());
@@ -168,7 +211,7 @@ public class SubscriptionApiService {
 
             DateTime now = clock.getUTCNow();
             requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
-            validateRequestedDateOnChangeOrCancel(subscription, now, requestedDate);
+            validateRequestedDate(subscription, now, requestedDate);
 
             String currentPriceList = subscription.getCurrentPriceList();
 
@@ -235,7 +278,7 @@ public class SubscriptionApiService {
         }
     }
 
-    private void validateRequestedDateOnChangeOrCancel(SubscriptionData subscription, DateTime now, DateTime requestedDate)
+    private void validateRequestedDate(SubscriptionData subscription, DateTime now, DateTime requestedDate)
         throws EntitlementUserApiException {
 
         if (requestedDate.isAfter(now) ) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index ce341fd..178c4d5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -16,9 +16,14 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.*;
-import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
@@ -152,13 +157,9 @@ public class SubscriptionData implements Subscription {
     }
 
     @Override
-    public void pause() throws EntitlementUserApiException {
-        throw new EntitlementUserApiException(ErrorCode.NOT_IMPLEMENTED);
-    }
-
-    @Override
-    public void resume() throws EntitlementUserApiException  {
-        throw new EntitlementUserApiException(ErrorCode.NOT_IMPLEMENTED);
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+            throws EntitlementUserApiException {
+        apiService.recreatePlan(this, spec, requestedDate);
     }
 
     @Override
@@ -185,7 +186,7 @@ public class SubscriptionData implements Subscription {
         List<SubscriptionTransition> result = new ArrayList<SubscriptionTransition>();
         for (SubscriptionTransition cur : transitions) {
             result.add(cur);
-               }
+        }
         return result;
     }
 
@@ -270,7 +271,8 @@ public class SubscriptionData implements Subscription {
                 continue;
             }
             if (cur.getEventType() == EventType.API_USER &&
-                    cur.getApiEventType() == ApiEventType.CHANGE) {
+                    (cur.getApiEventType() == ApiEventType.CHANGE ||
+                            cur.getApiEventType() == ApiEventType.RE_CREATE)) {
                 return cur;
             }
         }
@@ -325,11 +327,12 @@ public class SubscriptionData implements Subscription {
                 continue;
             }
             if (cur.getEventType() == EventType.PHASE
-                    || (cur.getEventType() == EventType.API_USER && cur.getApiEventType() == ApiEventType.CHANGE)) {
+                    || (cur.getEventType() == EventType.API_USER &&
+                            (cur.getApiEventType() == ApiEventType.CHANGE ||
+                                    cur.getApiEventType() == ApiEventType.RE_CREATE))) {
                 return cur.getEffectiveTransitionTime();
             }
         }
-
         // CREATE event
         return transitions.get(0).getEffectiveTransitionTime();
     }
@@ -378,6 +381,7 @@ public class SubscriptionData implements Subscription {
                 switch(apiEventType) {
                 case MIGRATE_ENTITLEMENT:
                 case CREATE:
+                case RE_CREATE:
                     nextState = SubscriptionState.ACTIVE;
                     nextPlanName = userEV.getEventPlan();
                     nextPhaseName = userEV.getEventPlanPhase();
@@ -388,12 +392,6 @@ public class SubscriptionData implements Subscription {
                     nextPhaseName = userEV.getEventPlanPhase();
                     nextPriceList = userEV.getPriceList();
                     break;
-                case PAUSE:
-                    nextState = SubscriptionState.PAUSED;
-                    break;
-                case RESUME:
-                    nextState = SubscriptionState.ACTIVE;
-                    break;
                 case CANCEL:
                     nextState = SubscriptionState.CANCELLED;
                     nextPlanName = null;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 5a04a47..d7d6b94 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -67,6 +67,8 @@ public interface EntitlementDao {
     // Subscription creation, cancellation, changePlan apis
     public void createSubscription(SubscriptionData subscription, List<EntitlementEvent> initialEvents);
 
+    public void recreateSubscription(UUID subscriptionId, List<EntitlementEvent> recreateEvents);
+
     public void cancelSubscription(UUID subscriptionId, EntitlementEvent cancelEvent);
 
     public void uncancelSubscription(UUID subscriptionId, List<EntitlementEvent> uncancelEvents);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
index ef3168f..15654d8 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
@@ -244,6 +244,31 @@ public class EntitlementSqlDao implements EntitlementDao {
     }
 
     @Override
+    public void recreateSubscription(final UUID subscriptionId,
+            final List<EntitlementEvent> recreateEvents) {
+
+        eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
+            @Override
+            public Void inTransaction(EventSqlDao dao,
+                    TransactionStatus status) throws Exception {
+
+                for (final EntitlementEvent cur : recreateEvents) {
+                    dao.insertEvent(cur);
+                    recordFutureNotificationFromTransaction(dao,
+                            cur.getEffectiveDate(),
+                            new NotificationKey() {
+                        @Override
+                        public String toString() {
+                            return cur.getId().toString();
+                        }
+                    });
+                }
+                return null;
+            }
+        });
+    }
+
+    @Override
     public void cancelSubscription(final UUID subscriptionId, final EntitlementEvent cancelEvent) {
 
         eventsDao.inTransaction(new Transaction<Void, EventSqlDao>() {
@@ -549,4 +574,5 @@ public class EntitlementSqlDao implements EntitlementDao {
             throw new RuntimeException(e);
         }
     }
+
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
index 4e2128e..67c60c0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
@@ -144,16 +144,16 @@ public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transm
 
                 if (userType == ApiEventType.CREATE) {
                     result = new ApiEventCreate(builder);
+                } else if (userType == ApiEventType.RE_CREATE) {
+                    result = new ApiEventReCreate(builder);
                 } else if (userType == ApiEventType.MIGRATE_ENTITLEMENT) {
                     result = new ApiEventMigrate(builder);
                 } else if (userType == ApiEventType.CHANGE) {
                     result = new ApiEventChange(builder);
                 } else if (userType == ApiEventType.CANCEL) {
                     result = new ApiEventCancel(builder);
-                } else if (userType == ApiEventType.PAUSE) {
-                    result = new ApiEventPause(builder);
-                } else if (userType == ApiEventType.RESUME) {
-                    result = new ApiEventResume(builder);
+                } else if (userType == ApiEventType.RE_CREATE) {
+                    result = new ApiEventReCreate(builder);
                 } else if (userType == ApiEventType.UNCANCEL) {
                     result = new ApiEventUncancel(builder);
                 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
index b994899..ec56655 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventType.java
@@ -32,13 +32,9 @@ public enum ApiEventType {
         @Override
         public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.CHANGE; }
     },
-    PAUSE {
+    RE_CREATE {
         @Override
-        public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.PAUSE; }
-    },
-    RESUME {
-        @Override
-        public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.RESUME; }
+        public SubscriptionTransitionType getSubscriptionTransitionType() { return SubscriptionTransitionType.RE_CREATE; }
     },
     CANCEL {
         @Override
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
index 39f6c48..5e8e1ef 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
@@ -38,10 +38,9 @@ public class ApiTestListener {
     public enum NextEvent {
         MIGRATE_ENTITLEMENT,
         CREATE,
+        RE_CREATE,
         CHANGE,
         CANCEL,
-        PAUSE,
-        RESUME,
         PHASE
     }
 
@@ -59,18 +58,15 @@ public class ApiTestListener {
         case CREATE:
             subscriptionCreated(event);
             break;
+        case RE_CREATE:
+            subscriptionReCreated(event);
+            break;
         case CANCEL:
             subscriptionCancelled(event);
             break;
         case CHANGE:
             subscriptionChanged(event);
             break;
-        case PAUSE:
-            subscriptionPaused(event);
-            break;
-        case RESUME:
-            subscriptionResumed(event);
-            break;
         case UNCANCEL:
             break;
         case PHASE:
@@ -151,6 +147,12 @@ public class ApiTestListener {
         notifyIfStackEmpty();
     }
 
+    public void subscriptionReCreated(SubscriptionTransition recreated) {
+        log.debug("-> Got event RE_CREATED");
+        assertEqualsNicely(NextEvent.RE_CREATE);
+        notifyIfStackEmpty();
+    }
+
 
     public void subscriptionCancelled(SubscriptionTransition cancelled) {
         log.debug("-> Got event CANCEL");
@@ -166,20 +168,6 @@ public class ApiTestListener {
     }
 
 
-    public void subscriptionPaused(SubscriptionTransition paused) {
-        log.debug("-> Got event PAUSE");
-        assertEqualsNicely(NextEvent.PAUSE);
-        notifyIfStackEmpty();
-    }
-
-
-    public void subscriptionResumed(SubscriptionTransition resumed) {
-        log.debug("-> Got event RESUME");
-        assertEqualsNicely(NextEvent.RESUME);
-        notifyIfStackEmpty();
-    }
-
-
     public void subscriptionPhaseChanged(
             SubscriptionTransition phaseChanged) {
         log.debug("-> Got event PHASE");
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java
index 4d57dac..5f8788c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java
@@ -139,4 +139,9 @@ class BrainDeadMockEntitlementDao implements EntitlementDao {
     public EntitlementEvent getEventById(final UUID eventId) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void recreateSubscription(UUID subscriptionId,
+            List<EntitlementEvent> recreateEvents) {
+    }
 }
\ No newline at end of file
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
index fab66dd..3fd0ac2 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
@@ -24,6 +24,7 @@ import org.joda.time.DateTime;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
@@ -52,19 +53,6 @@ public class BrainDeadSubscription implements Subscription {
 	}
 
 	@Override
-	public void pause() throws EntitlementUserApiException {
-		throw new UnsupportedOperationException();
-
-
-	}
-
-	@Override
-	public void resume() throws EntitlementUserApiException {
-		throw new UnsupportedOperationException();
-
-	}
-
-	@Override
 	public UUID getId() {
 		throw new UnsupportedOperationException();
 
@@ -151,4 +139,10 @@ public class BrainDeadSubscription implements Subscription {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+            throws EntitlementUserApiException {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index d5546d7..ee8490b 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -40,7 +40,8 @@ import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.util.clock.DefaultClock;
 
 public abstract class TestUserApiCreate extends TestApiBase {
-	Logger log = LoggerFactory.getLogger(TestUserApiCreate.class);
+
+    private static Logger log = LoggerFactory.getLogger(TestUserApiCreate.class);
 
     public void testCreateWithRequestedDate() {
         log.info("Starting testCreateWithRequestedDate");
@@ -75,6 +76,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
         }
     }
 
+
     protected void testCreateWithInitialPhase() {
         log.info("Starting testCreateWithInitialPhase");
         try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
index f4474f9..3adf86e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
@@ -36,21 +36,25 @@ public class TestUserApiCreateMemory extends TestUserApiCreate {
         super.testCreateWithRequestedDate();
     }
 
+    @Override
     @Test(enabled=true, groups={"fast"})
     public void testCreateWithInitialPhase() {
         super.testSimpleSubscriptionThroughPhases();
     }
 
+    @Override
     @Test(enabled=true, groups={"fast"})
     public void testSimpleCreateSubscription() {
         super.testSimpleCreateSubscription();
     }
 
+    @Override
     @Test(enabled=true, groups={"fast"})
     protected void testSimpleSubscriptionThroughPhases() {
         super.testSimpleSubscriptionThroughPhases();
     }
 
+    @Override
     @Test(enabled=false, groups={"fast"})
     protected void testSubscriptionWithAddOn() {
         super.testSubscriptionWithAddOn();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index 81ee501..7442298 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -85,6 +85,22 @@ public class TestUserApiError extends TestApiBase {
     }
 
     @Test(enabled=true, groups={"fast"})
+    public void testRecreateSubscriptionBPNotCancelled() {
+        try {
+            SubscriptionData subscription = createSubscription("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME);
+            try {
+                subscription.recreate(getProductSpecifier("Pistol", PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, null), clock.getUTCNow());
+                Assert.assertFalse(true);
+            } catch (EntitlementUserApiException e) {
+                assertEquals(e.getCode(), ErrorCode.ENT_RECREATE_BAD_STATE.getCode());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            Assert.assertFalse(true);
+        }
+    }
+
+    @Test(enabled=true, groups={"fast"})
     public void testCreateSubscriptionAddOnNotAvailable() {
         try {
             UUID accountId = UUID.randomUUID();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
new file mode 100644
index 0000000..092e1ec
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreate.java
@@ -0,0 +1,118 @@
+/*
+ * 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.entitlement.api.user;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+
+import com.google.inject.Injector;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.entitlement.api.TestApiBase;
+import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+
+public abstract class TestUserApiRecreate extends TestApiBase {
+
+    private static Logger log = LoggerFactory.getLogger(TestUserApiRecreate.class);
+
+
+    protected void testRecreateWithBPCanceledThroughSubscription() {
+        log.info("Starting testRecreateWithBPCanceled");
+        try {
+            testCreateAndRecreate(false);
+        } catch (EntitlementUserApiException e) {
+            log.error("Unexpected exception",e);
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    protected void testCreateWithBPCanceledFromUserApi() {
+        log.info("Starting testCreateWithBPCanceled");
+        try {
+            testCreateAndRecreate(true);
+        } catch (EntitlementUserApiException e) {
+            log.error("Unexpected exception",e);
+            Assert.fail(e.getMessage());
+        }
+    }
+
+
+    private SubscriptionData testCreateAndRecreate(boolean fromUserAPi) throws EntitlementUserApiException {
+
+        DateTime init = clock.getUTCNow();
+        DateTime requestedDate = init.minusYears(1);
+
+        String productName = "Shotgun";
+        BillingPeriod term = BillingPeriod.MONTHLY;
+        String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+
+        testListener.pushExpectedEvent(NextEvent.PHASE);
+        testListener.pushExpectedEvent(NextEvent.CREATE);
+        SubscriptionData subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+                getProductSpecifier(productName, planSetName, term, null), requestedDate);
+        assertNotNull(subscription);
+        assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
+        assertEquals(subscription.getBundleId(), bundle.getId());
+        assertEquals(subscription.getStartDate(), requestedDate);
+        assertEquals(productName, subscription.getCurrentPlan().getProduct().getName());
+
+        assertTrue(testListener.isCompleted(5000));
+
+        // CREATE (AGAIN) WITH NEW PRODUCT
+        productName = "Pistol";
+        term = BillingPeriod.MONTHLY;
+        planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+        try {
+
+            if (fromUserAPi) {
+                subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+                        getProductSpecifier(productName, planSetName, term, null), requestedDate);
+            } else {
+                subscription.recreate(getProductSpecifier(productName, planSetName, term, null), requestedDate);
+            }
+            Assert.fail("Expected Create API to fail since BP already exists");
+        } catch (EntitlementUserApiException e) {
+            assertTrue(true);
+        }
+
+        // NOW CANCEL ADN THIS SHOULD WORK
+        testListener.pushExpectedEvent(NextEvent.CANCEL);
+        subscription.cancel(null, false);
+
+        testListener.pushExpectedEvent(NextEvent.PHASE);
+        testListener.pushExpectedEvent(NextEvent.CREATE);
+
+        if (fromUserAPi) {
+            subscription = (SubscriptionData) entitlementApi.createSubscription(bundle.getId(),
+                    getProductSpecifier(productName, planSetName, term, null), requestedDate);
+        } else {
+            subscription.recreate(getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow());
+        }
+        assertEquals(subscription.getActiveVersion(), SubscriptionEvents.INITIAL_VERSION);
+        assertEquals(subscription.getBundleId(), bundle.getId());
+        assertEquals(subscription.getStartDate(), requestedDate);
+        assertEquals(productName, subscription.getCurrentPlan().getProduct().getName());
+
+        return subscription;
+    }
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreateSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreateSql.java
new file mode 100644
index 0000000..2c1db68
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiRecreateSql.java
@@ -0,0 +1,44 @@
+/*
+ * 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.entitlement.api.user;
+
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+
+public class TestUserApiRecreateSql extends TestUserApiRecreate {
+
+    @Override
+    protected Injector getInjector() {
+        return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
+    }
+
+    @Override
+    @Test(enabled=true, groups={"slow"})
+    protected void testRecreateWithBPCanceledThroughSubscription() {
+        super.testRecreateWithBPCanceledThroughSubscription();
+    }
+
+    @Override
+    @Test(enabled=true, groups={"slow"})
+    protected void testCreateWithBPCanceledFromUserApi() {
+        super.testRecreateWithBPCanceledThroughSubscription();
+    }
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
index 6395470..fac7d62 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
@@ -169,6 +169,23 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
     }
 
     @Override
+    public void recreateSubscription(final UUID subscriptionId,
+            final List<EntitlementEvent> recreateEvents) {
+
+        synchronized(events) {
+            events.addAll(recreateEvents);
+            for (final EntitlementEvent cur : recreateEvents) {
+                recordFutureNotificationFromTransaction(null, cur.getEffectiveDate(), new NotificationKey() {
+                    @Override
+                    public String toString() {
+                        return cur.getId().toString();
+                    }
+                });
+            }
+        }
+    }
+
+    @Override
     public List<Subscription> getSubscriptions(final UUID bundleId) {
 
         List<Subscription> results = new ArrayList<Subscription>();
@@ -429,4 +446,5 @@ public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlement
             throw new RuntimeException(e);
         }
     }
+
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
index c0b054a..4cf1380 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
@@ -19,6 +19,7 @@ package com.ning.billing.invoice.dao;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
@@ -47,16 +48,6 @@ public class MockSubscription implements Subscription {
     }
 
     @Override
-    public void pause() throws EntitlementUserApiException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void resume() throws EntitlementUserApiException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public UUID getId() {
         return subscriptionId;
     }
@@ -130,4 +121,10 @@ public class MockSubscription implements Subscription {
     public ProductCategory getCategory() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+            throws EntitlementUserApiException {
+        throw new UnsupportedOperationException();
+    }
 }
\ No newline at end of file
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/BrainDeadSubscription.java b/invoice/src/test/java/com/ning/billing/invoice/notification/BrainDeadSubscription.java
index 05d7c79..dc06929 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/BrainDeadSubscription.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/BrainDeadSubscription.java
@@ -24,6 +24,7 @@ import org.joda.time.DateTime;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
@@ -47,21 +48,6 @@ public class BrainDeadSubscription implements Subscription {
 			String planSet, DateTime requestedDate)
 			throws EntitlementUserApiException {
 		throw new UnsupportedOperationException();
-
-
-	}
-
-	@Override
-	public void pause() throws EntitlementUserApiException {
-		throw new UnsupportedOperationException();
-
-
-	}
-
-	@Override
-	public void resume() throws EntitlementUserApiException {
-		throw new UnsupportedOperationException();
-
 	}
 
 	@Override
@@ -152,4 +138,9 @@ public class BrainDeadSubscription implements Subscription {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public void recreate(PlanPhaseSpecifier spec, DateTime requestedDate)
+            throws EntitlementUserApiException {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
index 67c27fa..f6c1063 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
@@ -73,7 +73,7 @@ public class TestNextBillingDateNotifier {
 	private DummySqlTest dao;
 	private Bus eventBus;
 	private MysqlTestingHelper helper;
-	private InvoiceListenerMock listener = new InvoiceListenerMock();
+	private final InvoiceListenerMock listener = new InvoiceListenerMock();
 	private NotificationQueueService notificationQueueService;
 
 	private static final class InvoiceListenerMock extends InvoiceListener {
@@ -83,7 +83,7 @@ public class TestNextBillingDateNotifier {
 		public InvoiceListenerMock() {
 			super(null);
 		}
-		
+
 
 		@Override
 		public void handleNextBillingDateEvent(UUID subscriptionId,
@@ -91,17 +91,17 @@ public class TestNextBillingDateNotifier {
 			eventCount++;
 			latestSubscriptionId=subscriptionId;
 		}
-		
+
 		public int getEventCount() {
 			return eventCount;
 		}
-		
+
 		public UUID getLatestSubscriptionId(){
 			return latestSubscriptionId;
 		}
-		
+
 	}
-	
+
 	private class MockEntitlementDao implements EntitlementDao {
 
 		@Override
@@ -123,7 +123,7 @@ public class TestNextBillingDateNotifier {
 		@Override
 		public SubscriptionBundle createSubscriptionBundle(
 				SubscriptionBundleData bundle) {
-			throw new UnsupportedOperationException();
+            throw new UnsupportedOperationException();
 
 		}
 
@@ -205,7 +205,7 @@ public class TestNextBillingDateNotifier {
 		public void uncancelSubscription(UUID subscriptionId,
 				List<EntitlementEvent> uncancelEvents) {
 			throw new UnsupportedOperationException();
-	
+
 		}
 
 		@Override
@@ -223,14 +223,21 @@ public class TestNextBillingDateNotifier {
 		public void undoMigration(UUID accountId) {
 			throw new UnsupportedOperationException();
 		}
-		
+
+        @Override
+        public void recreateSubscription(UUID subscriptionId,
+                List<EntitlementEvent> recreateEvents) {
+            throw new UnsupportedOperationException();
+        }
+
 	}
-	
+
 	@BeforeClass(groups={"setup"})
 	public void setup() throws ServiceException, IOException, ClassNotFoundException, SQLException {
 		//TestApiBase.loadSystemPropertiesFromClasspath("/entitlement.properties");
         final Injector g = Guice.createInjector(Stage.PRODUCTION,  new AbstractModule() {
-			protected void configure() {
+			@Override
+            protected void configure() {
 				 bind(Clock.class).to(ClockMock.class).asEagerSingleton();
 				 bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
 				 bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
@@ -273,12 +280,12 @@ public class TestNextBillingDateNotifier {
 		final UUID subscriptionId = new UUID(0L,1L);
 		final DateTime now = new DateTime();
 		final DateTime readyTime = now.plusMillis(2000);
-		final NextBillingDatePoster poster = new DefaultNextBillingDatePoster(notificationQueueService); 
+		final NextBillingDatePoster poster = new DefaultNextBillingDatePoster(notificationQueueService);
 
 		eventBus.start();
 		notifier.initialize();
 		notifier.start();
-		
+
 
 		dao.inTransaction(new Transaction<Void, DummySqlTest>() {
 			@Override
@@ -289,8 +296,8 @@ public class TestNextBillingDateNotifier {
 				return null;
 			}
 		});
-		
-		
+
+
 		// Move time in the future after the notification effectiveDate
 		((ClockMock) clock).setDeltaFromReality(3000);